From 86f6a31e4b41acb71ba37f3838a9ce75f7743330 Mon Sep 17 00:00:00 2001
From: mdw <mdw>
Date: Sun, 3 Feb 2002 20:49:03 +0000
Subject: [PATCH] Checkin for new build system.

---
 .cvsignore   |   21 +
 .links       |    5 +
 .skelrc      |    9 +
 Makefile.m4  |   92 +
 at.dtx       |  753 ++++++++
 cmtt.dtx     |  523 ++++++
 configure.in |   57 +
 crypto.dtx   |  461 +++++
 doafter.dtx  |  519 ++++++
 doafter.tex  |  113 ++
 exercise.dtx |  555 ++++++
 footnote.dtx |  702 ++++++++
 mdwlist.dtx  |  759 ++++++++
 mdwmath.dtx  | 1224 +++++++++++++
 mdwtab.dtx   | 5525 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 mdwthm.dtx   |  303 ++++
 mdwtools.ins |   87 +
 mdwtools.tex | 1215 +++++++++++++
 poetry.dtx   | 1242 +++++++++++++
 sverb.dtx    | 1189 +++++++++++++
 syntax.dtx   | 2940 +++++++++++++++++++++++++++++++
 21 files changed, 18294 insertions(+)
 create mode 100644 .cvsignore
 create mode 100644 .links
 create mode 100644 .skelrc
 create mode 100644 Makefile.m4
 create mode 100644 at.dtx
 create mode 100644 cmtt.dtx
 create mode 100644 configure.in
 create mode 100644 crypto.dtx
 create mode 100644 doafter.dtx
 create mode 100644 doafter.tex
 create mode 100644 exercise.dtx
 create mode 100644 footnote.dtx
 create mode 100644 mdwlist.dtx
 create mode 100644 mdwmath.dtx
 create mode 100644 mdwtab.dtx
 create mode 100644 mdwthm.dtx
 create mode 100644 mdwtools.ins
 create mode 100644 mdwtools.tex
 create mode 100644 poetry.dtx
 create mode 100644 sverb.dtx
 create mode 100644 syntax.dtx

diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..e0ed709
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,21 @@
+*.ans
+*.aux
+*.def
+*.dvi
+*.fd
+*.idx
+*.ilg
+*.ind
+*.log
+*.lot
+*.sty
+*.thm
+*.tmp
+*.toc
+Makefile
+Makefile.am
+Makefile.in
+aclocal.m4
+config.cache
+config.status
+configure
diff --git a/.links b/.links
new file mode 100644
index 0000000..b091697
--- /dev/null
+++ b/.links
@@ -0,0 +1,5 @@
+missing
+mkinstalldirs
+install-sh
+COPYING
+gpl.tex
diff --git a/.skelrc b/.skelrc
new file mode 100644
index 0000000..efff991
--- /dev/null
+++ b/.skelrc
@@ -0,0 +1,9 @@
+;;; -*-emacs-lisp-*-
+
+(setq skel-alist
+      (append
+       '((author . "Mark Wooding")
+	 (full-title . "the mdwtools LaTeX package collection")
+	 (Program . "mdwtools")
+	 (program . "mdwtools"))
+       skel-alist))
diff --git a/Makefile.m4 b/Makefile.m4
new file mode 100644
index 0000000..380b5a0
--- /dev/null
+++ b/Makefile.m4
@@ -0,0 +1,92 @@
+## -*-makefile-*-
+##
+## $Id: Makefile.m4,v 1.1 2002/02/03 20:49:02 mdw Exp $
+##
+## Build system for mdwtools
+##
+## (c) 2002 Mark Wooding
+##
+
+##----- Licensing notice ----------------------------------------------------
+##
+## This file is part of the mdwtools LaTeX package collection.
+##
+## mdwtools is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+## 
+## mdwtools is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+## 
+## You should have received a copy of the GNU General Public License
+## along with mdwtools; if not, write to the Free Software Foundation,
+## Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+##----- Revision history ----------------------------------------------------
+##
+## $Log: Makefile.m4,v $
+## Revision 1.1  2002/02/03 20:49:02  mdw
+## Checkin for new build system.
+##
+
+AUTOMAKE_OPTIONS = foreign
+
+texmfdir = @texmfdir@
+pkglatexdir = ${texmfdir}/tex/latex/${PACKAGE}
+pkgdocdir = ${texmfdir}/doc/latex/${PACKAGE}
+
+define(`addsuffix', `patsubst(`$1', `\>', `.$2')')
+define(`BASE', `\
+	at cmtt crypto doafter exercise footnote \
+	mdwlist mdwmath mdwtab mdwthm poetry sverb syntax')
+
+SRC = addsuffix(BASE, `dtx')
+DVI = addsuffix(BASE, `dvi') mdwtools.dvi
+OBJ = \
+	at.sty \
+	cmtt.sty mTTcmtt.fd mTTenc.def \
+	crypto.sty \
+	doafter.sty \
+	doafter.tex \
+	exercise.sty \
+	footnote.sty \
+	mdwlist.sty \
+	mdwmath.sty \
+	mdwtab.sty mathenv.sty \
+	mdwthm.sty mdwmargin.thm \
+	poetry.sty \
+	sverb.sty \
+	syntax.sty
+
+pkglatex_DATA = $(OBJ)
+pkgdoc_DATA = $(DVI)
+
+SUFFIXES = .dtx .tex .dvi
+define(`run_latex', `latex "\def\indexing{n} \nonstopmode \input $<"
+	latex "\def\indexing{y} \nonstopmode \input $<"
+	makeindex -s gind.ist $`'*.idx
+	latex "\def\indexing{n} \nonstopmode \input $<"')
+
+.dtx.dvi: gpl.tex mdwtools.tex
+	run_latex
+.tex.dvi: gpl.tex
+	run_latex
+
+all: $(OBJ)
+dvi: $(DVI)
+
+$(OBJ): $(SRC) mdwtools.ins
+	tex mdwtools.ins
+
+MAINTAINERCLEANFILES = $(OBJ) $(DVI)
+CLEANFILES = *.tmp *.aux *.idx *.ilg *.log *.toc *.ind *.lot *.ans
+
+Makefile.am: Makefile.m4
+	cd $(srcdir) && m4 Makefile.m4 >Makefile.am
+
+.PHONY: dvi
+
+##----- That's all, folks ---------------------------------------------------
diff --git a/at.dtx b/at.dtx
new file mode 100644
index 0000000..753a475
--- /dev/null
+++ b/at.dtx
@@ -0,0 +1,753 @@
+% \begin{meta-comment}
+%
+% $Id: at.dtx,v 1.1 2002/02/03 20:49:02 mdw Exp $
+%
+% Allow @-commands
+%
+% (c) 1995 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: at.dtx,v $
+% Revision 1.1  2002/02/03 20:49:02  mdw
+% Checkin for new build system.
+%
+% Revision 1.3  1996/11/19 20:46:55  mdw
+% Entered into RCS
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% at package -- support for `@' commands'
+%% Copyright (c) 1996 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preamble>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{at}
+%<+package>                [1996/05/02 1.3 @-command support (MDW)]
+% \end{meta-comment}
+%
+% \CheckSum{355}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment} <driver>
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{at}
+\aton
+\atlet p=\package
+\atdef at{\package{at}}
+\atdef={\mbox{-}}
+\atdef-{@@@=}
+\atlet.=\syntax
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+% \section{User guide}
+%
+% The @at\ package is an attempt to remove a lot of tedious typing that
+% ends up in \LaTeX\ documents, by expanding the number of short command
+% names available.  The new command names begin with the `|@|' character,
+% rather than the conventional `|\|', so you can tell them apart.
+%
+% The package provides some general commands for defining @-commands, and
+% then uses them to define some fairly simple ones which will be useful to
+% most people.
+%
+% The rules for @-command names aren't terribly complex:
+% \begin{itemize}
+% \item If the first character of the name is a letter, then the command name
+%       consists of all characters up to, but not including, the first
+%       nonletter.  Spaces following the command name are ignored.
+% \item If the first character of the name is a backslash, then the @-command
+%       name consists of the control sequence introduced by the backslash.
+% \item Otherwise, the command name consists only of that first character.
+%       Spaces following the name are not ignored, unless that character
+%       was itself a space character.
+% \end{itemize}
+%
+% Usually, digits are not considered to be letters.  However, the
+% \package{at} package will consider digits to be letters if you give it the
+% \textsf{digits} option in the |\usepackage| command.  (Note that this
+% only affects the \package{at} package; it won't change the characters
+% allowed in normal command names.)
+%
+% \DescribeMacro{\atallowdigits}
+% \DescribeMacro{\atdisallowdigits}
+% You can enable and disable digits being considered as letters dynamically.
+% The |\atallowdigits| command allows digits to be used as letters;
+% |\atdisallowdigits| prevents this.  Both declarations follow \LaTeX's
+% usual scoping rules.  Both of these commands have corresponding
+% environments with the same names (without the leading `|\|', obviously).
+%
+% \subsection{Defining @-commands}
+%
+% \DescribeMacro{\newatcommand}
+% \DescribeMacro{\renewatcommand}
+% The |\newatcommand| command will define a new @-command using a syntax
+% similar to |\newcommand|.  For example, you could define
+% \begin{listing}
+%\newatcommand c[1]{\chapter{#1}}
+% \end{listing}
+% to make @.{"@c{"<name>"}"} equivalent to @.{"\\chapter{"<name>"}"}.
+%
+% A |\renewatcommand| is also provided to redefine existing commands, should
+% the need arise.
+%
+% \DescribeMacro{\atdef}
+% For \TeX\ hackers, the |\atdef| command defines @-commands using a syntax
+% similar to \TeX's built-in |\def|.  
+%
+% As an example, the following command makes @.{"@/"<text>"/"} write its
+% argument \<text> in italics:
+% \begin{listing}
+%\atdef/#1/{\textit{#1}}
+% \end{listing}
+% The real implementation of the |@/|\dots|/| command is a bit more
+% complex, and is given in the next section.
+%
+% You can use all of \TeX's features for defining the syntax of your
+% command.  (See chapter~20 of @/The \TeX book/ for more details.)
+%
+% \DescribeMacro{\atlet}
+% Since |\atdef| is provided to behave similarly to |\def|, @at\ provides
+% |\atlet| which works similarly to |\let|.  For example you can say
+% \begin{listing}
+%\atlet!=\index
+% \end{listing}
+% to allow the short |@!| to behave exactly like |\index|.
+%
+% Note that all commands defined using these commands are robust even if you
+% use fragile commands in their definitions.  Unless you start doing very
+% strange things, @-commands never need |\protect|ing.
+%
+% \subsection{Predefined @-commands}
+%
+% A small number of hopefully useful commands are provided by default.
+% These are described in the table below:
+%
+% \bigskip \begin{center} \begin{tabular}{lp{3in}}                    \hline
+% \bf Command        & \bf Meaning                                 \\ \hline
+% @.{"@@"}           & Typesets an `@@' character.                 \\
+% @.{"@/"<text>"/"}  & In text (LR or paragraph) mode, typesets its
+%                      argument emphasised.  In maths mode, it
+%                      always chooses italics.                     \\
+% @.{"@*"<text>"*"}  & Typesets its argument \<text> in bold.      \\
+% @.{"@i{"<text>"}"} & Equivalent to `@.{"\\index{"<text>"}"}'.    \\
+% @.{"@I{"<text>"}"} & As for |@i|, but also writes its argument
+%                      to the document.                            \\ \hline
+% \end{tabular} \end{center} \bigskip
+%
+% Package writers should not rely on any predefined @-commands -- they're
+% provided for users, and users should be able to redefine them without
+% fear of messing anything up.  (This includes the `standard' commands
+% provided by the @at\ package, by the way.  They're provided in the vague
+% hope that they might be useful, and as examples.)
+%
+% \implementation
+%
+% \section{Implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+% \subsection{Options handling}
+%
+% We need a switch to say whether digits should be allowed.  Since this
+% is a user thing, I'll avoid |\newif| and just define the thing by hand.
+%
+%    \begin{macrocode}
+\def\atallowdigits{\let\ifat@digits\iftrue}
+\def\atdisallowdigits{\let\ifat@digits\iffalse}
+%    \end{macrocode}
+%
+% Now define the options.
+%
+%    \begin{macrocode}
+\DeclareOption{digits}{\atallowdigits}
+\DeclareOption{nodigits}{\atdisallowdigits}
+\ExecuteOptions{nodigits}
+\ProcessOptions
+%    \end{macrocode}
+%
+% \subsection{How the commands work}
+%
+% Obviously we make the `@@' character active.  It inspects the next
+% character (or argument, actually -- it can be enclosed in braces for
+% longer commands, although this is a bit futile), and builds the command
+% name from that.
+%
+% The |\at| command is equivalent to the active `@@' character always.
+%
+%
+% \subsection{Converting command names}
+%
+% We need to be able to read an @-command name, and convert it to a normal
+% \TeX\ control sequence.  First, we declare some control sequences for
+% braces, which we need later.
+%
+%    \begin{macrocode}
+\begingroup
+\catcode`\<1
+\catcode`\>2
+\catcode`\{12
+\catcode`\}12
+\gdef\at@lb<{>
+\gdef\at@rb<}>
+\gdef\at@spc< >
+\endgroup
+%    \end{macrocode}
+%
+% I'll set up some helper routines now, to help me read the command
+% names.  The way this works is that we |\futurelet| the token into
+% |\@let@token|.  These routines will then sort out what to do next.
+%
+% \begin{macro}{\at@test}
+%
+% Given an |\if|\dots\ test, does its first or second argument.
+%
+%    \begin{macrocode}
+\def\at@test#1\then{%
+  #1\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\at@ifcat}
+%
+% Checks the category code of the current character.  If it matches the
+% argument, it does its second argument, otherwise it does the third.
+%
+%    \begin{macrocode}
+\def\at@ifcat#1{\at@test\ifcat#1\noexpand\@let@token\then}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\at@ifletter}
+%
+% This routine tests the token to see if it's a letter, and if so adds
+% it to the token list and does the first argument; otherwise it does the
+% second argument.  It accepts digits as letters if the switch is turned
+% on.
+%
+% There's some fun later, so I'll describe this slowly.  First, we compare
+% the category code to a letter, and if we have a match, we know we're done;
+% we need to pick up the letter as an argument.  If the catcode is `other',
+% we must compare with numbers to see if it's in range.
+%
+%    \begin{macrocode}
+\def\at@ifletter#1#2{%
+  \at@ifcat x%
+    {\at@ifletter@ii{#1}}%
+    {\at@ifcat 0%
+      {\at@ifletter@i{#1}{#2}}%
+      {#2}%
+    }% 
+}
+%    \end{macrocode}
+%
+% Right.  It's `other' (so it's safe to handle as a macro argument) and we
+% need to know if it's a digit.  This is a little tricky: I use |\if| to
+% compare two characters.  The first character is~`1' or~`0' depending on the
+% `digit' switch; the second is~`1' or~`x' depending on whether it's actually
+% a digit.  They'll only match if everything's worked out OK.
+%
+%    \begin{macrocode}
+\def\at@ifletter@i#1#2#3{%
+  \at@test\if%
+    \ifat@digits1\else0\fi%
+    \ifnum`#3<`0x\else\ifnum`#3>`9x\else1\fi\fi%
+  \then%
+    {\at@ifletter@ii{#1}{#3}}%
+    {#2#3}%
+}
+%    \end{macrocode}
+%
+% Right; we have the character, so add it to the list and carry on.
+%
+%    \begin{macrocode}
+\def\at@ifletter@ii#1#2{\toks@\expandafter{\the\toks@#2}#1}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% Now we define the command name reading routines.  We have @/almost/ the
+% same behaviour as \TeX, although we can't support `|%|' characters for
+% reasons to do with \TeX's tokenising algorithm.
+%
+% \begin{macro}{\at@read@name}
+%
+% The routine which actually reads the command name works as follows:
+% \begin{enumerate}
+% \item Have a peek at the next character.  If it's a left or right brace,
+%       then use the appropriate character.
+% \item If the character is not a letter, just use the character (or whole
+%       control sequence.
+% \item Finally, if it's a letter, keep reading letters until we find one
+%       that wasn't.
+% \end{enumerate}
+%
+% First, we do some setting up and read the first character
+%
+%    \begin{macrocode}
+\def\at@read@name#1{%
+  \let\at@next=#1%
+  \toks@{}%
+  \futurelet\@let@token\at@rn@i%
+}
+%    \end{macrocode}
+%
+% Next, sort out what to do, based on the category code.
+%
+%    \begin{macrocode}
+\def\at@rn@i{%
+  \def\@tempa{\afterassignment\at@rn@iv\let\@let@token= }%
+  \at@ifletter%
+    {\futurelet\@let@token\at@rn@iii}%
+    {\at@ifcat\bgroup%
+      {\toks@\expandafter{\at@lb}\@tempa}%
+      {\at@ifcat\egroup%
+        {\toks@\expandafter{\at@rb}\@tempa}%
+        {\at@ifcat\at@spc%
+          {\toks@{ }\@tempa}%
+          {\at@rn@ii}%
+        }%
+      }%
+    }%
+}
+%    \end{macrocode}
+%
+% Most types of tokens can be fiddled using |\string|.
+%
+%    \begin{macrocode}
+\def\at@rn@ii#1{%
+  \toks@\expandafter{\string#1}%
+  \at@rn@iv%
+}
+%    \end{macrocode}
+%
+% We've found a letter, so we should check for another one.
+%
+%    \begin{macrocode}
+\def\at@rn@iii{%
+  \at@ifletter%
+    {\futurelet\@let@token\at@rn@iii}%
+    {\@ifnextchar.\at@rn@iv\at@rn@iv}%
+}
+%    \end{macrocode}
+%
+% Finally, we need to pass the real string, as an argument, to the
+% macro.  We make |\@let@token| relax, since it might be something which will
+% upset \TeX\ later, e.g., a |#| character.
+%
+%    \begin{macrocode}
+\def\at@rn@iv{%
+  \let\@let@token\relax%
+  \expandafter\at@next\csname at.\the\toks@\endcsname%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\at@cmdname}
+%
+% Given a control sequence, work out which @-command it came from.
+%
+%    \begin{macrocode}
+\def\at@cmdname#1{\expandafter\at@cmdname@i\string#1\@@foo}
+%    \end{macrocode}
+%
+% Now extract the trailing bits.
+%
+%    \begin{macrocode}
+\def\at@cmdname@i#1.#2\@@foo{#2}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\at@decode}
+%
+% The |\at@decode| macro takes an extracted @-command name, and tries to
+% execute the correct control sequence derived from it.
+%
+%    \begin{macrocode}
+\def\at@decode#1{%
+  \at@test\ifx#1\relax\then{%
+    \PackageError{at}{Unknown @-command `@\at@cmdname#1'}{%
+      The @-command you typed wasn't recognised, so I've ignored it.
+    }%
+  }{%
+    #1%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\@at}
+%
+% We'd like a measure of compatibility with @p{amsmath}.  The @-commands
+% provided by @p{amsmath} work only in maths mode, so this gives us a way of
+% distinguishing.  If the control sequence |\Iat| is defined, and we're in
+% maths mode, we'll call that instead of doing our own thing.
+%
+%    \begin{macrocode}
+\def\@at{%
+  \def\@tempa{\at@read@name\at@decode}%
+  \ifmmode\ifx\Iat\not@@defined\else%
+    \let\@tempa\Iat%
+  \fi\fi%
+  \@tempa%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Defining new commands}
+%
+% \begin{macro}{\at@buildcmd}
+%
+% First, we define a command to build these other commands:
+%
+%    \begin{macrocode}
+\def\at@buildcmd#1#2{%
+  \expandafter\def\csname\expandafter
+    \@gobble\string#1@decode\endcsname##1{#2##1}%
+  \edef#1{%
+    \noexpand\at@read@name%
+    \expandafter\noexpand%
+      \csname\expandafter\@gobble\string#1@decode\endcsname%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\newatcommand}
+% \begin{macro}{\renewatcommand}
+% \begin{macro}{\provideatcommand}
+% \begin{macro}{\atdef}
+% \begin{macro}{\atshow}
+%
+% Now we define the various operations on @-commands.
+%
+%    \begin{macrocode}
+\at@buildcmd\newatcommand\newcommand
+\at@buildcmd\renewatcommand\renewcommand
+\at@buildcmd\provideatcommand\providecommand
+\at@buildcmd\atdef\def
+\at@buildcmd\atshow\show
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\atlet}
+%
+% |\atlet| is rather harder than the others, because we want to allow people
+% to say things like @.{"\\atlet"<name>"=@"<name>}.  The following hacking
+% does the trick.  I'm trying very hard to duplicate |\let|'s behaviour with
+% respect to space tokens here, to avoid any surprises, although there
+% probably will be some differences.  In particular, |\afterassignment|
+% won't work in any sensible way.
+%
+% First, we read the name of the @-command we're defining.  We also open
+% a group, to stop messing other people up, and make `@@' into an `other'
+% token, so that it doesn't irritatingly look like its meaning as a control
+% sequence.
+%
+%    \begin{macrocode}
+\def\atlet{%
+  \begingroup%
+  \@makeother\@%
+  \at@read@name\atlet@i%
+}
+%    \end{macrocode}
+%
+% Put the name into a scratch macro for later use.  Now see if there's an
+% equals sign up ahead.  If not, this will gobble any spaces in between the
+% @-command name and the argument.
+%
+%    \begin{macrocode}
+\def\atlet@i#1{%
+  \def\at@temp{#1}%
+  \@ifnextchar=\atlet@ii{\atlet@ii=}%
+}
+%    \end{macrocode}
+%
+% Now we gobble the equals sign (whatever catcode it is), and peek at the
+% next token up ahead using |\let| with no following space.
+%
+%    \begin{macrocode}
+\def\atlet@ii#1{\afterassignment\atlet@iii\global\let\at@gnext=}
+%    \end{macrocode}
+%
+% The control sequence |\at@gnext| is now |\let| to be whatever we want the
+% @-command to be, unless it's picked up an `@@' sign.  If it has, we've
+% eaten the |@| token, so just read the name and pass it on.  Otherwise,
+% we can |\let| the @-command directly to |\at@gnext|.  There's some
+% nastiness here to make |\the\toks@| expand before we close the group and
+% restore its previous definition.
+%
+%    \begin{macrocode}
+\def\atlet@iii{%
+  \if @\noexpand\at@gnext%
+    \expandafter\at@read@name\expandafter\atlet@iv%
+  \else%
+    \expandafter\endgroup%
+    \expandafter\let\at@temp= \at@gnext%
+  \fi%
+}
+%    \end{macrocode}
+%
+% We've read the source @-command name, so just copy the definitions over.
+%
+%    \begin{macrocode}
+\def\atlet@iv#1{%
+  \expandafter\endgroup%
+  \expandafter\let\at@temp=#1%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Robustness of @-commands}
+%
+% We want all @-commands to be robust.  We could leave them all being
+% fragile, although making robust @-commands would then be almost impossible.
+% There are two problems which we must face:
+%
+% \begin{itemize}
+%
+% \item The `|\@at|' command which scans the @-command name is (very)
+%       fragile.  I could have used |\DeclareRobustCommand| for it (and in
+%       fact I did in an earlier version), but that doesn't help the other
+%       problem at all.
+%
+% \item The `name' of the @-command may contain active characters or control
+%       sequences, which will be expanded at the wrong time unless we do
+%       something about it now.
+%
+% \end{itemize}
+%
+% We must also be careful not to introduce extra space characters into any
+% files written, because spaces are significant in @-commands.  Finally,
+% we have a minor problem in that most auxiliary files are read in with
+% the `@@' character set to be a letter.
+%
+% \begin{macro}{\at}
+%
+% Following the example of \LaTeX's `short' command handling, we'll define
+% |\at| to decide what to do depending on what |\protect| looks like.  If
+% we're typesetting, we just call |\@at| (above) and expect it to cope.
+% Otherwise we call |\at@protect|, which scoops up the |\fi| and the |\@at|,
+% and inserts other magic.
+%
+%    \begin{macrocode}
+\def\at{\ifx\protect\@typeset@protect\else\at@protect\fi\@at}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\at@protect}
+%
+% Since we gobbled the |\fi| from the above, we must put that back.  We then 
+% need to do things which are more complicated.  If |\protect| is behaving 
+% like |\string|, then we do one sort of protection.  Otherwise, we assume
+% that |\protect| is being like |\noexpand|.
+%
+%    \begin{macrocode}
+\def\at@protect\fi#1{%
+  \fi%
+  \ifx\protect\string%
+    \expandafter\at@protect@string%
+  \else%
+    \expandafter\at@protect@noexpand%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\at@protect@string}
+%
+% When |\protect| is |\string|, we don't need to be able to recover the
+% original text particularly accurately -- it's for the user to look at.
+% Therefore, we just output a $|@|_{11}$ and use |\string| on the next
+% token.  This must be sufficient, since we only allow multi-token command
+% names if the first token is a letter (code~11).
+%
+%    \begin{macrocode}
+\def\at@protect@string{@\string}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\at@protect@noexpand}
+%
+% This is a little more complex, since we're still expecting to be executed
+% properly at some stage.  However, there's a cheeky dodge we can employ
+% since the |\at| command is thoroughly robustified (or at least it will be
+% by the time we've finished this).  All |\@unexpandable@protect| does
+% is confer repeated robustness on a fragile command.  Since our command
+% is robust, we don't need this and we can get away with just using a
+% single |\noexpand|, both for the |\@at@| command and the following token
+% (which we must robustify, because no-one else can do it for us -- if
+% anyone tries, they end up using the |@\protect| command which is rather
+% embarassing).
+%
+% I'll give the definition, and then examine how this expands in various
+% cases.
+%
+%    \begin{macrocode}
+\def\at@protect@noexpand{\noexpand\@at@ @\noexpand}
+\def\@at@#1{\at}
+%    \end{macrocode}
+%
+% A few points, before we go into the main examination of the protection.
+% I've inserted a $|@|_{11}$ token, which is gobbled by |\@at@| when the
+% thing is finally expanded fully.  This prevents following space tokens
+% in an |\input| file from being swallowed because they follow a control
+% sequence.  (I can't use the normal $|@|_{13}$ token, because when files
+% like the |.aux| file are read in, |@| is given code~11 by
+% |\makeatletter|.)
+%
+% \setbox0\hbox{|@at@|}
+% Now for a description of why this works.  When |\at| is expanded, it works
+% out that |\protect| is either |\noexpand| or |\@unexpandable@protect|, and
+% becomes |\at@protect@noexpand|.  Because of the |\noexpand| tokens, this
+% stops being expanded once it reaches $\fbox{\box0}\,|@|_{11}\,x$ (where
+% $x$ is the token immediately following the $|@|_{13}$ character).  If this
+% is expanded again, for example in another |\edef|, or in a |\write| or a
+% |\mark|, the |\@at@| wakes up, gobbles the following |@| (whatever catcode
+% it is -- there may be intervening |\write| and |\input| commands) and
+% becomes |\at|, and the whole thing can start over again.
+%
+% \end{macro}
+%
+%
+% \subsection{Enabling and disabling @-commands}
+%
+% \begin{macro}{\aton}
+%
+% We define the |\aton| command to enable all of our magic.  We store
+% the old catcode in the |\atoff| command, make `@@' active, and make it
+% do the stuff.
+%
+%    \begin{macrocode}
+\def\aton{%
+  \ifnum\catcode`\@=\active\else%
+    \edef\atoff{\catcode`\noexpand\@\the\catcode`\@}%
+    \catcode`\@\active%
+    \lccode`\~`\@%
+    \lowercase{\let~\at}%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\atoff}
+%
+% The |\atoff| command makes `@@' do the stuff it's meant to.  We remember
+% the old catcode and revert to it.  This is largely unnecessary.
+%
+%    \begin{macrocode}
+\def\atoff{\catcode`\@12}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\makeatother}
+%
+% Now we make our active `@@' the default outside of package files.
+%
+%    \begin{macrocode}
+\let\makeatother\aton
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% And we must make sure that the user can use all of our nice commands.
+% Once the document starts, we allow @-commands.
+%
+%    \begin{macrocode}
+\AtBeginDocument{\aton}
+%    \end{macrocode}
+%
+% \begin{macro}{\dospecials}
+% \begin{macro}{\@sanitize}
+%
+% We must add the `@@' character to the various specials lists.
+%
+%    \begin{macrocode}
+\expandafter\def\expandafter\dospecials\expandafter{\dospecials\do\@}
+\expandafter\def\expandafter\@sanitize\expandafter{%
+  \@sanitize\@makeother\@}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Default @-commands}
+%
+% We define some trivial examples to get the user going.
+%
+%    \begin{macrocode}
+\expandafter\chardef\csname at.@\endcsname=`\@
+\atdef*#1*{\ifmmode\mathbf{#1}\else\textbf{#1}\fi}
+\atdef/#1/{\ifmmode\mathit{#1}\else\emph{#1}\fi}
+\atlet i=\index
+\atdef I#1{#1\index{#1}}
+%</package>
+%    \end{macrocode}
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
diff --git a/cmtt.dtx b/cmtt.dtx
new file mode 100644
index 0000000..95d284f
--- /dev/null
+++ b/cmtt.dtx
@@ -0,0 +1,523 @@
+% \begin{meta-comment}
+%
+% $Id: cmtt.dtx,v 1.1 2002/02/03 20:49:02 mdw Exp $
+%
+% Nicer handling of the Computer Modern Typewriter font
+%
+% (c) 1996 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: cmtt.dtx,v $
+% Revision 1.1  2002/02/03 20:49:02  mdw
+% Checkin for new build system.
+%
+% Revision 1.1  1996/11/19 20:47:55  mdw
+% Initial revision
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% mdwlist package -- various list-related things
+%% Copyright (c) 1996 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+%
+% \begin{meta-comment} <Package preambles>
+%<+sty>\NeedsTeXFormat{LaTeX2e}
+%<+sty>\ProvidesPackage{cmtt}
+%<+fd>\ProvidesFile{mTTcmtt.fd}
+%<+def>\ProvidesFile{mTTcmtt.def}
+%<+sty|fd|def>         [1996/05/25 1.1 Handing of the cmtt font]
+% \end{meta-comment}
+%
+% ^^A \CheckSum{174}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{cmtt}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+%^^A-------------------------------------------------------------------------
+% \section{Introductory note}
+%
+% \LaTeX\ has a rather cunning encoding handling system, which makes funny
+% commands like accents work properly independent of the current font's
+% actual layout.  While this works rather well most of the time, the standard
+% \mtt{tt} font has been rather left out of things.  \LaTeX\ assumes that
+% the Computer Modern Typewriter fonts have exactly the same layout as the
+% more normal Computer Modern Roman family (i.e., that both conform to the
+% \mtt{OT1} encoding).  This plainly isn't true, since the Typewriter font
+% contains a bunch of standard ASCII characters which are omitted from the
+% standard Computer Modern fonts, such as curly braces \mtt{\{} and \mtt{\}},
+% and the backslash \mtt{\\}; these are usually dug up from the maths fonts,
+% which looks fine in normal text, but looks really odd in monospace text.
+% Compare `\texttt{\textbackslash begin\{document\}}' to
+% `\mtt{\\begin\{document\}}', for example.
+%
+% There are two possibilities for dealing with this problem.  One is to use
+% the \mtt{\\verb} command, which works since all the extra characters in
+% the Typewriter font are in the correct places, or use the DC~fonts, which
+% have a proper encoding set up which contains all of these special
+% characters anyway.
+%
+% Neither of these solutions is perfect.  Using \mtt{\\verb} causes all
+% manner of little niggly problems: you can't use it in footnotes or
+% section headings, for example.  (There are of course workarounds for this
+% sort of thing: the author's \package{footnote} package provides a
+% \env{footnote} environment which will allow verbatim text, and verbatim
+% text in section headings can be achieved if one is sufficiently
+% \TeX nical.)  Using the DC~fonts is fine, although you actually lose a
+% glyph or two.  As far as the author is aware, the character \mtt{\'} (an
+% `unsexed' single quote) is not present in the \mtt{T1}-encoded version of
+% Computer Modern Typewriter, although it is hidden away in the original
+% version.  The author has found a need for this character in computer
+% listings, and was horrified to discover that it was replaced by a German
+% single quote character (\mtt{\\quotesinglbase}).
+%
+% This package defines a special encoding for the Computer Modern Typewriter
+% font, so that documents can take advantage of its ASCII characters without
+% resorting to verbatim text.  (The main advantage of the DC~fonts, that
+% words containing accents can be hyohenated, doesn't really apply to the
+% Typewriter font, since it doesn't allow hyphenation by default anyway.)
+%
+% There are several files you'll need to create:
+% \begin{description} \def\makelabel#1{\hskip\labelsep\mttfamily#1\hfil}
+%
+% \item [cmtt.sty] tells \LaTeX\ that there's a new encoding.  It also
+%       provides some options for customising some aspects of the
+%       encoding, and defines some useful commands.
+%
+% \item [mTTenc.def] describes the encoding to \LaTeX: it sets up all the
+%       appropriate text commands so that they produce beautiful results.
+%
+% \item [mTTcmtt.fd] describes the re-encoded version of the font.  This
+%       is more or less a copy of the file \mtt{OT1cmtt.fd}.
+%
+% \end{description}
+%
+% The package accepts some options which may be useful:
+% \begin{description} \def\makelabel#1{\hskip\labelsep\sffamily#1\hfil}
+%
+% \item [override] overrides the meaning of the \mtt{\\ttfamily} command
+%       (and therefore also the \mtt{\\texttt} command too), making it the
+%       same as the new \mtt{\\mttfamily} command.  This isn't the default
+%       just in case the change breaks something in an unexpected way.
+%
+% \item [t1] informs the package that you're using the \mtt{T1} encoding,
+%       and therefore can borrow some accented characters from the DC~version
+%       of Computer Modern Typewriter.  This will probably be unnecessary,
+%       since the package attempts to work out what to do all by itself.
+%
+% \item [ot1] forces the package \emph{not} to use the DC~version of the
+%       Computer Modern Typewriter font for funny accents.  Only use this
+%       option if the package thinks it should use the DC~Typewriter font
+%       when it shouldn't.
+%
+% \end{description}
+%
+% \DescribeMacro{\mttfamily}
+% The command \mtt{\\mttfamily} selects the properly-encoded Typewriter
+% font.  It's a declaration which works just like the \mtt{\\ttfamily}
+% command, except that comamnds like \mtt{\\\}} and \mtt{\\\_} use the
+% characters from the font rather than choosing odd-looking versions from
+% the maths fonts.  All of the accent commands still work properly.  In fact,
+% some accent commands which didn't work before have been fixed.  For
+% example, saying `\mtt{\\texttt\{P\\'al Erd\\H os\}}' would produce
+% something truly appalling like `\texttt{P\'al Erd\H os}', which is
+% obviously ghastly.  The new encoding handles this properly, and produces
+% `\textmtt{P\'al Erd\H os}'.\footnote{
+%   This isn't quite perfect.  The accent, which isn't actually present in
+%   the Typewriter font, is taken from the Computer Modern bold font, but
+%   it doesn't look too bad.  However, if you pass the option \textsf{t1}
+%   to the \package{cmtt} package when you load it, the accent will be taken
+%   from the DC~Typewriter font, and it will look totally wonderful.}
+%
+% \DescribeMacro{\textmtt}
+% Font changing commands are much more convenient than th declarations,
+% so a command \mtt{\\textmtt} is provided: it just typesets its argument
+% in the re-encoded Typewriter font.
+%
+% \DescribeMacro{\mtt}
+% Rather more excitingly, the \mtt{\\mtt} command allows you to generate
+% almost-verbatim text very easily, without any of the restrictions of
+% the \mtt{\\verb} command.  This command was inspired by something which
+% David Carlisle said to me in an email correspondence regarding the
+% overuse of verbatim commands.
+%
+% \mtt{\\mtt} redefines several `short' commands to typeset the obvious
+% characters.  The complete list is shown below: there are some oddities,
+% so watch out.
+%
+% ^^A This is an evil table.  See if I care.  (This is based on lots of
+% ^^A hacking I did in glyphs.tex, but a good deal less horrible.)
+%
+% \medskip
+% \hbox to \hsize\bgroup
+% \hfil\vbox\bgroup
+% \def\ex#1#2{\strut
+%   \enskip
+%   \mtt{\\\char`#2}\quad\hfil%
+%   \mtt{#2}\enskip}
+% \def\h{\noalign{\hrule}}
+% \def\v{height2pt&\omit&&\omit&&\omit&&\omit&&\omit&\cr}
+% \let~\relax
+% \offinterlineskip
+% \ialign\bgroup&\vrule#&\ex#\cr        \h\v
+% &~\\&&~\{&&~\}&&~\_&&~\^&\cr        \v\h\v
+% &~\$&&~\%&&~\&&&~\#&&~\~&\cr        \v\h\v
+% &~\"&&~\'&&~\ &&~\|&&\omit\hfil&\cr \v\h
+% \egroup\egroup
+% \hfil\egroup
+% \medskip
+%
+% As well as redefining these commands, \mtt{\\mtt} will endeavour to make
+% single special characters display themselves in a verbatim-like way.  This
+% only works on `active' characters (like \mtt{~}), and \mtt{\\mtt} makes
+% no attempt to change the category codes of any characters.
+%
+% Among other things, you'll probably noticed that several accent-making
+% commands have been redefined.  You can still use these accents through
+% the \mtt{\\a} command, by saying \mtt{\\a'}, \mtt{\\a\^} and so on,
+% as in the \env{tabbing} environment.
+%
+% There are also some oddities in the table: \mtt{\|} and \mtt{\"} can be
+% accessed easily without playing with silly commands.  Well, that's almost
+% the case: these two characters are both often used as `short' verbatim
+% commands, so they are forced back to their normal meanings so you can
+% type them.
+%
+% Finally, a word on spacing.  The \mtt{\\\ } command has been hijacked
+% to produce a funny `visible space' character.  You can still produce
+% multiple spaces by saying something like `\mtt{\ \{\}\ \{\}}\dots\mtt{\ }',
+% which is a bit contrived, but that's tough.  Also, \mtt{~} has been stolen
+% so that you can type \mtt{~} characters (e.g., in URLs), so the only
+% way you can tpye a nonbreaking space is by using the \mtt{\\nobreakspace}
+% command, which is a bit of a mouthful.  There's an abbreviation, though:
+% \mtt{\\nbsp} now means exactly the same thing.
+%
+% Was that not all supremely useful?  Oh, just a note: this document doesn't
+% use a single verbatim command or environment (except in the listings,
+% where it's unavoidable) -- it's all done with \mtt{\\mtt}.
+%
+% \implementation
+%
+% \section{Implementation}
+%
+% \subsection{The package}
+%
+%    \begin{macrocode}
+%<*sty>
+%    \end{macrocode}
+%
+% I'll start with some options handling.
+%
+%    \begin{macrocode}
+\newif\ifcmtt@override
+\newif\ifcmtt@dcfonts
+\def\@tempa{T1}\ifx\encodingdefault\@tempa
+  \cmtt@dcfontstrue
+\fi
+\DeclareOption{override}{\cmtt@overridetrue}
+\DeclareOption{t1}{\cmtt@dcfontstrue}
+\DeclareOption{ot1}{\cmtt@dcfontsfalse}
+\ProcessOptions
+%    \end{macrocode}
+%
+% This bit is really trivial.  I'll just declare the font encoding.  Oh, that
+% was easy.
+%
+%    \begin{macrocode}
+\DeclareFontEncoding{mTT}{}{}
+%    \end{macrocode}
+%
+% Wait: there's a problem.  \LaTeX\ will now complain bitterly that it can't
+% find the font \mtt{mTT/cmr/m/n}, which is readonable, since I haven't
+% declared any such font.  The following line should sort this out,
+%
+%    \begin{macrocode}
+\DeclareFontSubstitution{mTT}{cmtt}{m}{n}
+%    \end{macrocode}
+%
+% Now I'd better load all the text commands I'll need when in this funny
+% font variant.
+%
+%    \begin{macrocode}
+\input{mTTenc.def}
+%    \end{macrocode}
+%
+% \begin{macro}{\mttfamily}
+% \begin{macro}{\textmtt}
+%
+% Finally, I'll need to define a command which switches to this funny font,
+% and a \mtt{\\text}\dots\ command for it.
+%
+%    \begin{macrocode}
+\DeclareRobustCommand{\mttfamily}{%
+  \fontencoding{mTT}\fontfamily{\ttdefault}\selectfont%
+}
+\DeclareTextFontCommand{\textmtt}{\mttfamily}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+% If an override was requested, make \mtt{\\ttfamily} the same as
+% \mtt{\\mttfamily}.
+%
+%    \begin{macrocode}
+\ifcmtt@override
+  \let\ttfamily\mttfamily
+\fi
+%    \end{macrocode}
+%
+% Well, that's all that's needed for the font definition.  Here's a command
+% which will typeset its argument in the typewriter font, allowing easy
+% access to all the funny characters, and printing them properly in the
+% correct font (which \mtt{\\\{} doesn't do, for example).
+%
+% \begin{macro}{\mtt@setchar}
+%
+% This macro assigns the given meaning to the given control sequence.  Also,
+% if the character named in the control sequence is currently set active,
+% it will set the active meaning of the character to the same value.
+%
+%    \begin{macrocode}
+\def\mtt@setchar#1#2{%
+  \ifx#1#2\chardef#1`#1\else\let#1#2\fi%
+  \ifnum\catcode`#1=13%
+    \begingroup%
+      \lccode`\~=`#1%
+    \lowercase{\endgroup\let~#1}%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\mtt@chars}
+%
+% This macro lists the various control sequences which should be set up,
+% so that they can be easily added to.
+%
+%    \begin{macrocode}
+\def\mtt@chars{%
+  \do\#\#%
+  \do\%\%%
+  \do\&\&% 
+  \do\^\^%
+  \do\~\~%
+  \do\'\textquotesingl%
+  \do\"\textquotedbl%
+  \do\|\textbar%
+  \do\$\textdollar%
+  \do\_\textunderscore%
+  \do\{\textbraceleft%
+  \do\}\textbraceright%
+  \do\\\textbackslash%
+  \do\ \textvisiblespace%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\mtt@do}
+%
+% This just sets up all the special characters listed above.  It's a simple
+% abbreviation, really.
+%
+%    \begin{macrocode}
+\def\mtt@do{\let\do\mtt@setchar\mtt@chars}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\mtt}
+%
+% And finally, the macro itself.  Ta-da!
+%
+%    \begin{macrocode}
+\DeclareRobustCommand\mtt[1]{\textmtt{\mtt@do#1}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\@tabacckludge}
+%
+% The otherwise almost totally perfect \mtt{\\@tabacckludge} gets very
+% upset when its argument is an active character.  (If you're wondering,
+% this is the command which is responsible for the behaviour of the \mtt{\\a}
+% command.)  Adding a \mtt{\\string} makes everything work perfectly.
+%
+%    \begin{macrocode}
+\def\@tabacckludge#1{%
+  \expandafter\@changed@cmd\csname\string#1\endcsname\relax%
+}
+\let\a\@tabacckludge
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\nbsp}
+%
+% Make an abbreviation for \mtt{\\nobreakspace}.
+%
+%    \begin{macrocode}
+\let\nbsp\nobreakspace
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% I think that's all that I have to do for the package.  If there's any
+% more to do, I'll add it later.
+%
+%    \begin{macrocode}
+%</sty>
+%    \end{macrocode}
+%
+%
+% \subsection{The font definition file}
+%
+% This is obviously copied almost verbatim from the file \mtt{OT1cmtt.fd}.
+%
+%    \begin{macrocode}
+%<*fd>
+\DeclareFontFamily{mTT}{cmtt}{\hyphenchar\font\m@ne}
+\DeclareFontShape{mTT}{cmtt}{m}{n}{
+  <5> <6> <7> <8> cmtt8
+  <9> cmtt9
+  <10> <10.95> cmtt10
+  <12> <14.4> <17.28> <20.74> <24.88> cmtt12
+}{}
+\DeclareFontShape{mTT}{cmtt}{m}{it}{
+  <5> <6> <7> <8> <9> <10> <10.95> <12> <14.4> <17.28> <20.74> <24.88>
+  cmitt10
+}{}
+\DeclareFontShape{mTT}{cmtt}{m}{sl}{
+  <5> <6> <7> <8> <9> <10> <10.95> <12> <14.4> <17.28> <20.74> <24.88>
+  cmsltt10
+}{}
+\DeclareFontShape{mTT}{cmtt}{m}{sc}{
+  <5> <6> <7> <8> <9> <10> <10.95> <12> <14.4> <17.28> <20.74> <24.88>
+  cmtcsc10
+}{}
+\DeclareFontShape{mTT}{cmtt}{m}{ui}  {<->sub * cmtt/m/it} {}
+\DeclareFontShape{mTT}{cmtt}{bx}{n}  {<->sub * cmtt/m/n}  {}
+\DeclareFontShape{mTT}{cmtt}{bx}{it} {<->sub * cmtt/m/it} {}
+\DeclareFontShape{mTT}{cmtt}{bx}{ui} {<->sub * cmtt/m/it} {}
+%</fd>
+%    \end{macrocode}
+%
+%
+% \subsection{The encoding definitions file}
+%
+% I've saved the trickiest bit until last.  This file defines the mappings
+% from text commands to glyphs in the font.
+%
+%    \begin{macrocode}
+%<*def>
+%    \end{macrocode}
+%
+% First for some fun with accents.  The |cmtt| font doesn't contain all of
+% the accents which the other Computer Modern fonts do, because those slots
+% contain the standard ASCII characters which usually have to be `borrowed'
+% from the maths fonts.
+%
+% Anyway, there's a load which don't need any special treatment.  These are
+% chosen from the \mtt{OT1} encoding by default anyway, so I needn't
+% bother unless I'm really bothered about speed.  I'm not, so I'll save
+% the memory.
+%
+% Following the example of the \TeX book, I'll use the bold roman font
+% for accents, so that they don't look really spindly.  This is actually
+% remarkably difficult to do, because the \textsf{NFSS} keeps getting in
+% the way.  I'll look after the old font name in a macro (it's handy that
+% \textsf{NFSS} maintains this for me) and change to a known font, do the
+% accent, change font back again, do the argument to the accent, and then
+% close the group I did all of this in, so that no-one else notices what a
+% naughty chap I am, really.  This is startlingly evil.
+%
+%    \begin{macrocode}
+\def\cmtt@accent#1#2{{%
+  \let\@old@font\font@name%
+  \ifcmtt@dcfonts%
+    \fontencoding{T1}\selectfont%
+  \else%
+    \usefont{OT1}{cmr}{bx}{n}%
+  \fi%
+  #1{\@old@font#2}%
+}}
+%    \end{macrocode}
+%
+% And now for the actual offending accents.
+%
+%    \begin{macrocode}
+\DeclareTextCommand{\H}{mTT}{\cmtt@accent\H}
+\DeclareTextCommand{\.}{mTT}{\cmtt@accent\.}
+%    \end{macrocode}
+%
+% The `under' accents are all OK, so I shan't bother to define them either.
+% Similarly, lots of the text symbol commands are fine as they are by
+% default and I don't need to try and define them again.
+%
+% This, then, is the remaining commands which really need sorting out.
+% (By the way, the only reason I've redefined \mtt{\\textellipsis} is
+% because otherwise it will mess up the nice monospacing.)
+%
+%    \begin{macrocode}
+\DeclareTextSymbol{\textbackslash}{mTT}{92}
+\DeclareTextSymbol{\textbar}{mTT}{124}
+\DeclareTextSymbol{\textbraceleft}{mTT}{123}
+\DeclareTextSymbol{\textbraceright}{mTT}{125}
+\DeclareTextSymbol{\textless}{mTT}{60}
+\DeclareTextSymbol{\textgreater}{mTT}{62}
+\DeclareTextSymbol{\textunderscore}{mTT}{95}
+\DeclareTextSymbol{\textvisiblespace}{mTT}{32}
+\DeclareTextCommand{\textellipsis}{mTT}{...}
+\DeclareTextSymbol{\textquotedbl}{mTT}{34}
+\DeclareTextSymbol{\textquotesingl}{mTT}{13}
+%    \end{macrocode}
+%
+% That's all there is.  Please return to your homes.
+%
+% \Finale
+%
+\endinput
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..172c82d
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,57 @@
+dnl -*-fundamental-*-
+dnl
+dnl $Id: configure.in,v 1.1 2002/02/03 20:49:03 mdw Exp $
+dnl
+dnl Configuration script for mdwtools
+dnl
+dnl (c) 2002 Mark Wooding
+dnl
+
+dnl ----- Licensing notice --------------------------------------------------
+dnl
+dnl This file is part of the mdwtools LaTeX package collection.
+dnl
+dnl mdwtools is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl 
+dnl mdwtools is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU General Public License for more details.
+dnl 
+dnl You should have received a copy of the GNU General Public License
+dnl along with mdwtools; if not, write to the Free Software Foundation,
+dnl Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+dnl ----- Revision history --------------------------------------------------
+dnl
+dnl $Log: configure.in,v $
+dnl Revision 1.1  2002/02/03 20:49:03  mdw
+dnl Checkin for new build system.
+dnl
+
+AC_INIT(mdwtools.ins)
+AM_INIT_AUTOMAKE(mdwtools, 1.6.0)
+
+AC_ARG_WITH([texmfdir], 
+[  --with-texmfdir=DIR     set the TeX install directory to DIR],
+[texmfdir=$witharg],
+[AC_MSG_CHECKING([where to put installed TeX files])
+mdw_DEFINE_PATHS([
+texmfdir='${datadir}/texmf'
+for d in \
+  '${datadir}/texmf' '${libdir}/texmf' '${prefix}/lib/texmf' \
+  '${prefix}/texmf'; do
+  if test -d "mdw_PATH([$d])"; then
+    texmfdir=$d
+    break
+  fi
+done
+AC_MSG_RESULT([$texmfdir])])])
+AC_SUBST(texmfdir)
+
+AC_OUTPUT(Makefile)
+
+dnl ----- That's all, folks -------------------------------------------------
diff --git a/crypto.dtx b/crypto.dtx
new file mode 100644
index 0000000..92f381c
--- /dev/null
+++ b/crypto.dtx
@@ -0,0 +1,461 @@
+% \begin{meta-comment}
+%
+% $Id: crypto.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
+%
+% Typesetting crypto papers
+%
+% (c) 2001 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: crypto.dtx,v $
+% Revision 1.1  2002/02/03 20:49:03  mdw
+% Checkin for new build system.
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% crypto package -- useful macros for typesetting crypto papers
+%% Copyright (c) 2001 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%% 
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%% 
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software Foundation,
+%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preambles>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{crypto}
+%<+package>                [2001/09/16 1.0 Crypto typesetting]
+% \end{meta-comment}
+%
+% \CheckSum{215}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{crypto}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+%^^A-------------------------------------------------------------------------
+% \section{User guide}
+%
+% \subsection{Algorithm typesetting}
+%
+% A lot of provable-security papers need to be able to typeset algorithms
+% describing adversaries, schemes, oracle behaviour, etc.  There is a
+% (relatively) standard format for doing this which we support.
+%
+% \DescribeEnv{program}
+% The \env{program} environment provides handy notation for describing
+% algorithms formally.  It gives a \env{tabbing} environment, so that things
+% can be laid out nicely, and allows fragments of algorithms to be laid out
+% in columns or rows, with separating rules.
+%
+% \DescribeMacro\next
+% Within the \env{program} environment, the |\next| command stops typesetting
+% the current column, typesets a vertical separator rule, and starts a new
+% column.  Adjacent columns are spaced out evenly across the page, with equal
+% space around the rules rules and at the current margins.  This means that
+% the rules don't line up, but it still seems to provide a pleasing effect.
+%
+% \DescribeMacro\newline
+% The |\newline| macro begins a new row of algorithm typesetting.  A page
+% break is possible at a |\newline|.
+%
+% \DescribeMacro\kw
+% A number of standard keywords are available, as shown in
+% table~\ref{tab:kw}.  The typsetting of these is done by the |\kw| command,
+% which usually sets its argument in text bold face, but can be redefined.
+% The standard definition uses |\xspace| so that you don't need to remember
+% to say \verb*+\ *+ after a keyword command.
+% \begin{table}
+%   \centering
+%   \def\row#1{\texttt{\string#1} & #1 \\}
+%   \begin{tabular}{ll}
+%     \textbf{Command} & \textbf{Keyword} \\
+%     \row\RETURN
+%     \row\IF
+%     \row\THEN
+%     \row\ELSE
+%     \row\REPEAT
+%     \row\WHILE
+%     \row\UNTIL
+%     \row\FOREVER
+%     \row\DO
+%     \row\FOR
+%     \row\FOREACH
+%     \row\FROM
+%     \row\IN
+%     \row\TO
+%     \row\ABORT
+%     \row\PARSE
+%     \row\AS
+%   \end{tabular}
+%   \caption{Keywords available for algorithm typesetting}
+%   \label{tab:kw}
+% \end{table}
+%
+% \DescribeMacro\gets
+% \DescribeMacro\getsr
+% \DescribeMacro\inr
+% Assignment can be represented using the standard command |\gets|, which
+% typesets a left-pointing arrow `$\gets$'.  Random sampling -- the selection
+% of a random element from a set or probability distribution -- can be
+% represented using the new command |\getsr|, which typesets an arrow with a
+% little `R' above it `$\getsr$'.  Random membership -- showing that
+% something is a random variable with some distribution -- can be represented
+% using the |\inr| command, which just typesets an $\in$ sign with a
+% subscript `R': `$\inr$'.
+%
+% \DescribeMacro\id
+% Long identifiers can be typeset using the |\id| command. giving the
+% identifier name as an argument.  The |\id| command is only valid in maths
+% mode.  As currently set up, |\id| sets its argument in \emph{text} italics;
+% this seems to look better in documents which use a PostScript body face and
+% Computer Modern for maths.
+%
+% \DescribeMacro\Xid
+% It's handy to be able to glue a bit of (possibly fancy) maths typesetting
+% to an identifier, e.g., to construct $\Xid{H'}{list}$, or
+% $\Xid{\mathcal{E}}{CTR$\$$}^F$.  This is done using
+% \syntax{"\\Xid{"<maths>"}{"<text>"}"}.  The two bits are joined by a text
+% hyphen `-'.
+%
+% \DescribeMacro\cookie
+% Sometimes textual names are used for special `symbols', which have meaning
+% to algorithms, e.g., the symbols $\cookie{find}$ and $\cookie{guess}$ in
+% the standard indistinguishability game.  These can be typeset using the
+% |\cookie| command.
+%
+% \subsection{Other stuff}
+%
+% \DescribeMacro\Thing
+% In the quantifiable-security world, there are standard symbols for
+% advantage, success probability, insecurity, etc.  The generic `style hook'
+% for these is \syntax{"\\Thing{"<name>"}{"<notion>"}{"scheme"}"}, which
+% typesets $\Thing{name}{notion}{scheme}$.  It helps a lot if you have the
+% \package{amstext} package loaded.
+%
+% \DescribeMacro\Succ
+% \DescribeMacro\Adv
+% \DescribeMacro\InSec
+% \DescribeMacro\Expt
+% \begin{synshorts}
+% Some standard `things' are provided: "\\Succ{"<notion>"}{"<scheme>"}",
+% "\\Adv{"<notion>"}{"<scheme>"}", "\\InSec{"<notion>"}", and
+% "\\Expt{"<notion>"}{"<scheme>"}".
+% \end{synshorts}
+%
+% \DescribeMacro\G
+% In proofs which proceed by varying the rules of the game played by the
+% adversary and bounding the probability of it noticing at each step, game
+% names are usually typeset as $\G n$ for small numbers $n$.  The command
+% \syntax{"\\G{"<n>"}"} command does this typesetting.  There's an optional
+% argument, which is a symbol to write instead of `G'.
+%
+% \DescribeMacro\Func
+% \DescribeMacro\Perm
+% When dealing with finite PRFs and PRPs, we need to talk about the set of
+% \emph{all} functions (or permutations) over particular sets, usually
+% $n$-vectors of bits.  The macros \syntax{"\\Func{"<l>"}{"<L>"}"} and
+% \syntax{"\\Perm{"<L>"}"} typeset $\Func{l}{L}$ and $\Perm{L}$ respectively,
+% and are intended to denote the sets of all functions $F\colon \{0, 1\}^l
+% \to \{0, 1\}^L$ and all permutations $\Pi\colon \{0, 1\}^L \to \{0, 1\}^L$
+% respectively. 
+%
+% \DescribeMacro\PKCS
+% Finally, the |\PKCS| macro typesets `\PKCS{$n$}', allowing you to name RSA
+% Security Inc.'s Public Key Cryptography Standards in a relatively nice way.
+% 
+% \implementation
+%
+%
+%^^A-------------------------------------------------------------------------
+% \section{Implementation}
+%
+% We need David Carlisle's handy \package{xspace} package and the AMS |\text|
+% command.
+%
+%    \begin{macrocode}
+%<*package>
+\RequirePackage{amstext}
+\RequirePackage{xspace}
+%    \end{macrocode}
+
+% \subsection{Algorithm typsetting}
+%
+% \begin{macro}{\cookie}
+% \begin{macro}{\kw}
+% \begin{macro}{\id}
+%
+% First, some style issues.  Note the |\xspace| at the end of |\kw|.
+%
+%    \begin{macrocode}
+\def\cookie#1{\text{\normalfont\sffamily\/#1\/}}
+\def\kw#1{\text{\normalfont\bfseries\/#1\/}\xspace}
+\def\id#1{\text{\normalfont\itshape\/#1\/}}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\getsr}
+% \begin{macro}{\inr}
+%
+% The symbols for random selection and membership are fairly easy.  The `R'
+% over $\getsr$ is actually in scriptscript style, because that seems to look
+% nicer.
+%
+%    \begin{macrocode}
+\def\inr{\mathrel{\in_R}}
+\def\getsr{\mathrel{\mathop{\gets}\limits^{\scriptscriptstyle R}}}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\Xid}
+%
+% The compound identifiers set by |\Xid| are easy.
+%
+%    \begin{macrocode}
+\def\Xid#1#2{\id{$#1$-#2}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% Now for the various keywords.  These are trivial, but useful.
+%
+%    \begin{macrocode}
+\def\RETURN{\kw{return}}
+\def\IF{\kw{if}}
+\def\THEN{\kw{then}}
+\def\ELSE{\kw{else}}
+\def\REPEAT{\kw{repeat}}
+\def\WHILE{\kw{while}}
+\def\UNTIL{\kw{until}}
+\def\FOREVER{\kw{forever}}
+\def\DO{\kw{do}}
+\def\FOR{\kw{for}}
+\def\FOREACH{\kw{for\,each}}
+\def\FROM{\kw{from}}
+\def\IN{\kw{in}}
+\def\TO{\kw{in}}
+\def\ABORT{\kw{abort}}
+\def\PARSE{\kw{parse}}
+\def\AS{\kw{as}}
+%    \end{macrocode}
+%
+% \begin{environment}{program}
+% \begin{macro}{\next}
+% \begin{macro}{\newline}
+%
+% Now for the \env{program} environment and its associated twiddling.  This
+% is actually a little fiddly.
+%
+% At the beginning, if we're in vertical mode -- i.e., there was a paragraph
+% break before the start of the environment -- then remember this, because it
+% affects the typesetting at the end.  Set up |\next| and |\newline| in terms
+% of the underlying machinery, and start a row of algorithm.
+%
+%    \begin{macrocode}
+\def\program{%
+  \normalfont%
+  \@tempswatrue\ifvmode\@tempswafalse\fi%
+  \def\next{\program@end\vrule\program@begin}%
+  \def\newline{\program@endline\medskip\program@startline}%
+  \begingroup\trivlist%
+  \advance\@topsep-\parskip\advance\@topsepadd-\parskip\item%
+  \program@startline%
+}
+%    \end{macrocode}
+%
+% Ending the environment is easy-ish.  We stop the current row and leave a
+% gap, matching the one that |\poem@startline| adds automatically.  If we
+% were initially in horizontal mode, then don't indent the next paragraph,
+% and ignore spaces after the |\end{program}| command.
+%
+%    \begin{macrocode}
+\def\endprogram{%
+  \program@endline\endtrivlist\endgroup%
+  \if@tempswa\noindent\fi\@ignoretrue%
+}
+%    \end{macrocode}
+%
+% Now for the guts of all of this.  First of all, we turn to the typesetting
+% of a column, which is just hfil glue, a \env{minipage} with zero width and
+% a \env{tabbing} environment.  The first tab is already set 1\,em in from
+% the margin.  We use \env{minipage} to set up the list parameters correctly
+% and manage the initial and final spacing.  The zero width is OK because
+% \env{tabbing} sets a list of hboxes rather than using outer horizontal
+% mode, so the |\hsize| is irrelevant.
+%
+%    \begin{macrocode}
+\def\program@begin{%
+  \begingroup%
+  \hfil%
+  \minipage[t]\z@%
+    \topsep\z@%
+    \itemsep\z@%
+    \parskip\z@\parsep\z@%
+    \partopsep\z@%
+    \tabbing%
+%    \end{macrocode}
+%
+% This is rather messy.  The |\item| from the \env{trivlist} messes up the
+% spacing.  We remove the box, and fix |\prevdepth| to ensure that there's no
+% glue at the top.
+%
+%    \begin{macrocode}
+      \quad\=dummy\\%
+      \@stopfield%
+      \begingroup%
+        \setbox\z@\lastbox\unskip\unskip\unskip\setbox\z@\lastbox\unskip%
+      \endgroup%
+      \prevdepth-\@m\p@%
+      \@startfield\strut%
+}
+%    \end{macrocode}
+%
+% Ending a program has no discernable subtlety.
+%
+%    \begin{macrocode}
+\def\program@end{%
+    \endtabbing%
+  \endminipage%
+  \hfil%
+  \endgroup%
+}
+%    \end{macrocode}
+%
+% Finally, the row setting is fairly easy.  We have to ensure that we obey
+% the prevailing list parameters.
+%
+%    \begin{macrocode}
+\def\program@startline{%
+  \moveright\@totalleftmargin%
+  \hb@xt@\linewidth\bgroup%
+    \program@begin%
+}
+\def\program@endline{%
+    \program@end%
+  \egroup%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{environment}
+%
+% \subsection{Other stuff}
+%
+% \begin{macro}{\Thing}
+% \begin{macro}{\Succ}
+% \begin{macro}{\Adv}
+% \begin{macro}{\InSec}
+% \begin{macro}{\Expt}
+%
+% Typesetting |\Thing| is easy.  This acts as a style hook for the rest of
+% these things..
+%
+%    \begin{macrocode}
+\def\Thing#1#2#3{\text{\normalfont\bfseries#1}^{\text{\normalfont#2}}_{#3}}
+%    \end{macrocode}
+%
+% And now here they are.
+%
+%    \begin{macrocode}
+\def\Succ{\Thing{Succ}}
+\def\Adv{\Thing{Adv}}
+\def\InSec#1{\Thing{InSec}{#1}{}}
+\def\Expt{\Thing{Expt}}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\G}
+%
+% The name of a game is typeset simply as
+%
+%    \begin{macrocode}
+\newcommand\G[2][G]{\mathbf{#1}_{#2}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\Func}
+% \begin{macro}{\Perm}
+%
+% The finite sets of functions and permutations are just a style choice.  We
+% choose to buck the standard trends and use caligraphic letters.
+%
+%    \begin{macrocode}
+\def\Func#1#2{\mathcal{F}^{#1,#2}}
+\def\Perm#1{\mathcal{P}^{#1}}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\PKCS}
+%
+% Finally, I find that \PKCS{$n$} looks best typeset like this:
+%
+%    \begin{macrocode}
+\def\PKCS#1{PKCS\,\##1}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \vskip\parskip\vbox{ ^^A The best way I could find of keeping this lot
+%                      ^^A together, I'm afraid.
+% That's all there is.  Byebye.
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+% \nopagebreak
+%
+% \hfill Mark Wooding, \today
+% }
+% \Finale
+%
+\endinput
diff --git a/doafter.dtx b/doafter.dtx
new file mode 100644
index 0000000..f1ec3f2
--- /dev/null
+++ b/doafter.dtx
@@ -0,0 +1,519 @@
+% \begin{meta-comment}
+%
+% $Id: doafter.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
+%
+% Insert tokens to be read after a group has been processed
+%
+% (c) 1996 Peter Schmitt and Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: doafter.dtx,v $
+% Revision 1.1  2002/02/03 20:49:03  mdw
+% Checkin for new build system.
+%
+% Revision 1.2  1996/11/19 20:49:08  mdw
+% Entered into RCS
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% doafter package -- insert a token really after a group
+%% Copyright (c) 1996 Peter Schmitt and Mark Wooding
+%<*package>
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%</package>
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preamble>
+%<+latex2e>\NeedsTeXFormat{LaTeX2e}
+%<+latex2e>\ProvidesPackage{doafter}
+%<+latex2e>                [1996/05/08 1.2 Aftergroup hacking (PS/MDW)]
+% \end{meta-comment}
+%
+% \CheckSum{259}
+%\iffalse
+%<*package>
+%\fi
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%\iffalse
+%</package>
+%\fi
+%
+% \begin{meta-comment} <driver>
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{doafter}
+\author{Peter Schmitt\thanks{%
+  Peter came up with the basic implementation after I posed the problem
+  in the \texttt{comp.text.tex} newsgroup.  I fixed some really piddly little
+  things, to improve it a bit, wrote the documentation, and turned the code
+  into a nice \package{doc}ced package.  Then Peter gave me an updated
+  version, and I upgraded this from memory.  Then he gave me some more tweaks
+  which I haven't incorporated.}
+  \and Mark Wooding}
+\def\author#1{}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+% \section{Description}
+%
+% \subsection{What it's all about}
+%
+% \DescribeMacro{\doafter}
+% It's common for the \TeX\ primitive |\aftergroup| to be used to `tidy up'
+% after a group.  For example, \LaTeX's colour handling uses this to insert
+% appropriate |\special|s when the scope of a colour change ends.  This
+% causes several problems, though; for example, extra grouping must be added
+% within boxes to ensure that the |\special|s don't `leak' out of their box
+% and appear in odd places in the document.  \LaTeX\ usually solves this
+% problem by reading the box contents as an argument, although this isn't
+% particularly desirable.  The |\doafter| macro provided here will solve the
+% problem in a different way, by allowing a macro to regain control after
+% all the |\aftergroup| things have been processed.
+%
+% The macro works like this:
+% \begin{grammar}
+% <doafter-cmd> ::= \[[
+%   "\\doafter" <token> <group>
+% \]]
+% \end{grammar}
+% The \<token> can be any token you like, except an explicit braces, since
+% it's read as an undelimited macro argument.  The \<group> is a normal
+% \TeX\ group, surrounded by either implicit or explicit braces, or by
+% |\begingroup| and |\endgroup| tokens.  Once the final closing token of the
+% \<group> is read, and any tokens saved up by |\aftergroup| have been
+% processed, the \<token> is inserted and processed.  Under normal
+% circumstances, this will be a macro.
+%
+% There are some subtle problems with the current implementation, which you
+% may need to be aware of:
+%
+% \begin{itemize}
+%
+% \item Since we're inserting things after all the |\aftergroup| tokens,
+%       those tokens might read something they're not expecting if they try
+%       to look ahead at the text after the group (e.g., with |\futurelet|).
+%       This is obviously totally unavoidable.
+%
+% \item Implicit braces (like |\bgroup| and |\egroup|) inserted using
+%       |\aftergroup| may be turned into \emph{explicit} $|{|_1$ and $|}|_2$
+%       characters within a |\doafter| group.  This can cause probems under
+%       very specialised circumstances.  The names |\bgroup| and |\egroup|
+%       are treated specially, and they will work normally (remaining as
+%       implicit braces).  This should minimise problems caused by this
+%       slight difference.  (This only applies to the last |\aftergroup|
+%       token in a group.)
+%
+% \item To handle the |\aftergroup| tokens properly, |\doafter| has to insert
+%       some |\aftergroup| tokens of its own.  It will then process the
+%       other tokens some more, and set them up to be read again.  This does
+%       mean that after the group ends, some assignments and other `stomach
+%       operations' will be performed, which may cause problems in
+%       alignments and similar places.
+%
+% \end{itemize}
+%
+%
+% \subsection{Package options}
+%
+% There are a fair few \textsf{docstrip} options provided by this packge:
+%
+% \begin{description}
+% \item [driver] extracts the documentation driver.  This isn't usually
+%       necessary.
+% \item [package] extracts the code as a standalone package, formatted for
+%       either \LaTeXe\ or Plain~\TeX.
+% \item [latex2e] inserts extra identification code for a \LaTeXe\ package.
+% \item [plain] inserts some extra code for a Plain \TeX\ package.
+% \item [macro] just extracts the raw code, for inclusion in another package.
+% \item [test] extracts some code for testing the current implementation.
+% \end{description}
+%
+%
+% \implementation
+%
+% \section{Implementation}
+%
+% \subsection{The main macro}
+%
+% We start outputting code here.  If this is a Plain~\TeX\ package, we must
+% make \lit{@} into a letter.
+%
+%    \begin{macrocode}
+%<*macro|package>
+%<+plain>\catcode`\@=11
+%    \end{macrocode}
+%
+% \begin{macro}{\doafter}
+%
+% The idea is to say \syntax{"\\doafter" <token> <group>} and expect the
+% \synt{token} to be processed after the group has finished its stuff,
+% even if it contains |\aftergroup| things.  My eternal gratitude goes to
+% Peter Schmitt, who came up with most of the solution implemented here;
+% I've just tidied up some very minor niggles and things later.
+%
+% Let's start with some preamble.  I'll save the (hopefully) primitive
+% |\aftergroup| in a different token.
+%
+%    \begin{macrocode}
+\let\@@aftergroup\aftergroup
+%    \end{macrocode}
+%
+% Now to define the `user' interface.  It takes a normal undelimited
+% argument, although this must be a single token; otherwise eveything will
+% go wrong.  It assumes that the token following is some kind of group
+% opening thing (an explicit or implicit character with catcode~1, or
+% a |\begingroup| token).  To make this work, I'll save the token,
+% together with an |\@@aftergroup| (to save an |\expandafter| later) in
+% a temporary macro which no-one will mind me using, and then look ahead at
+% the beginning-group token.
+%
+%    \begin{macrocode}
+\def\doafter#1{%
+  \def\@tempa{\@@aftergroup#1}%
+  \afterassignment\doafter@i\let\@let@token%
+}
+%    \end{macrocode}
+%
+% I now have the token in |\@let@token|, so I'll put that in.  I'll then
+% make |\aftergroup| do my thing rather than the normal thing, and queue
+% the tokens |\@prepare@after| and the |\doafter| argument for later use.
+%
+%    \begin{macrocode}
+\def\doafter@i{%
+  \@let@token%
+  \let\aftergroup\@my@aftergroup%
+  \@@aftergroup\@prepare@after\@tempa%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\@my@aftergroup}
+%
+% Now the cleverness begins.  We keep two macros (Peter's original used
+% count registers) which keep counts of the numbers of |\aftergroup|s,
+% both locally and globally.  Let's call the local counter~$n$ and the
+% global one $N$.  Every time we get a call to our |\aftergroup| hack,
+% we set~$n := n+1$ and~$N := n$, and leave the token given to us for later
+% processing.  When we actually process an |\aftergroup| token properly,
+% set~$N := N-1$ to indicate that it's been handled; when they're all done,
+% we'll have $N=n$, which is exactly what we'd have if there weren't any
+% to begin with.
+%
+%    \begin{macrocode}
+\def\ag@cnt@local{0 }
+\let\ag@cnt@global\ag@cnt@local
+%    \end{macrocode}
+%
+% Now we come to the definition of my version of |\aftergroup|.  I'll just
+% add the token |\@after@token| before every |\aftergroup| token I find.
+% This means there's two calls to |\aftergroup| for every one the user makes,
+% but these things aren't all that common, so it's OK really.  I'll also
+% bump the local counter, and synchronise them.
+%
+%    \begin{macrocode}
+\def\@my@aftergroup{%
+  \begingroup%
+    \count@\ag@cnt@local%
+    \advance\count@\@ne%
+    \xdef\ag@cnt@global{\the\count@\space}%
+  \endgroup%
+  \let\ag@cnt@local\ag@cnt@global%
+  \@@aftergroup\@after@token\@@aftergroup%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% Now what does |\@after@token| we inserted above actually do?  Well, this
+% is more exciting.  There are actually two different variants of the
+% macro, which are used at different times.
+%
+% \begin{macro}{\@after@token}
+%
+% The default |\@after@token| starts a group, which will `catch'
+% |\aftergroup| tokens which I throw at it.  I put the two counters into
+% some scratch count registers.  (There's a slight problem here: Plain \TeX\
+% only gives us one.  For the sake of evilness I'll use |\clubpenalty| as the
+% other one.  Eeeek.)  I then redefine |\@after@token| to the second
+% variant, and execute it.  The |\@start@after@group| macro starts the
+% group, because this code is shared with |\@prepare@after| below.
+%
+%    \begin{macrocode}
+\def\@after@token{%
+  \@start@after@group%
+  \@after@token%
+}
+\def\@start@after@group{%
+  \begingroup%
+  \count@\ag@cnt@global%
+  \clubpenalty\ag@cnt@local%
+  \let\@after@token\@after@token@i%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\@after@token@i}
+%
+% I have $|\count@| = N$ and $|\@tempcnta| = n$.  I'll decrement~$N$,
+% and if I have $N = n$, I know that this is the last token to do, so I
+% must insert an |\@after@all| after the token.  This will close the group,
+% and maybe insert the original |\doafter| token if appropriate.
+%
+%    \begin{macrocode}
+\def\@after@token@i{%
+  \advance\count@\m@ne%
+  \ifnum\count@=\clubpenalty%
+    \global\let\ag@cnt@global\ag@cnt@local%
+    \expandafter\@after@aftertoken\expandafter\@after@all%
+  \else%
+    \expandafter\@@aftergroup%
+  \fi%
+}
+%    \end{macrocode}
+%
+% Finally, establish a default meaning for |\@after@all|.
+%
+%    \begin{macrocode}
+\let\@after@all\endgroup
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\@prepare@after}
+%
+% If this group is handled by |\doafter|, then the first |\aftergroup| token
+% isn't |\@after@token|; it's |\@prepare@after|.
+%
+% There are some extra cases to deal with:
+% \begin{itemize}
+% \item If $N=n$ then there were no |\aftergroup| tokens, so we have an easy
+%       job.  I'll just let the token do its stuff directly.
+% \item Otherwise, $N>n$, and there are |\aftergroup| tokens.  I'll open
+%       the group, and let |\@after@token| do all the handling.
+% \end{itemize}
+%
+%    \begin{macrocode}
+\def\@prepare@after{%
+  \ifx\ag@cnt@local\ag@cnt@global\else%
+    \expandafter\@prepare@after@i%
+  \fi%
+}
+\def\@prepare@after@i#1{%
+  \@start@after@group%
+  \def\@after@all{\@@aftergroup#1\endgroup}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\@after@aftertoken}
+%
+% This is where all the difficulty lies.  The next token in the stream is
+% an |\aftergroup| one, which could be more or less anything.  We have an
+% argument, which is some code to do \emph{after} the token has been
+% |\aftergroup|ed.
+%
+% If the token is anything other than a brace (i.e., an  explicit character
+% of category~1 or~2) then I have no problem; I can scoop up the token with
+% an undelimited macro argument.  But the only way I can decide if this token
+% is a brace (nondestructively) is with |\futurelet|, which makes the token
+% implicit, so I can't decide whether it's really dangerous.
+%
+% There is a possible way of doing this\footnote{Due to Peter Schmitt,
+% again.} which relates to nobbling the offending token with |\string| and
+% sifting through the results.  The problem here involves scooping up all the
+% tokens of a |\string|ed control sequence, which may turn out to be
+% `|\csname\endcsname|' or something equally horrid.
+%
+% The solution I've used is much simpler: I'll change |\bgroup| and |\egroup|
+% to stop them from being implicit braces before comparing.
+%
+%    \begin{macrocode}
+\def\@after@aftertoken#1{%
+  \let\bgroup\relax\let\egroup\relax%
+  \toks@{#1}%
+  \futurelet\@let@token\@after@aftertoken@i%
+}
+\def\@after@aftertoken@i{%
+  \ifcat\noexpand\@let@token{%
+    \@@aftergroup{%
+  \else\ifcat\noexpand\@let@token}%
+    \@@aftergroup}%
+  \else%
+    \def\@tempa##1{\@@aftergroup##1\the\toks@}%
+    \expandafter\expandafter\expandafter\@tempa%
+  \fi\fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% Phew!
+%
+%    \begin{macrocode}
+%<+plain>\catcode`\@=12
+%</macro|package>
+%    \end{macrocode}
+%
+% \subsection{Test code}
+%
+% The following code gives |\doafter| a bit of a testing.  It's based on
+% the test suite I gave to comp.text.tex, although it's been improved a
+% little since then.
+%
+% The first thing to do is define a control sequence with an \lit{@} sign
+% in its name, so we can test catcode changes.  This also hides an
+% |\aftergroup| within a macro, making life more difficult for prospective
+% implementations.
+%
+%    \begin{macrocode}
+%<*test>
+\catcode`\@=11
+\def\at@name{\aftergroup\saynine}
+\def\saynine{\say{ix}}
+\catcode`\@=12
+%    \end{macrocode}
+%
+% Now define a command to write a string to the terminal.  The name will
+% probably be familiar to REXX hackers.
+%
+%    \begin{macrocode}
+\def\say{\immediate\write16}
+%    \end{macrocode}
+%
+% Test one: This is really easy; it just tests that the thing works at all.
+% If your implementation fails this, it's time for a major rethink.
+%
+%    \begin{macrocode}
+\say{Test one... (1--2)}
+\def\saytwo{\say{ii}}
+\doafter\saytwo{\say{i}}
+%    \end{macrocode}
+%
+% Test two: Does |\aftergroup| work?
+%
+%    \begin{macrocode}
+\say{Test two... (1--4)}
+\def\saythree{\say{iii}}
+\def\sayfour{\say{iv}}
+\doafter\sayfour{\say{i}\aftergroup\saythree\say{ii}}
+%    \end{macrocode}
+%
+% Test three: Test braces and |\iffalse| working as they should.  Several
+% proposed solutions based on |\write|ing the group to a file get upset by
+% this test, although I forgot to include it in the torture test.  It also
+% tests whether literal braces can be |\aftergroup|ed properly.  (Added a new
+% test here, making sure that |\bgroup| is left as an implicit token.)
+%
+%    \begin{macrocode}
+\say{Test three... (1--4, `\string\bgroup', 5)}
+\def\sayfive{\say{v}}
+\doafter\sayfive{%
+  \say{i}%
+  \aftergroup\say%
+  \aftergroup{%
+  \aftergroup\romannumeral\aftergroup3%
+  \aftergroup}%
+  \iffalse}\fi%
+  \aftergroup\def%
+  \aftergroup\sayfouretc%
+  \aftergroup{%
+  \aftergroup\say%
+  \aftergroup{%
+  \aftergroup i%
+  \aftergroup v%
+  \aftergroup}%
+  \aftergroup\say%
+  \aftergroup{%
+  \aftergroup\string%
+  \aftergroup\bgroup%
+  \aftergroup}%
+  \aftergroup}%
+  \aftergroup\sayfouretc%
+  \say{ii}%
+}
+%    \end{macrocode}
+%
+% Test four: Make sure the implementation isn't leaking things.  This just
+% makes sure that |\aftergroup| is its normal reasonable self.
+%
+%    \begin{macrocode}
+\say{Test four... (1--3)}
+{\say{i}\aftergroup\saythree\say{ii}}
+%    \end{macrocode}
+%
+% Test five: Nesting, aftergroup, catcodes, grouping.  This is the `torture'
+% test I gave to comp.text.tex, slightly corrected (oops) and amended.  It
+% ensures that nested groups and |\doafter|s work properly (the latter is
+% actually more likely than might be imagined).
+%
+%    \begin{macrocode}
+\say{Test five... (1--14)}
+\def\sayten{\say{x}}
+\def\saythirteen{\say{xiii}}
+\def\sayfourteen{\say{xiv}}
+\doafter\sayfourteen\begingroup%
+  \say{i}%
+  {\say{ii}\aftergroup\sayfour\say{iii}}%
+  \def\saynum{\say{viii}}%
+  \doafter\sayten{%
+    \say{v}%
+    \def\saynum{\say{vii}}%
+    \catcode`\@=11%
+    \aftergroup\saynum%
+    \say{vi}%
+    \at@name%
+    \saynum%
+  }%
+  \say{xi}%
+  \aftergroup\saythirteen%
+  \say{xii}%
+\endgroup
+\end
+%</test>
+%    \end{macrocode}
+%
+% That's it.  All present and correct.
+%
+% \Finale
+%
+\endinput
diff --git a/doafter.tex b/doafter.tex
new file mode 100644
index 0000000..2e9cabb
--- /dev/null
+++ b/doafter.tex
@@ -0,0 +1,113 @@
+%%
+%% This is file `doafter.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% doafter.dtx  (with options: `package,plain')
+%% 
+%% IMPORTANT NOTICE
+%%
+%% doafter package -- insert a token really after a group
+%% Copyright (c) 1996 Peter Schmitt and Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+\catcode`\@=11
+\let\@@aftergroup\aftergroup
+\def\doafter#1{%
+  \def\@tempa{\@@aftergroup#1}%
+  \afterassignment\doafter@i\let\@let@token%
+}
+\def\doafter@i{%
+  \@let@token%
+  \let\aftergroup\@my@aftergroup%
+  \@@aftergroup\@prepare@after\@tempa%
+}
+\def\ag@cnt@local{0 }
+\let\ag@cnt@global\ag@cnt@local
+\def\@my@aftergroup{%
+  \begingroup%
+    \count@\ag@cnt@local%
+    \advance\count@\@ne%
+    \xdef\ag@cnt@global{\the\count@\space}%
+  \endgroup%
+  \let\ag@cnt@local\ag@cnt@global%
+  \@@aftergroup\@after@token\@@aftergroup%
+}
+\def\@after@token{%
+  \@start@after@group%
+  \@after@token%
+}
+\def\@start@after@group{%
+  \begingroup%
+  \count@\ag@cnt@global%
+  \clubpenalty\ag@cnt@local%
+  \let\@after@token\@after@token@i%
+}
+\def\@after@token@i{%
+  \advance\count@\m@ne%
+  \ifnum\count@=\clubpenalty%
+    \global\let\ag@cnt@global\ag@cnt@local%
+    \expandafter\@after@aftertoken\expandafter\@after@all%
+  \else%
+    \expandafter\@@aftergroup%
+  \fi%
+}
+\let\@after@all\endgroup
+\def\@prepare@after{%
+  \ifx\ag@cnt@local\ag@cnt@global\else%
+    \expandafter\@prepare@after@i%
+  \fi%
+}
+\def\@prepare@after@i#1{%
+  \@start@after@group%
+  \def\@after@all{\@@aftergroup#1\endgroup}%
+}
+\def\@after@aftertoken#1{%
+  \let\bgroup\relax\let\egroup\relax%
+  \toks@{#1}%
+  \futurelet\@let@token\@after@aftertoken@i%
+}
+\def\@after@aftertoken@i{%
+  \ifcat\noexpand\@let@token{%
+    \@@aftergroup{%
+  \else\ifcat\noexpand\@let@token}%
+    \@@aftergroup}%
+  \else%
+    \def\@tempa##1{\@@aftergroup##1\the\toks@}%
+    \expandafter\expandafter\expandafter\@tempa%
+  \fi\fi%
+}
+\catcode`\@=12
+\endinput
+%%
+%% End of file `doafter.tex'.
diff --git a/exercise.dtx b/exercise.dtx
new file mode 100644
index 0000000..5b01925
--- /dev/null
+++ b/exercise.dtx
@@ -0,0 +1,555 @@
+% \begin{meta-comment}
+%
+% $Id: exercise.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
+%
+% Exercises
+%
+% (c) 2001 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: exercise.dtx,v $
+% Revision 1.1  2002/02/03 20:49:03  mdw
+% Checkin for new build system.
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% exercise package -- useful macros for setting exercises with answers
+%% Copyright (c) 2001 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%% 
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%% 
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software Foundation,
+%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preambles>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{exercise}
+%<+package>                [2001/09/21 1.0 Exercies with answers]
+% \end{meta-comment}
+%
+% \CheckSum{236}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{exercise}
+\let\epsilon\varepsilon
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+%^^A-------------------------------------------------------------------------
+% \section{User guide}
+%
+% The \package{exercise} package allows you to typeset exercises and keep the
+% answers together with the questions in your source (so they don't get
+% lost) but typeset them all together at the end of your document.
+%
+% \subsection{Exercises and answers}
+%
+% \DescribeEnv{exercise}
+% Exercises are typset in an \env{exercise} environment.  This takes no
+% arguments.  There's a counter for exercises, named |exercise|, and you can
+% cross-reference exercises in the usual way.
+%
+% \DescribeMacro\answer
+% If you want to include an answer for your exercise, just say |\answer|
+% followed by your answer.  The rest of the text up to the end of the
+% \env{exercise} environment is considered to be the answer, and is stored
+% away until asked for.  This material can contain anything you like.  It
+% \emph{isn't} a moving argument.
+%
+% \begin{figure}
+%\begin{demo}[w]{The \env{exercise} environment}
+%\begin{exercise}
+%Show that if $F\colon \{0, 1\}^k \times \{0, 1\}^* \to \{0, 1\}^L$
+%is a $(t, q + 1, \epsilon)$-secure PRF, then $F$~is also a
+%$(t, q, \epsilon + 2^{-L})$-secure MAC.
+%\answer
+%Let~$A$ be an adversary attacking~$F$ as a MAC.  Consider the
+%adversary~$B$ \ldots
+%\end{exercise}
+%\end{demo}
+% \end{figure}
+%
+% \subsection{The answers file}
+%
+% \DescribeMacro\answrite
+% Answers are accumulated into a file, to be read later.  Additional material
+% can be added to the file using the |\answrite| macro, which just writes its
+% argument.  Note that this is a \emph{moving} argument, so fragile commands
+% need |\protect|ing.
+%
+% \DescribeMacro\exctrcheck
+% It's common to divide up the answers by section.  You can tell the package
+% to check a collection of counters and perform actions if they've changed
+% since last time, giving you a chance to write the correct decorations to
+% the answers file.  This is done by saying
+% \syntax{"\\exctrcheck{"<counter>"}{"<action>"}"}.  Then, each |\answer|
+% command checks to see if \<counter> has changed since last time, and if it
+% has, it does \<action>,  For example,
+%\begin{verbatim}
+%\exctrcheck{section}
+%  {\answrite{\protect\subsection*{Section \thesection}}}
+%\end{verbatim}
+% starts a new (unnumbered) subsection in the answers for each section in the
+% main document.
+%
+% \subsection{Style tweaks}
+%
+% The \env{exercise} environment is very simple, and can be easily rewritten
+% to fit in with your style preferences.  If you like exercises to look like
+% theorems, the easiest thing to do is say something like
+%\begin{verbatim}
+%\newtheorem{doexercise}[exercise]{\exercisename}
+%\renewenvironment{exercise}{\exfix\doexercise}{\enddoexercise}
+%\end{verbatim}
+% This makes the environment use the existing exercise counter.  If you don't
+% want that, say
+%\begin{verbatim}
+%\newtheorem{doexercise}[othercounter]{\exercisename}
+%\renewenvironment{exercise}{\exfix\doexercise}{\enddoexercise}
+%\let\theexercise\theothercounter
+%\end{verbatim}
+% and all will be well.
+%
+% \DescribeEnv{doanswer}
+% Answers are typeset in a \env{doanswer} environment, which is given one
+% argument: the exercise number (as set by |\theexercise|).  This can be
+% modified to do whatever you like.
+%
+% \DescribeMacro\exfix
+% The |\exfix| is a convenient hook which is run both in the \env{exercise}
+% and \env{doanswer} environments by default.  The current implementation
+% just skips a level of \env{enumerate} depth, which usually means that
+% \env{enumerate} lists will go (a), (b), (c), \ldots\ rather than 1, 2, 3,
+% \ldots
+%
+% \subsection{Lists in paragraphs}
+%
+% \DescribeEnv{parenum}
+% Answers to subparts tend to be compressed together into a single
+% paragraph.  It's nice, when you do this, not to have to worry about losing
+% your numbering of subparts.  The \env{parenum} environment provides an
+% enumerated list in a paragraph.  So, for example, you can say something
+% like this.
+%\begin{demo}[w]{Example of \env{parenum}}
+%\begin{exercise}
+%A PRG $g\colon \{0, 1\}^k \to \{0, 1\}^L$ is \emph{trivial} if
+%$k \ge L$.
+%\begin{enumerate}
+%\item Show that trivial PRGs exist.
+%\item Show that a non-trivial $(t, \epsilon)$-secure PRG is a
+%  $(t, \epsilon + 2^{k-L})$-secure one-way function.
+%\end{enumerate}
+%\answer
+%\begin{parenum}
+%\item The identity function is a trivial PRG: the real and random
+%  games are identically distributed.
+%\item Let~$A$ be an adversary attempting to invert~$g$: then we
+%  can construct a distinguisher~$B$ as follows \ldots
+%\end{parenum}
+%\end{exercise}
+%\end{demo}
+%
+% \subsection{And finally}
+%
+% \DescribeMacro\answers
+% In order to extract your answers, say |\answers|.
+%\begin{demo}[w]{The \texttt{\string\answers} command}
+%\section*{Answers}
+%\answers
+%\end{demo}
+%
+% \implementation
+% 
+%
+%^^A-------------------------------------------------------------------------
+% \section{Implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+% \subsection{Initialization}
+%
+% The \textsf{within} option is handled by the \package{keyval} package.
+%
+%    \begin{macrocode}
+\RequirePackage{keyval}
+%    \end{macrocode}
+%
+% \begin{macro}{\ex@within}
+%
+% When the \textsf{within} option is seen, we set a command |\ex@within| to
+% the correct code, to be executed later when we've made our minds up.
+%
+%    \begin{macrocode}
+\let\ex@within\relax
+\define@key{ex}{within}{%
+  \def\ex@within{%
+    \@addtoreset{exercise}{#1}%
+    \toks@\expandafter{\csname the#1\expandafter\endcsname%
+                       \expandafter.\theexercise}%
+    \edef\theexercise{\the\toks@}%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ex@opts}
+%
+% The |\ex@opts| macro just runs the \package{keyval} kit to parse an option
+% string.
+%
+%    \begin{macrocode}
+\def\ex@opts{\setkeys{ex}}
+%    \end{macrocode}
+% \end{macro}
+%
+% Now do the options thing.
+%
+%    \begin{macrocode}
+\DeclareOption*{\expandafter\ex@opts\expandafter{\CurrentOption}}
+\ProcessOptions*
+%    \end{macrocode}
+%
+% Set up the |exercise| counter, and number it within some other sort of
+% counter as appropriate.
+%
+%    \begin{macrocode}
+\newcounter{exercise}\ex@within
+%    \end{macrocode}
+%
+% We also need the \package{sverb} package in order to do the delaying of the
+% answers.
+%
+%    \begin{macrocode}
+\RequirePackage{sverb}
+%    \end{macrocode}
+%
+% \subsection{Checking for counter changes}
+%
+% \begin{macro}{\ex@ctrcheck}
+%
+% The counter checking state is stored here.  It's initially empty.
+%
+%    \begin{macrocode}
+\def\ex@ctrcheck{}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\exctrcheck}
+%
+% Adding a counter to the check list is relatively easy.  We expand the
+% current list into a token register, add the new material to the end, and
+% put the list back in our macro using |\edef|.  The `last' value of the
+% counter is set to |\relax|, to force out the change on the next |\answer|.
+%
+%    \begin{macrocode}
+\def\exctrcheck#1#2{%
+  \toks@\expandafter{\ex@ctrcheck\ex@ctrdo{#1}{#2}}%
+  \edef\ex@ctrcheck{\the\toks@}%
+  \global\expandafter\let\csname ex@ctrlast@#1\endcsname\relax%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ex@ctrdo}
+%
+% Here we actually check to see whether a counter has changed and execute the
+% appropriate code.
+%
+%    \begin{macrocode}
+\def\ex@ctrdo#1#2{%
+  \edef\@tempa{\csname the#1\endcsname}%
+  \expandafter\ifx\csname ex@ctrlast@#1\endcsname\@tempa\else%
+    #2%
+    \global\expandafter\let\csname ex@ctrlast@#1\endcsname\@tempa%
+  \fi%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{The \env{exercise} environment}
+%
+% \begin{macro}{\exercisename}
+%
+% We store the string to print for each exercise in |\exercisename| as a
+% half-hearted attempt at internationalization.
+%
+%    \begin{macrocode}
+\providecommand\exercisename{Exercise}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\exfix}
+%
+% This is a dumping ground for style fixing common to both exercises and
+% answers.  Here, we bump on the \env{enum} depth counter, so that it skips
+% labelling with digits.
+%
+%    \begin{macrocode}
+\def\exfix{\advance\@enumdepth\@ne}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{exercise}
+%
+% This is pretty simple.  The environment is list-based, with the number set
+% in bold in a label.
+%
+%    \begin{macrocode}
+\def\exercise{%
+  \refstepcounter{exercise}%
+  \exfix%
+  \trivlist\advance\itemindent\labelsep%
+  \item[\textbf{\exercisename\ \theexercise}]%
+}
+\let\endexercise\endtrivlist
+%    \end{macrocode}
+% \end{environment}
+%
+% \subsection{Answers}
+%
+% We need a file in which to store our answers.
+%
+%    \begin{macrocode}
+\newwrite\ex@ansfile
+%    \end{macrocode}
+%
+% \begin{macro}{\ex@ansfilename}
+%
+% In case anyone has a better idea for a filename than our default, we
+% provide a hook.
+%
+%    \begin{macrocode}
+\def\ex@ansfilename{\jobname.ans}
+%    \end{macrocode}
+% \end{macro}
+%
+% We open the file at the end of the preamble, to give the user a chance to
+% say |\nofiles|, or change |\ex@ansfilename|.
+%
+%    \begin{macrocode}
+\AtBeginDocument{%
+  \if@filesw%
+    \immediate\openout\ex@ansfile=\ex@ansfilename\relax%
+    \answrite\relax%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \begin{macro}{\answrite}
+%
+% This writes stuff to the answers file.  We make sure that it's
+% appropriately protected, so that you can insert section headings and so on.
+%
+%    \begin{macrocode}
+\def\answrite#1{%
+  \if@filesw%
+    \begingroup%
+    \let\protect\@unexpandable@protect%
+    \immediate\write\ex@ansfile{#1}%
+    \endgroup%
+  \fi%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\answer}
+%
+% The |\answer| macro needs to read until the end of the enclosing
+% \env{exercise} environment (or whatever).
+%
+%    \begin{macrocode}
+\def\answer{\sv@readenv\ex@answer}
+%    \end{macrocode}
+%
+% Now for the main guts.
+%
+%    \begin{macrocode}
+\def\ex@answer#1#2{%
+  \begingroup%
+  \@bsphack%
+%    \end{macrocode}
+%
+% First of all, check to see whether any counters have changed.
+%
+%    \begin{macrocode}
+  \ex@ctrcheck%
+%    \end{macrocode}
+%
+% Start a \env{doanswer} environment in the file.
+%
+%    \begin{macrocode}
+  \answrite{\noexpand\begin{doanswer}{\theexercise}}%
+%    \end{macrocode}
+%
+% Set catcodes to be strange, and read lines one-at-a-time, writing them to
+% the file.  When finished, continue at |\ex@endanswer|.
+%
+%    \begin{macrocode}
+  \let\do\@makeother\dospecials%
+  \sv@safespc%
+  \sv@read{#1}\answrite{\ex@endanswer#2}%
+}
+%    \end{macrocode}
+%
+% When that's done, we wind up here.
+%
+%    \begin{macrocode}
+\def\ex@endanswer{%
+  \@esphack%
+  \answrite{\noexpand\end{doanswer}}%
+  \endgroup%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\answers}
+%
+% The |\answers| macro closes the file, makes sure that future
+% \env{exercise}s with answers cause an error, and reads in the file.
+%
+%    \begin{macrocode}
+\def\answers{%
+  \immediate\closeout\ex@ansfile%
+  \global\let\answrite\exerr@toolate%
+  \input{\ex@ansfilename}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{doanswer}
+%
+% A very simple environment.  We set the exercise number in bold and then
+% just write the text.
+%
+%    \begin{macrocode}
+\def\doanswer#1{%
+  \exfix%
+  \trivlist\advance\itemindent\labelsep%
+  \item[\textbf{#1}]%
+}
+\let\enddoanswer\endtrivlist
+%    \end{macrocode}
+% \end{environment}
+%
+% \subsection{Lists inside paragraphs}
+%
+% \begin{environment}{parlist}
+%
+% The \env{parlist} environment is a trimmed-down version of a normal list.
+% We todge the |\item| command, make |\list| and |\trivlist| make errors, and
+% do various normal list things. 
+%
+%    \begin{macrocode}
+\def\parlist#1#2{%
+  \let\@trivlist\exerr@parlist%
+  \def\@itemlabel{#1}%
+  \let\makelabel\relax%
+  \@nmbrlistfalse%
+  #2%
+  \let\item\pl@item%
+  \ignorespaces%
+}
+%    \end{macrocode}
+% \end{environment}
+%
+% \begin{macro}{\pl@item}
+%
+% This is the implementation of |\item| within a \env{parlist}.  The main
+% interesting point is the game with boxes, which has the objective of
+% extracting the text of the item, together with any style changes set by
+% |\makelabel|, but without any stupid bits of glue, or |\llap| or anything
+% like that.
+%
+%    \begin{macrocode}
+\def\pl@item{\@ifnextchar[\pl@item@i{\pl@item@i[\@itemlabel]}}
+\def\pl@item@i[#1]{%
+  \if@nmbrlist\refstepcounter{\@listctr}\fi%
+  \setbox\z@\hbox{\makelabel{\global\setbox\@ne\hbox{#1}}}%
+  \ifvmode\leavevmode\else\unskip\hskip1em\fi\box\@ne~\ignorespaces%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\useparlist}
+%
+% We just set the \env{list} environment to use \env{parlist}.
+%
+%    \begin{macrocode}
+\def\useparlist{\let\list\parlist\let\endlist\relax}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{parenum}
+%
+% Very simple, this.  Note that we don't run |\endenumerate|, because that's
+% |\let| to |\endlist|.
+%
+%    \begin{macrocode}
+\def\parenum{\useparlist\enumerate}
+\let\endparenum\endparlist
+%    \end{macrocode}
+% \end{environment}
+%
+% \subsection{Errors}
+%
+%    \begin{macrocode}
+\def\exerr@toolate{%
+  \PackageError{exercise}{Too late now for \string\answrite}{%
+    You can't write answers after you've read the file in.  I've^^J%
+    ignored the text you attempted to write.  This is why answers^^J%
+    go at the end of a book!%
+  }%
+}
+\def\exerr@parlist{%
+  \PackageError{exercise}{You can't nest a `list' inside a `parlist'.}{%
+    I've found a `list' or `trivlist' environment nested inside^^J%
+    a `parlist'.  This isn't allowed.%
+  }%
+}
+%</package>
+%    \end{macrocode}
+%
+% Done.
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
diff --git a/footnote.dtx b/footnote.dtx
new file mode 100644
index 0000000..07dac84
--- /dev/null
+++ b/footnote.dtx
@@ -0,0 +1,702 @@
+% \begin{meta-comment}
+%
+% $Id: footnote.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
+%
+% Save footnotes around boxing environments and things
+%
+% (c) 1996 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: footnote.dtx,v $
+% Revision 1.1  2002/02/03 20:49:03  mdw
+% Checkin for new build system.
+%
+% Revision 1.13  1997/01/28 19:45:16  mdw
+% Fixed stupid bug in AMS environment handling which stops the thing from
+% working properly if you haven't included amsmath.  Doh.
+%
+% Revision 1.12  1997/01/18 00:45:37  mdw
+% Fix problems with duplicated footnotes in broken AMS environments which
+% typeset things multiple times.  This is a nasty kludge.
+%
+% Revision 1.11  1996/11/19 20:50:05  mdw
+% Entered into RCS
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% footnote package -- Save footnotes around boxing environments
+%% Copyright (c) 1996 Mark Wooding
+%<*package>
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%</package>
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preamble>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{footnote}
+%<+package>                [1997/01/28 1.13 Save footnotes around boxes]
+% \end{meta-comment}
+%
+% \CheckSum{327}
+%\iffalse
+%<*package>
+%\fi
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%\iffalse
+%</package>
+%\fi
+%
+% \begin{meta-comment} <driver>
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{footnote}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+% \section{User guide}
+%
+% This package provides some commands for handling footnotes slightly
+% better than \LaTeX\ usually does; there are several commands and
+% environments (notably |\parbox|, \env{minipage} and \env{tabular}
+% \begin{footnote}
+%   The \package{mdwtab} package, provided in this distribution, handles
+%   footnotes correctly anyway; it uses an internal version of this package
+%   to do so.
+% \end{footnote})
+% which `trap' footnotes so that they can't escape and appear at the bottom
+% of the page.
+%
+% \DescribeEnv{savenotes}
+% The \env{savenotes} environment saves up any footnotes encountered within
+% it, and performs them all at the end.
+%
+% \DescribeMacro{\savenotes}
+% \DescribeMacro{\spewnotes}
+% If you're defining a command or environment, you can use the |\savenotes|
+% command to start saving up footnotes, and the |\spewnotes| command to
+% execute them all at the end.  Note that |\savenotes| and |\spewnotes|
+% enclose a group, so watch out.  You can safely nest the commands and
+% environments -- they work out if they're already working and behave
+% appropriately.
+%
+% \DescribeEnv{minipage*}
+% To help things along a bit, the package provides a $*$-version of the
+% \env{minipage} environment, which doesn't trap footnotes for itself (and
+% in fact sends any footnotes it contains to the bottom of the page, where
+% they belong).
+%
+% \DescribeMacro{\makesavenoteenv}
+% The new \env{minipage$*$} environment was created with a magic command
+% called |\makesavenoteenv|.  It has a fairly simple syntax:
+%
+% \begin{grammar}
+% <make-save-note-env-cmd> ::= \[[
+%   "\\makesavenoteenv"
+%   \begin{stack} \\ "[" <new-env-name> "]" \end{stack}
+%   "{" <env-name> "}"
+% \]]
+% \end{grammar}
+%
+% Without the optional argument, it redefines the named environment so that
+% it handles footnotes correctly.  With the optional argument, it makes
+% the new environment named by \<new-env-name> into a footnote-friendly
+% version of the \<env-name> environment.
+%
+% \DescribeMacro{\parbox}
+% The package also redefines the |\parbox| command so that it works properly
+% with footnotes.
+%
+% \DescribeEnv{footnote}
+% The other problem which people tend to experience with footnotes is that
+% you can't put verbatim text (with the |\verb| comamnd or the \env{verbatim}
+% environment) into the |\footnote| command's argument.  This package
+% provides a \env{footnote} \emph{environment}, which \emph{does} allow
+% verbatim things.  You use the environment just like you do the command.
+% It's really easy.  It even has an optional argument, which works the same
+% way.
+%
+% \DescribeEnv{footnotetext}
+% To go with the \env{footnote} environment, there's a \env{footnotetext}
+% environment, which just puts the text in the bottom of the page, like
+% |\footnotetext| does.
+%
+% There's a snag with these environments, though.  Some other nonstandard
+% environments, like \env{tabularx}, try to handle footnotes their own
+% way, because they won't work otherwise.  The way they do this is not
+% compatible with the way that the \env{footnote} and \env{footnotetext}
+% environments work, and you will get strange results if you try (there'll
+% be odd vertical spacing, and the footnote text may well be incorrect).
+% \begin{footnote}
+%   The solution to this problem is to send mail to David Carlisle persuading
+%   him to use this package to handle footnotes, rather than doing it his
+%   way.
+% \end{footnote}
+%
+% \implementation
+%
+% \section{Implementation}
+%
+% Most implementations of footnote-saving (in particular, that used in
+% the \package{tabularx} and \package{longtable} packages) use a token
+% list register to store the footnote text, and then expand it when whatever
+% was preventing footnotes (usually a vbox) stops.  This is no good at all
+% if the footnotes contain things which might not be there by the time the
+% expansion occurs.  For example, references to things in temporary boxes
+% won't work.
+%
+% This implementation therefore stores the footnotes up in a box register.
+% This must be just as valid as using tokens, because all I'm going to do
+% at the end is unbox the box).
+%
+%    \begin{macrocode}
+%<*macro|package>
+\ifx\fn@notes\@@undefined%
+  \newbox\fn@notes%
+\fi
+%    \end{macrocode}
+%
+% I'll need a length to tell me how wide the footnotes should be at the
+% moment.
+%
+%    \begin{macrocode}
+\newdimen\fn@width
+%    \end{macrocode}
+%
+% Of course, I can't set this up until I actually start saving footnotes.
+% Until then I'll use |\columnwidth| (which works in \package{multicol}
+% even though it doesn't have any right to).
+%
+%    \begin{macrocode}
+\let\fn@colwidth\columnwidth
+%    \end{macrocode}
+%
+% And now a switch to remember if we're already handling footnotes,
+%
+%    \begin{macrocode}
+\newif\if@savingnotes
+%    \end{macrocode}
+%
+%
+% \subsection{Building footnote text}
+%
+% I need to emulate \LaTeX's footnote handling when I'm putting the notes
+% into my box; this is also useful in the verbatim-in-footnotes stuff.
+%
+% \begin{macro}{\fn@startnote}
+%
+% Here's how a footnote gets started.  Most of the code here is stolen
+% from |\@footnotetext|.
+%
+%    \begin{macrocode}
+\def\fn@startnote{%
+  \hsize\fn@colwidth%
+  \interlinepenalty\interfootnotelinepenalty%
+  \reset@font\footnotesize%
+  \floatingpenalty\@MM% Is this right???
+  \@parboxrestore%
+  \protected@edef\@currentlabel{\csname p@\@mpfn\endcsname\@thefnmark}%
+  \color@begingroup%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\fn@endnote}
+%
+% Footnotes are finished off by this macro.  This is the easy bit.
+%
+%    \begin{macrocode}
+\let\fn@endnote\color@endgroup
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Footnote saving}
+%
+% \begin{macro}{\fn@fntext}
+%
+% Now to define how to actually do footnotes.  I'll just add the notes to
+% the bottom of the footnote box I'm building.
+%
+% There's some hacking added here to handle the case that a footnote is
+% in an |\intertext| command within a broken \package{amsmath} alignment
+% environment -- otherwise the footnotes get duplicated due to the way that
+% that package measures equations.
+% \begin{footnote}
+%   The correct solution of course is to
+%   implement aligning environments in a sensible way, by building the table
+%   and leaving penalties describing the intended format, and then pick that
+%   apart in a postprocessing phase.  If I get the time, I'll start working
+%   on this again.  I have a design worked out and the beginnings of an
+%   implementation, but it's going to be a long time coming.
+% \end{footnote}
+%
+%    \begin{macrocode}
+\def\fn@fntext#1{%
+  \ifx\ifmeasuring@\@@undefined%
+    \expandafter\@secondoftwo\else\expandafter\@iden%
+  \fi%
+  {\ifmeasuring@\expandafter\@gobble\else\expandafter\@iden\fi}%
+  {%
+    \global\setbox\fn@notes\vbox{%
+      \unvbox\fn@notes%
+      \fn@startnote%
+      \@makefntext{%
+        \rule\z@\footnotesep%
+        \ignorespaces%
+        #1%
+        \@finalstrut\strutbox%
+      }%
+      \fn@endnote%
+    }%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\savenotes}
+%
+% The |\savenotes| declaration starts saving footnotes, to be spewed at a
+% later date.  We'll also remember which counter we're meant to use, and
+% redefine the footnotes used by minipages.
+%
+% The idea here is that we'll gather up footnotes within the environment,
+% and output them in whatever format they were being typeset outside the
+% environment.
+%
+% I'll take this a bit at a time.  The start is easy: we need a group in
+% which to keep our local definitions.
+%
+%    \begin{macrocode}
+\def\savenotes{%
+  \begingroup%
+%    \end{macrocode}
+%
+% Now, if I'm already saving footnotes away, I won't bother doing anything
+% here.  Otherwise I need to start hacking, and set the switch.
+%
+%    \begin{macrocode}
+  \if@savingnotes\else%
+    \@savingnotestrue%
+%    \end{macrocode}
+%
+% I redefine the |\@footnotetext| command, which is responsible for adding
+% a footnote to the appropriate insert.  I'll redefine both the current
+% version, and \env{minipage}'s specific version, in case there's a nested
+% minipage.
+%
+%    \begin{macrocode}
+    \let\@footnotetext\fn@fntext%
+    \let\@mpfootnotetext\fn@fntext%
+%    \end{macrocode}
+%
+% I'd better make sure my box is empty before I start, and I must set up
+% the column width so that later changes (e.g., in \env{minipage}) don't
+% upset things too much.
+%
+%    \begin{macrocode}
+    \fn@width\columnwidth%
+    \let\fn@colwidth\fn@width%
+    \global\setbox\fn@notes\box\voidb@x%
+%    \end{macrocode}
+%
+% Now for some yuckiness.  I want to ensure that \env{minipage} doesn't
+% change how footnotes are handled once I've taken charge.  I'll store the
+% current values of |\thempfn| (which typesets a footnote marker) and
+% |\@mpfn| (which contains the name of the current footnote counter).
+%
+%    \begin{macrocode}
+    \let\fn@thempfn\thempfn%
+    \let\fn@mpfn\@mpfn%
+%    \end{macrocode}
+%
+% The \env{minipage} environment provides a hook, called |\@minipagerestore|.
+% Initially it's set to |\relax|, which is unfortunately unexpandable, so if
+% I want to add code to it, I must check this possibility.  I'll make it
+% |\@empty| (which expands to nothing) if it's still |\relax|.  Then I'll
+% add my code to the hook, to override |\thempfn| and |\@mpfn| set up by
+% \env{minipage}.
+%
+% Note that I can't just force the |mpfootnote| counter to be equal to
+% the |footnote| one, because \env{minipage} clears |\c@mpfootnote| to zero
+% when it starts.  This method will ensure that even so, the current counter
+% works OK.
+%
+%    \begin{macrocode}
+    \ifx\@minipagerestore\relax\let\@minipagerestore\@empty\fi%
+    \expandafter\def\expandafter\@minipagerestore\expandafter{%
+      \@minipagerestore%
+      \let\thempfn\fn@thempfn%
+      \let\@mpfn\fn@mpfn%
+    }%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\spewnotes}
+%
+% Now I can spew out the notes we saved.  This is a bit messy, actually.
+% Since the standard |\@footnotetext| implementation tries to insert funny
+% struts and things, I must be a bit careful.  I'll disable all this bits
+% which start paragraphs prematurely.
+%
+%    \begin{macrocode}
+\def\spewnotes{%
+  \endgroup%
+  \if@savingnotes\else\ifvoid\fn@notes\else\begingroup%
+    \let\@makefntext\@empty%
+    \let\@finalstrut\@gobble%
+    \let\rule\@gobbletwo%
+    \@footnotetext{\unvbox\fn@notes}%
+  \endgroup\fi\fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% Now make an environment, for users.
+%
+%    \begin{macrocode}
+\let\endsavenotes\spewnotes
+%    \end{macrocode}
+%
+% That's all that needs to be in the shared code section.
+%
+%    \begin{macrocode}
+%</macro|package>
+%<*package>
+%    \end{macrocode}
+%
+%
+% \subsection{The \env{footnote} environment}
+%
+% Since |\footnote| is a command with an argument, things like \env{verbatim}
+% are unwelcome in it.  Every so often someone on |comp.text.tex| moans
+% about it and I post a nasty hack to make it work.  However, as a more
+% permanent and `official' solution, here's an environment which does the
+% job rather better.  Lots of this is based on code from my latest attempt
+% on the newsgroup.
+%
+% I'll work on this in a funny order, although I think it's easier to
+% understand.  First, I'll do some macros for reading the optional argument
+% of footnote-related commands.
+%
+% \begin{macro}{\fn@getmark}
+%
+% Saying \syntax{"\\fn@getmark{"<default-code>"}{"<cont-code>"}"} will read
+% an optional argument giving a value for the footnote counter; if the
+% argument isn't there, the \<default-code> is executed, and it's expected
+% to set up the appropriate counter to the current value.  The footnote
+% marker text is stored in the macro |\@thefnmark|, as is conventional for
+% \LaTeX's footnote handling macros.  Once this is done properly, the
+% \<cont-code> is called to continue handling things.
+%
+% Since the handling of the optional argument plays with the footnote
+% counter locally, I'll start a group right now to save some code.  Then I'll
+% decide what to do based on the presence of the argument.
+%
+%    \begin{macrocode}
+\def\fn@getmark#1#2{%
+  \begingroup%
+  \@ifnextchar[%
+    {\fn@getmark@i{#1}}%
+    {#1\fn@getmark@ii{#2}}%
+}
+%    \end{macrocode}
+%
+% There's an optional argument, so I need to read it and assign it to the
+% footnote counter.
+%
+%    \begin{macrocode}
+\def\fn@getmark@i#1[#2]{%
+  \csname c@\@mpfn\endcsname#2%
+  \fn@getmark@ii%
+}
+%    \end{macrocode}
+%
+% Finally, set up the macro properly, and end the group.
+%
+%    \begin{macrocode}
+\def\fn@getmark@ii#1{%
+  \unrestored@protected@xdef\@thefnmark{\thempfn}%
+  \endgroup%
+  #1%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% From argument reading, I'll move on to footnote typesetting.
+%
+% \begin{macro}{\fn@startfntext}
+%
+% The |\fn@startfntext| macro sets everything up for building the footnote
+% in a box register, ready for unboxing into the footnotes insert.  The
+% |\fn@prefntext| macro is a style hook I'll set up later.
+%
+%    \begin{macrocode}
+\def\fn@startfntext{%
+  \setbox\z@\vbox\bgroup%
+    \fn@startnote%
+    \fn@prefntext%
+    \rule\z@\footnotesep%
+    \ignorespaces%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\fn@endfntext}
+%
+% Now I'll end the vbox, and add it to the footnote insertion.  Again, I
+% must be careful to prevent |\@footnotetext| from adding horizontal mode
+% things in bad places.
+%
+%    \begin{macrocode}
+\def\fn@endfntext{%
+    \@finalstrut\strutbox%
+    \fn@postfntext%
+  \egroup%
+  \begingroup%
+    \let\@makefntext\@empty%
+    \let\@finalstrut\@gobble%
+    \let\rule\@gobbletwo%
+    \@footnotetext{\unvbox\z@}%
+  \endgroup%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{footnote}
+%
+% I can now start on the environment proper.  First I'll look for an
+% optional argument.
+%
+%    \begin{listing}
+%\def\footnote{%
+%    \end{listing}
+%
+% Oh.  I've already come up against the first problem: that name's already
+% used.  I'd better save the original version.
+%
+%    \begin{macrocode}
+\let\fn@latex@@footnote\footnote
+%    \end{macrocode}
+%
+% The best way I can think of for seeing if I'm in an environment is to
+% look at |\@currenvir|.  I'll need something to compare with, then.
+%
+%    \begin{macrocode}
+\def\fn@footnote{footnote}
+%    \end{macrocode}
+%
+% Now to start properly.  |;-)|
+%
+%    \begin{macrocode}
+\def\footnote{%
+  \ifx\@currenvir\fn@footnote%
+    \expandafter\@firstoftwo%
+  \else%
+    \expandafter\@secondoftwo%
+  \fi%
+  {\fn@getmark{\stepcounter\@mpfn}%
+              {\leavevmode\unskip\@footnotemark\fn@startfntext}}%
+  {\fn@latex@@footnote}%
+}
+%    \end{macrocode}
+%
+% Ending the environment is simple.
+%
+%    \begin{macrocode}
+\let\endfootnote\fn@endfntext
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{environment}{footnotetext}
+%
+% I'll do the same magic as before for |\footnotetext|.
+%
+%    \begin{macrocode}
+\def\fn@footnotetext{footnotetext}
+\let\fn@latex@@footnotetext\footnotetext
+\def\footnotetext{%
+  \ifx\@currenvir\fn@footnotetext%
+    \expandafter\@firstoftwo%
+  \else%
+    \expandafter\@secondoftwo%
+  \fi%
+  {\fn@getmark{}\fn@startfntext}%
+  {\fn@latex@@footnotetext}%
+}
+\let\endfootnotetext\endfootnote
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{macro}{\fn@prefntext}
+% \begin{macro}{\fn@postfntext}
+%
+% Now for one final problem.  The style hook for footnotes is the command
+% |\@makefntext|, which takes the footnote text as its argument.  Clearly
+% this is utterly unsuitable, so I need to split it into two bits, where
+% the argument is.  This is very tricky, and doesn't deserve to work,
+% although it appears to be a good deal more effective than it has any right
+% to be.
+%
+%    \begin{macrocode}
+\long\def\@tempa#1\@@#2\@@@{\def\fn@prefntext{#1}\def\fn@postfntext{#2}}
+\expandafter\@tempa\@makefntext\@@\@@@
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsection{Hacking existing environments}
+%
+% Some existing \LaTeX\ environments ought to have footnote handling but
+% don't.  Now's our chance.
+%
+% \begin{macro}{\makesavenoteenv}
+%
+% The |\makesavenoteenv| command makes an environment save footnotes around
+% itself.
+%
+% It would also be nice to make |\parbox| work with footnotes.  I'll do this
+% later.
+%
+%    \begin{macrocode}
+\def\makesavenoteenv{\@ifnextchar[\fn@msne@ii\fn@msne@i}
+%    \end{macrocode}
+%
+% We're meant to redefine the environment.  We'll copy it (using |\let|) to
+% a magic name, and then pass it on to stage~2.
+%
+%    \begin{macrocode}
+\def\fn@msne@i#1{%
+  \expandafter\let\csname msne$#1\expandafter\endcsname%
+                  \csname #1\endcsname%
+  \expandafter\let\csname endmsne$#1\expandafter\endcsname%
+                  \csname end#1\endcsname%
+  \fn@msne@ii[#1]{msne$#1}%
+}
+%    \end{macrocode}
+%
+% Now we'll define the new environment.  The start is really easy, since we
+% just need to insert a |\savenotes|.  The end is more complex, since we
+% need to preserve the |\if@endpe| flag so that |\end| can pick it up.  I
+% reckon that proper hooks should be added to |\begin| and |\end| so that
+% environments can define things to be done outside the main group as
+% well as within it; still, we can't all have what we want, can we?
+%
+%    \begin{macrocode}
+\def\fn@msne@ii[#1]#2{%
+  \expandafter\edef\csname#1\endcsname{%
+    \noexpand\savenotes%
+    \expandafter\noexpand\csname#2\endcsname%
+  }%
+  \expandafter\edef\csname end#1\endcsname{%
+    \expandafter\noexpand\csname end#2\endcsname%
+    \noexpand\expandafter%
+    \noexpand\spewnotes%
+    \noexpand\if@endpe\noexpand\@endpetrue\noexpand\fi%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{minipage*}
+%
+% Let's define a \env{minipage$*$} environment which handles footnotes
+% nicely.  Really easy:
+%
+%    \begin{macrocode}
+\makesavenoteenv[minipage*]{minipage}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{macro}{\parbox}
+%
+% Now to alter |\parbox| slightly, so that it handles footnotes properly.
+% I'm going to do this fairly inefficiently, because I'm going to try and
+% change it as little as possible.
+%
+% First, I'll save the old |\parbox| command.  If I don't find a \lit{*},
+% I'll just call this command.
+%
+%    \begin{macrocode}
+\let\fn@parbox\parbox
+%    \end{macrocode}
+%
+% This is the clever bit: I don't know how many optional arguments
+% Mr~Mittelbach and his chums will add to |\parbox|, so I'll handle any
+% number.  I'll store them all up in my first argument and call myself
+% every time I find a new one.  If I run out of optional arguments,
+% I'll call the original |\parbox| command, surrounding it with |\savenotes|
+% and |\spewnotes|.
+%
+%    \begin{macrocode}
+\def\parbox{\@ifnextchar[{\fn@parbox@i{}}{\fn@parbox@ii{}}}
+\def\fn@parbox@i#1[#2]{%
+  \@ifnextchar[{\fn@parbox@i{#1[#2]}}{\fn@parbox@ii{#1[#2]}}%
+}
+\long\def\fn@parbox@ii#1#2#3{\savenotes\fn@parbox#1{#2}{#3}\spewnotes}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% Done!
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
diff --git a/mdwlist.dtx b/mdwlist.dtx
new file mode 100644
index 0000000..f93ef07
--- /dev/null
+++ b/mdwlist.dtx
@@ -0,0 +1,759 @@
+% \begin{meta-comment}
+%
+% $Id: mdwlist.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
+%
+% Various list-related things
+%
+% (c) 1996 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: mdwlist.dtx,v $
+% Revision 1.1  2002/02/03 20:49:03  mdw
+% Checkin for new build system.
+%
+% Revision 1.1  1996/11/19 20:52:26  mdw
+% Initial revision
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% mdwlist package -- various list-related things
+%% Copyright (c) 1996 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preambles>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{mdwlist}
+%<+package>                [1996/05/02 1.1 Various list-related things]
+% \end{meta-comment}
+%
+% \CheckSum{179}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{mdwlist}
+\def\defaultdesc{%
+  \desclabelwidth{80pt}%
+  \desclabelstyle\nextlinelabel%
+  \def\makelabel{\bfseries}%
+}
+\newenvironment{cmdlist}
+  {\basedescript{\let\makelabel\cmd}}
+  {\endbasedescript}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+% \section{User guide}
+%
+% This package provides some vaguely useful list-related commands and
+% environments:
+% \begin{itemize*}
+% \item A way of building \env{description}-like environments.
+% \item Commands for making `compacted' versions of list environments
+% \item A method for suspending and resuming enumerated lists.
+% \end{itemize*}
+%
+% \subsection{Description list handling}
+%
+% Different sorts of description-type lists require different sorts of
+% formatting: I think that's fairly obvious.  There are essentially three
+% different attributes which should be changable:
+% \begin{itemize*}
+% \item the indentation of the items being described,
+% \item the handling of labels which don't fit properly, and
+% \item the style used to typeset the label text.
+% \end{itemize*}
+% The first two items should usually be decided for all description-like
+% lists in the document, to ensure consistency of appearance.  The last
+% depends much more on the content of the labels.
+%
+% \DescribeEnv{basedescript}
+% The \env{basedescript} environment acts as a `skeleton' for description
+% environments.  It takes one argument, which contains declarations to
+% be performed while constructing the list.  I'd consider it unusual for
+% the \env{basedescript} environment to be used in the main text: it's
+% intended to be used to build other environments.
+%
+% The declarations which can be used to define description-type environments
+% include all of those which are allowed when setting up a list (see the
+% \LaTeX\ book for information here).  Some others, which apply specifically
+% to description lists, are also provided:
+%
+% \begin{itemize}
+%
+% \item \DescribeMacro{\desclabelwidth}
+%       The \syntax{"\\desclabelwidth{"<length>"}"} declaration sets labels
+%       to be left-aligned, with a standard width of \<length>; the item
+%       text is indented by \<length> plus the value of |\labelsep|.
+%
+% \item \DescribeMacro{\desclabelstyle}
+%       The label style determines how overlong labels are typeset.  A style
+%       may be set using the \syntax{"\\desclabelstyle{"<style>"}"}
+%       declaration.  The following \<style>s are provided:
+%       \begin{cmdlist}
+%       \item [\nextlinelabel] If the label is too wide to fit next to the
+%             first line of text, then it is placed on a line by itself;
+%             the main text is started on the next line with the usual
+%             indentation.
+%       \item [\multilinelabel] The label is typeset in a parbox with the
+%             appropriate width; if it won't fit on one line, then the
+%             text will be split onto subsequent lines.
+%       \item [\pushlabel] If the label is too wide to fit in the space
+%             allocated to it, the start of the item's text will be `pushed'
+%             over to the right to provide space for the label.  This is
+%             the standard \LaTeX\ \env{description} behaviour.
+%       \end{cmdlist}
+%
+% \item \DescribeMacro{\makelabel}
+%       The |\makelabel| command is responsible for typesetting a label.
+%       It is given one argument, which is the text given as an argument
+%       to the |\item| command; it should typeset it appropriately.  The
+%       text will then be arranged appropriately according to the chosen
+%       label style.  This command should be redefined using |\renewcommand|.
+%
+% \end{itemize}
+%
+% \begin{figure}
+% \begin{demo}[w]{Various labelling styles}
+%\begin{basedescript}{\desclabelstyle{\nextlinelabel}}
+%\item [Short label] This is a short item, although it has quite a
+%      lot of text attached to it.
+%\item [Slightly longer label text] This is a rather longer piece
+%      of text, with a correspondingly slightly longer label.
+%\end{basedescript}
+%\medskip
+%\begin{basedescript}{\desclabelstyle{\multilinelabel}}
+%\item [Short label] This is a short item, although it has quite a
+%      lot of text attached to it.
+%\item [Slightly longer label text] This is a rather longer piece
+%      of text, with a correspondingly slightly longer label.
+%\end{basedescript}
+%\medskip
+%\begin{basedescript}{\desclabelstyle{\pushlabel}}
+%\item [Short label] This is a short item, although it has quite a
+%      lot of text attached to it.
+%\item [Slightly longer label text] This is a rather longer piece
+%      of text, with a correspondingly slightly longer label.
+%\end{basedescript}
+% \end{demo}
+% \end{figure}
+%
+% \DescribeMacro{\defaultdesc}
+% To allow document designers to control the global appearance of description
+% lists, the |\defaultdesc| command may be redefined; it is called while
+% setting up a new \env{basedescript} list, before performing the user's
+% declarations.  By default, it attempts to emulate the standard \LaTeX\
+% \env{description} environment:\footnote{^^A
+%   This is a slightly sanitised version of the real definition, which is
+%   given in the implementation section of this document.}
+% \begin{listing}
+%\providecommand{\defaultdesc}{%
+%  \desclabelstyle{\pushlabel}%
+%  \renewcommand{\makelabel}[1]{\bfseries##1}%
+%  \setlength{\labelwidth}{0pt}%
+%}
+% \end{listing}
+% Unfortunately, \LaTeX\ doesn't provide a means for overriding a command
+% which may or may not have been defined yet; in this case, I'd probably
+% recommend using the \TeX\ primitive |\def| to redefine |\defaultdesc|.
+%
+% If you want to redefine the \env{description} environment in terms of
+% the commands in this package, the following method is recommended:
+% \begin{listing}
+%\renewenvironment{description}{%
+%  \begin{basedescript}{%
+%    \renewcommand{\makelabel}[1]{\bfseries##1}%
+%  }%
+%}{%
+%  \end{basedescript}%
+%}
+% \end{listing}
+% This ensures that labels are typeset in bold, as is usual, but other
+% properties of the list are determined by the overall document style.
+%
+% \subsection{Compacted lists}
+%
+% \LaTeX\ tends to leave a certain amount of vertical space between list
+% items.  While this is normally correct for lists in which the items are
+% several lines long, it tends to look odd if all or almost all the items
+% are only one line long.
+%
+% \DescribeMacro{\makecompactlist}
+% The command
+% \syntax{"\\makecompactlist{"<new-env-name>"}{"<old-env-name>"}"}
+% defines a new environment \<new-env-name> to be a `compacted' version of
+% the existing environment \<old-env-name>; i.e., the two environments are
+% the same except that the compacted version leaves no space between items
+% or paragraphs within the list.
+%
+% \DescribeEnv{itemize*}
+% \DescribeEnv{enumerate*}
+% \DescribeEnv{description*}
+% So that the most common cases are already handled, the package creates
+% compacted $*$-variants of the \env{itemize}, \env{enumerate} and
+% \env{description} environments.  These were created using the commands
+% \begin{listing}
+%\makecompactlist{itemize*}{itemize}
+%\makecompactlist{enumerate*}{enumerate}
+%\makecompactlist{description*}{description}
+% \end{listing}
+%
+% Some list environments accept arguments.  You can pass an argument to a
+% list environment using an optional argument to its compact variant.  For
+% example,
+% \begin{listing}
+%\begin{foolist*}[{someargument}]
+% \end{listing}
+%
+% \subsection{Suspending and resuming list environments}
+%
+% \DescribeMacro{\suspend}
+% \DescribeMacro{\resume}
+% The |\suspend| and |\resume| commands allow you to temporarily end a list
+% environment and then pick it up where you left off.  The syntax is fairly
+% simple:
+%
+% \begin{grammar}
+%
+% <suspend-cmd> ::= \[[
+%   "\\suspend"
+%   \begin{stack} \\ "[" <name> "]" \end{stack} "{" <env-name> "}"
+% \]]%
+%
+% <resume-cmd> ::= \[[
+%   "\\resume"
+%   \begin{stack} \\ "[" <name> "]" \end{stack} "{" <env-name> "}"
+%   \begin{stack} \\ "[" <text> "]" \end{stack}
+% \]]%
+%
+% \end{grammar}
+%
+% The \<env-name> is the name of the environment; this will more often than
+% not be the \env{enumerate} environment.  The \<name> is a magic name you
+% can use to identify the suspended environment; if you don't specify this,
+% the environment name is used instead.
+%
+% \begin{demo}{Suspended environments}
+%Here's some initial text.  It's
+%not very interesting.
+%\begin{enumerate*}
+%\item This is an item.
+%\item This is another.
+%\suspend{enumerate*}
+%Some more commentry text.
+%\resume{enumerate*}
+%\item Another item.
+%\end{enumerate*}
+% \end{demo}
+%
+% You can pass arguments to a resumed list environment through the second
+% optional argument of the |\resume| command.  If, for example, you're using
+% David Carlisle's \package{enumerate} package, you could say something like
+% \begin{listing}
+%\begin{enumerate}[\bfseries{Item} i]
+%\item An item
+%\item Another item
+%\suspend{enumerate}
+%Some intervening text.
+%\resume{enumerate}[{[\bfseries{Item} i]}]
+%\item Yet another item
+%\end{enumerate}
+% \end{listing}
+%
+% \implementation
+%
+% \section{Implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+% \subsection{Description lists}
+%
+% \subsubsection{Label styles}
+%
+% \begin{macro}{\nextlinelabel}
+%
+% The idea here is that if the label is too long to fit in its box, we put
+% it on its own line and start the text of the item on the next.  I've
+% used |\sbox| here to capture colour changes properly, even though I have
+% deep moral objections to the use of \LaTeX\ boxing commands.  Anyway,
+% I capture the text in box~0 and compare its width to the amount of space
+% I have in the label box.  If there's enough, I can just unbox the box;
+% otherwise I build a vbox containing the label text and an empty hbox --
+% |\baselineskip| glue inserted between the two boxes makes sure we get
+% the correct spacing between the two lines, and the vboxness of the vbox
+% ensures that the baseline of my strange thing is the baseline of the
+% \emph{bottom} box.  I then bash the vbox on the nose, so as to make its
+% width zero, and leave that as the result.  Either way, I then add glue
+% to left align whatever it is I've created.
+%
+%    \begin{macrocode}
+\def\nextlinelabel#1{%
+  \sbox\z@{#1}%
+  \ifdim\wd\z@>\labelwidth%
+    \setbox\z@\vbox{\box\z@\hbox{}}%
+    \wd\z@\z@%
+    \box\z@%
+  \else%
+    \unhbox\z@%
+  \fi%
+  \hfil%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\multilinelabel}
+%
+% A different idea -- make the label text wrap around onto the next line if
+% it's too long.  This is really easy, actually.  I use a parbox to contain
+% the label text, set to be ragged right, because there won't be enough
+% space to do proper justification.  There's also a funny hskip there --
+% this is because \TeX\ only hyphenates things it finds sitting \emph{after}
+% glue items.  The parbox is top-aligned, so the label text and the item
+% run downwards together.  I put the result in box~0, and remove the depth,
+% so as not to make the top line of the item text look really strange.
+%
+% All this leaves a little problem, though: if the item text isn't very long,
+% the label might go further down the page than the main item, and possibly
+% collide with the label below.  I must confess that I'm not actually sure
+% how to deal with this possibility, so I just hope it doesn't happen.
+%
+% By the way, I don't have moral objections to |\parbox|.
+%
+%    \begin{macrocode}
+\def\multilinelabel#1{%
+  \setbox\z@\hbox{%
+    \parbox[t]\labelwidth{\raggedright\hskip\z@skip#1}%
+  }%
+  \dp\z@\z@%
+  \box\z@%
+  \hfil%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\pushlabel}
+%
+% Now we implement the old style behaviour -- if the label is too wide, we
+% just push the first line of the item further over to the right.  This
+% is really very easy indeed -- we just stick some |\hfil| space on the
+% right hand side (to left align if the label comes up too short).  The
+% `push' behaviour is handled automatically by \LaTeX's item handling.
+%
+%    \begin{macrocode}
+\def\pushlabel#1{{#1}\hfil}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{The main environment}
+%
+% \begin{macro}{\desclabelstyle}
+%
+% This is a declaration intended to be used only in the argument to the
+% \env{basedescript} environment.  It sets the label style for the list.
+% All we do is take the argument and assign it to a magic control sequence
+% which \env{basedescript} will understand later.
+%
+%    \begin{macrocode}
+\def\desclabelstyle#1{\def\desc@labelstyle{#1}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\desclabelwidth}
+%
+% We set the label width and various other bits of information which will
+% make all the bits of the description line up beautifully.  We set
+% |\labelwidth| to the value we're given (using |\setlength|, so that
+% people can use the \package{calc} package if they so wish), and make
+% the |\leftmargin| equal $|\labelwidth|+|\labelsep|$.
+%
+%    \begin{macrocode}
+\def\desclabelwidth#1{%
+  \setlength\labelwidth{#1}%
+  \leftmargin\labelwidth%
+  \advance\leftmargin\labelsep%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{basedescript}
+%
+% This is the new description environment.  It does almost everything you
+% could want from a description environment, I think.  The argument is a
+% collection of declarations to be performed while setting up the list.
+%
+% This environment isn't really intended to be used by users -- it's here
+% so that you can define other description environments in terms of it,
+%
+% The environment is defined in two bits -- the `start' bit here simply
+% starts the list and inserts the user declarations in an appropriate
+% point, although sensible details will be inerted if the argument was
+% empty.
+%
+%    \begin{macrocode}
+\def\basedescript#1{%
+%    \end{macrocode}
+%
+% We must start the list.  If the |\item| command's optional argument is
+% missing, we should just leave a blank space, I think.
+%
+%    \begin{macrocode}
+  \list{}{%
+%    \end{macrocode}
+%
+% So far, so good.  Now put in some default declarations.  I'll use a
+% separate macro for this, so that the global appearance of lists can be
+% configured.
+%
+%    \begin{macrocode}
+    \defaultdesc%
+%    \end{macrocode}
+%
+% Now we do the user's declarations.
+%
+%    \begin{macrocode}
+    #1%
+%    \end{macrocode}
+%
+% Now set up the other parts of the list.  We set |\itemindent| so that the
+% label is up against the current left margin.  (The standard version
+% actually leaves the label hanging to the left of the margin by a
+% distance of |\labelsep| for a reason I can't quite comprehend -- there's
+% an |\hspace{\labelsep}| in the standard |\makelabel| to compensate for
+% this.  Strange\dots)
+%
+% To make the label start in the right place, the text of the item must
+% start a distance of $|\labelwidth|+|\labelsep|$ from the (pre-list) left
+% hand margin; this means that we must set |\itemindent| to be
+% $|\labelwidth|+|\labelsep|-|\leftmargin|$.  Time for some \TeX\ arithmetic.
+%
+%    \begin{macrocode}
+    \itemindent\labelwidth%
+    \advance\itemindent\labelsep%
+    \advance\itemindent-\leftmargin%
+%    \end{macrocode}
+%
+% Now we must set up the label typesetting.  We'll take the |\makelabel|
+% provided by the user, remember it, and then redefine |\makelabel| in
+% terms of the |\desclabelstyle| and the saved |\makelabel|.
+%
+%    \begin{macrocode}
+    \let\desc@makelabel\makelabel%
+    \def\makelabel##1{\desc@labelstyle{\desc@makelabel{##1}}}%
+%    \end{macrocode}
+%
+% I can't think of anything else which needs doing, so I'll call it a day
+% there.
+%
+%    \begin{macrocode}
+  }%
+}
+%    \end{macrocode}
+%
+% Now we define the `end-bit' of the environment.  Since all we need to do
+% is to close the list, we can be ever-so slightly clever and use |\let|.
+%
+%    \begin{macrocode}
+\let\endbasedescript\endlist
+%    \end{macrocode}
+%
+% Note that with these definitions, the standard \env{description}
+% environment can be emulated by saying simply:
+% \begin{listing}
+%\renewenvironment{description}{%
+%  \begin{basedescript}{}%
+%}{%
+%  \end{basedescript}
+%}
+% \end{listing}
+%
+% \end{environment}
+%
+% \begin{macro}{\defaultdesc}
+%
+% Now to set up the standard description appearance.  In the absence
+% of any other declarations, the label will `push' the text out the way if
+% the text is too long.  The standard |\labelsep| and |\leftmargin| are not
+% our problem.  We typeset the label text in bold by default. Also,
+% |\labelwidth| is cleared to 0\,pt, because this is what \LaTeX's usual
+% \env{description} does.
+%
+%    \begin{macrocode}
+\providecommand\defaultdesc{%
+  \desclabelstyle\pushlabel%
+  \def\makelabel##1{\bfseries##1}%
+  \labelwidth\z@%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{An example}
+%
+% \begin{environment}{note}
+%
+% The \env{note} environment is a simple application of the general
+% description list shown above.  It typesets the label (by default, the
+% text `\textbf{note}') at the left margin, and the note text indented by
+% the width of the label.
+%
+% The code is simple -- we take the environment's argument (which may have
+% been omitted), store it in a box (using |\sbox| again, to handle colour
+% changes correctly), set the label width from the width of the box, and
+% then create a single item containing the label text.  The text of the
+% environment then appears in exactly the desired place.
+%
+% I've not used |\newcommand| here, for the following reasons:
+% \begin{itemize}
+%
+% \item I don't like it much, to be honest.
+%
+% \item Until very recently, |\newcommand| only allowed you to define
+%       `long' commands, where new paragraphs were allowed to be started
+%       in command arguments; this removes a useful check which traps
+%       common errors like missing out `|}|' characters.  I'd prefer to
+%       be compatible with older \LaTeX s than to use the new |\newcommand|
+%       which provides a $*$-form to work around this restriction.
+%
+% \end{itemize}
+%
+%    \begin{macrocode}
+\def\note{\@ifnextchar[\note@i{\note@i[Note]}}
+\def\note@i[#1]{%
+  \basedescript{%
+    \sbox\z@{\makelabel{#1}}%
+    \desclabelwidth{\wd\z@}%
+  }%
+  \item[\box\z@]%
+}
+\let\endnote\endbasedescript
+%    \end{macrocode}
+%
+% \end{environment}
+%
+%
+% \subsection{Compacted environments}
+%
+% Normal lists tend to have rather too much space between items if all or
+% most of the item texts are one line or less each.  We therefore define
+% a macro |\makecompactlist| whuch creates `compacted' versions of existing
+% environments.
+%
+% \begin{macro}{\makecompactlist}
+%
+% We're given two arguments: the name of the new environment to create, and
+% the name of the existing list environment to create.
+%
+% The first thing to do is to ensure that the environment we're creating is
+% actually valid (i.e., it doesn't exist already, and it has a sensible
+% name).  We can do this with the internal \LaTeX\ macro |\@ifdefinable|.
+%
+%    \begin{macrocode}
+\def\makecompactlist#1#2{%
+  \expandafter\@ifdefinable\csname#1\endcsname%
+    {\makecompactlist@i{#1}{#2}}%
+}
+%    \end{macrocode}
+%
+% We also ought to ensure that the other environment already exists.  This
+% isn't too tricky.  We'll steal \LaTeX's error and message for this.
+%
+%    \begin{macrocode}
+\def\makecompactlist@i#1#2{%
+  \@ifundefined{#2}{\me@err{Environment `#2' not defined}\@ehc}{}%
+%    \end{macrocode}
+%
+% The main work for starting a compact list is done elsewhere.
+%
+%    \begin{macrocode}
+  \@namedef{#1}{\@compact@list{#2}}%
+%    \end{macrocode}
+%
+% Now to define the end of the environment; this isn't terribly difficult.
+%
+%    \begin{macrocode}
+  \expandafter\let\csname end#1\expandafter\endcsname%
+                  \csname end#2\endcsname%
+%    \end{macrocode}
+%
+% That's a compacted environment created.  Easy, no?
+%
+%    \begin{macrocode}
+}
+%    \end{macrocode}
+%
+% The general case macro has to try slurping some arguments, calling the
+% underlying environment, and removing vertical space.
+%
+%    \begin{macrocode}
+\def\@compact@list#1{\@testopt{\@compact@list@i{#1}}{}}
+\def\@compact@list@i#1[#2]{%
+  \@nameuse{#1}#2%
+  \parskip\z@%
+  \itemsep\z@%
+}%
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{itemize*}
+% \begin{environment}{enumerate*}
+% \begin{environment}{description*}
+%
+% Let's build some compacted environments now.  These are easy now that
+% we've done all the work above.
+%
+%    \begin{macrocode}
+\makecompactlist{itemize*}{itemize}
+\makecompactlist{enumerate*}{enumerate}
+\makecompactlist{description*}{description}
+%    \end{macrocode}
+%
+% \end{environment}
+% \end{environment}
+% \end{environment}
+%
+%
+% \subsection{Suspending and resuming lists}
+%
+% This is nowhere near perfect; it relies a lot on the goodwill of the user,
+% although it seems to work fairly well.
+%
+% \begin{macro}{\suspend}
+%
+% The only thing that needs saving here is the list counter, whose name
+% is stored in |\@listctr|.  When I get a request to save the counter, I'll
+% build a macro which will restore it when the environment is restored later.
+%
+% The first thing to do is to handle the optional argument.  |\@dblarg| will
+% sort this out, giving me a copy of the mandatory argument if there's no
+% optional one provided.
+%
+%    \begin{macrocode}
+\def\suspend{\@dblarg\suspend@i}
+%    \end{macrocode}
+%
+% That's all we need to do here.
+%
+%    \begin{macrocode}
+\def\suspend@i[#1]#2{%
+%    \end{macrocode}
+%
+% Now I have a little problem; when I |\end| the environment, it will close
+% off the grouping level, and the counter value will be forgotten.  This is
+% bad.  I'll store all my definitions into a macro, and build the |\end|
+% command into it; that way, everything will be expanded correctly.  This
+% requires the use of |\edef|, which means I must be a little careful.
+%
+%    \begin{macrocode}
+  \edef\@tempa{%
+%    \end{macrocode}
+%
+% The first thing to do is to end the environment.  I don't want |\end|
+% expanded yet, so I'll use |\noexpand|.
+%
+%    \begin{macrocode}
+    \noexpand\end{#2}%
+%    \end{macrocode}
+%
+% Now I must define the `resume' macro.  I'll use |\csname| to build the
+% named identifier into the name, so it won't go wrong (maybe).  There's
+% a little fun here to make the control sequence name but not expand it
+% here.
+%
+%    \begin{macrocode}
+    \def\expandafter\noexpand\csname resume.#1\endcsname{%
+%    \end{macrocode}
+%
+% The counter name is hidden inside |\@listctr|, so the actual counter is
+% called `|\csname c@\@listctr\endcsname|'.  I'll use |\the| to read its
+% current value, and assign it to the counter when the macro is used later.
+%
+%    \begin{macrocode}
+      \csname c@\@listctr\endcsname\the\csname c@\@listctr\endcsname%
+%    \end{macrocode}
+%
+% That's all we need to do there.  Now close the macros and run them.
+%
+%    \begin{macrocode}
+    }%
+  }%
+  \@tempa%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\resume}
+%
+% Resuming environments is much easier.  Since I use |\csname| to build the
+% name, nothing happens if you try to resume environments which weren't
+% suspended.  I'll trap this and raise an error.  Provide an optional
+% argument for collecting arguments to the target list.
+%
+%    \begin{macrocode}
+\def\resume{\@dblarg\resume@i}
+\def\resume@i[#1]#2{\@testopt{\resume@ii{#1}{#2}}{}}
+\def\resume@ii#1#2[#3]{%
+  \begin{#2}#3%
+  \@ifundefined{resume.#1}{\ml@err@resume}{\@nameuse{resume.#1}}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% That's all there is.
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
diff --git a/mdwmath.dtx b/mdwmath.dtx
new file mode 100644
index 0000000..ee6ed1c
--- /dev/null
+++ b/mdwmath.dtx
@@ -0,0 +1,1224 @@
+% \begin{meta-comment}
+%
+% $Id: mdwmath.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
+%
+% Various nicer mathematical things
+%
+% (c) 1996 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: mdwmath.dtx,v $
+% Revision 1.1  2002/02/03 20:49:03  mdw
+% Checkin for new build system.
+%
+% Revision 1.1  1996/11/19 20:53:21  mdw
+% Initial revision
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% mdwmath package -- various nicer mathematical things
+%% Copyright (c) 1996 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preamble>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{mdwmath}
+%<+package>                [2000/07/02 1.2 Nice mathematical things]
+%<+oldeqnarray>\NeedsTeXFormat{LaTeX2e}
+%<+oldeqnarray>\ProvidesPackage{eqnarray}
+%<+oldeqnarray>                [1996/04/11 1.1 Old enhanced eqnarray]
+% \end{meta-comment}
+%
+% \CheckSum{465}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\let\opmod\pmod
+\usepackage{amssymb}
+\describespackage{mdwmath}
+% \describespackage{eqnarray}
+\ignoreenv{old-eqnarray}
+% \unignoreenv{old-eqnarray}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+% \section{User guide}
+%
+% \subsection{Square root typesetting}
+%
+% \DescribeMacro{\sqrt}
+% The package supplies a star variant of the |\sqrt| command which omits the
+% vinculum over the operand (the line over the top).  While this is most
+% useful in simple cases like $\sqrt*{2}$ it works for any size of operand.
+% The package also re-implements the standard square root command so that it
+% positions the root number rather better.
+%
+% \begin{figure}
+% \begin{demo}[w]{Examples of the new square root command}
+%\[ \sqrt*{2} \quad \mbox{rather than} \quad \sqrt{2} \]
+%\[ \sqrt*[3]{2} \quad \mbox{ rather than } \quad \sqrt[3]{2} \]
+%\[ \sqrt{x^3 + \sqrt*[y]{\alpha}} - \sqrt*[n+1]{a} \]
+%\[ x = \sqrt*[3]{\frac{3y}{7}} \]
+%\[ q = \frac{2\sqrt*{2}}{5}+\sqrt[\frac{n+1}{2}]{2x^2+3xy-y^2} \]
+% \end{demo}
+% \end{figure}
+%
+% [Note that omission of the vinculum was originally a cost-cutting exercise
+% because the radical symbol can just fit in next to its operand and
+% everything ends up being laid out along a line.  However, I find that the
+% square root without vinculum is less cluttered, so I tend to use it when
+% it doesn't cause ambiguity.]
+%
+% \subsection{Modular arithmetic}
+%
+% In standard maths mode, there's too much space before the parentheses in
+% the output of the |\pmod| command.  Suppose that $x \equiv y^2 \opmod n$:
+% then the spacing looks awful.  Go on, admit it.
+%
+% It looks OK in a display.  For example, if
+% \[ c \equiv m^e \opmod n \]
+% then it's fine.  The package redefines the |\pmod| command to do something
+% more sensible.  So now $c^d \equiv m^{ed} \equiv m \pmod n$ and all looks
+% fine.
+%
+% \subsection{Some maths symbols you already have}
+%
+% \DescribeMacro\bitor
+% \DescribeMacro\bitand
+% \DescribeMacro\dblor
+% \DescribeMacro\dbland
+% Having just tried to do some simple things, I've found that there are maths
+% symbols missing.  Here they are, in all their glory:
+% \begin{center} \unverb\| \begin{tabular}{cl|cl|cl}
+% $\&$ & "\&"		& $\bitor$ & "\bitor"	& $\dbland$ & "\dbland" \\
+% $\bitand$ & "\bitand"	& $\dblor$ & "\dblor"	& 
+% \end{tabular} \end{center}
+%
+% \DescribeMacro\xor
+% \DescribeMacro\cat
+% I also set up the |\xor| command to typeset `$\xor$', which is commonly
+% used to represent the bitsize exclusive-or operation among cryptographers.
+% The command |\cat| typesets `$\cat$', which is a common operator indicating
+% concatenation of strings.
+%
+% \DescribeMacro\lsl
+% \DescribeMacro\lsr
+% \DescribeMacro\rol
+% \DescribeMacro\ror
+% The commands |\lsl| and |\lsr| typeset binary operators `$\lsl$' and
+% `$\lsr$' respectively, and |\rol| and |\ror| typeset `$\rol$' and `$\ror$'.
+% Note that these are spaced as binary operators, rather than relations.
+%
+% \DescribeMacro\compose
+% \DescribeMacro\implies
+% \DescribeMacro\vect
+% The |\compose| command typesets `$\compose$', which is usually used to
+% denote function composition.  The |\implies| command is made to typeset
+% `$\implies$'.  And \syntax{"\\vect{"<x>"}"} typesets `$\vect{x}$'.
+%
+% \DescribeMacro\statclose
+% \DescribeMacro\compind
+% The |\statclose| command typesets `$\statclose$', which indicates
+% `statistical closeness' of probability distributions; |\compind| typesets
+% `$\compind$', which indicates computational indistinguishability.
+%
+% \DescribeMacro\jacobi
+% The |\jacobi{x}{n}| command typesets `$\jacobi{x}{n}$', which may be of use
+% to number theorists talking about Jacobi or Lagrange symbols.
+%
+% \subsection{Rant about derivatives}
+%
+% \DescribeMacro\d
+% There is a difference between UK and US typesetting of derivatives.
+% Americans typeset
+% \[ \frac{dy}{dx} \]
+% while the British want
+% \[ \frac{\d y}{\d x}. \]
+% The command |\d| command is fixed to typeset a `$\d$'.  If you want the
+% accent, try |\a{d}{x}|, which typesets `\a{d}{x}'.
+%
+% \subsection{New operator names}
+%
+% \DescribeMacro\keys
+% \DescribeMacro\dom
+% \DescribeMacro\ran
+% \DescribeMacro\supp
+% \DescribeMacro\lcm
+% A few esoteric new operator names are supplied.
+% \begin{center} \unverb\| \begin{tabular}{cl|cl|cl}
+% $\keys$ & "\keys"	& $\dom$ & "\dom"	& $\ran$ & "\ran" \\
+% $\supp$ & "\supp"	& $\lcm$ & "\lcm"
+% \end{tabular} \end{center}
+% I think |\lcm| ought to be self-explanatory.  The |\dom| and |\ran|
+% operators pick out the domain and range of a function, respectively; thus,
+% if $F\colon X \to Y$ is a function, then $\dom F = X$ and $\ran F = Y$.
+% The \emph{support} of a probability distribution $\mathcal{D}$ is the set
+% of objects with nonzero probability; i.e., $\supp{D} = \{\, x \in
+% \dom\mathcal{D} \mid \mathcal{D}(x) > 0 \,\}$.
+%
+% \subsection{Standard set names}
+%
+% \DescribeMacro\Z
+% \DescribeMacro\Q
+% \DescribeMacro\R
+% \DescribeMacro\C
+% \DescribeMacro\N
+% \DescribeMacro\F
+% \DescribeMacro\powerset
+% If you have a |\mathbb| command defined, the following magic is revealed:
+% \begin{center} \unverb\| \begin{tabular}{cl|cl|cl}
+% $\Z$ & "\Z" & $\Q$ & "\Q" & $\R$ & "\R" \\
+% $\N$ & "\N" & $\F$ & "\F" & $\C$ & "\C"
+% \end{tabular} \end{center}
+% which are handy for various standard sets of things.  Also the |\powerset|
+% command typesets `$\powerset$'.
+%
+% \subsection{The `QED' symbol}
+%
+% \DescribeMacro\qed
+% \DescribeMacro\qedrule
+% For use in proofs of theorems, we provide a `QED' symbol which behaves well
+% under bizarre line-splitting conditions.  To use it, just say |\qed|.  The
+% little `\qedrule' symbol is available on its own, by saying |\qedrule|.
+% This also sets |\qedsymbol| if it's not set already.
+% \qed
+%
+% \begin{ignore}
+% There used to be an eqnarray here, but that's migrated its way into the
+% \package{mdwtab} package.  Maybe the original version, without dependency
+% on \package{mdwtab} ought to be releasable separately.  I'll keep it around
+% just in case.
+%
+% The following is the documentation for the original version.  There's an
+% updated edition in \package{mdwtab}.
+% \end{ignore}
+%
+% \begin{old-eqnarray}
+%
+% \subsection{A new \env{eqnarray} environment}
+%
+% \LaTeX's built-in \env{eqnarray} is horrible -- it puts far too much space
+% between the items in the array.  This environment is rather nearer to the
+% \env{amsmath} \env{align} environments, although rather less capable.
+%
+% \bigskip
+% \DescribeEnv{eqnarray}
+% {\synshorts
+% \setbox0\hbox{"\\begin{eqnarray}["<preamble>"]" \dots "\\end{eqnarray}"}
+% \leavevmode \hskip-\parindent \fbox{\box0}
+% }
+% \smallskip
+%
+% The new version of \env{eqnarray} tries to do everything which you really
+% want it to.  The \synt{preamble} string allows you to define the column
+% types in a vaguely similar way to the wonderful \env{tabular} environment.
+% The types provided (and it's easy-ish to add more) are:
+%
+% \def\ch{\char`}
+% \begin{description} \def\makelabel{\hskip\labelsep\normalfont\ttfamily}
+% \item [r] Right aligned equation
+% \item [c] Centre-aligned equation
+% \item [l] Left aligned equation
+% \item [\textrm{\texttt{Tr}, \texttt{Tc} and \texttt{Tl}}] Right, centre and
+%       left aligned text (not maths)
+% \item [L] Left aligned zero-width equation
+% \item [x] Centred entire equation
+% \item [:] Big gap separating sets of equations
+% \item [q] Quad space
+% \item [>\ch\{\synt{text}\ch\}] Insert text before column
+% \item [<\ch\{\synt{text}\ch\}] Insert text after column
+% \end{description}
+%
+% Some others are also defined: don't use them because they do complicated
+% things which are hard to explain and they aren't much use anyway.
+%
+% The default preamble, if you don't supply one of your own, is \lit{rcl}.
+% Most of the time, \lit{rl} is sufficient, although compatibility is more
+% important to me.
+%
+% By default, there is no space between columns, which makes formul\ae\ in an
+% \env{eqnarray} environment look just like formul\ae\ typeset on their own,
+% except that things get aligned in columns.  This is where the default
+% \env{eqnarray} falls down: it leaves |\arraycolsep| space between each
+% column making the thing look horrible.
+%
+% An example would be good here, I think.  This one's from exercise 22.9 of
+% the \textit{\TeX book}.
+%
+% \begin{demo}[w]{Simultaneous equations}
+%\begin{eqnarray}[rcrcrcrl]
+%  10w & + &  3x & + & 3y & + & 18z & = 1 \\
+%   6w & - & 17x &   &    & - &  5z & = 2
+%\end{eqnarray}
+% \end{demo}
+%
+% Choosing a more up-to-date example, here's one demonstrating the \lit{:}
+% column specifier from the \textit{\LaTeX\ Companion}.
+%
+% \begin{demo}[w]{Lots of equations}
+%\begin{eqnarray}[rl:rl:l]
+% V_i &= v_i - q_i v_j,	& X_i &= x_i - q_i x_j,	&
+%       U_i = u_i, \qquad \mbox{for $i \ne j$}  \label{eq:A} \\
+% V_j &= v_j,           & X_j &= x_j            &
+%       U_j u_j + \sum_{i \ne j} q_i u_i.
+%\end{eqnarray}
+% \end{demo}
+%
+% We can make things more interesting by adding a plain text column.  Here we
+% go:
+%
+% \begin{demo}[w]{Plain text column}
+%\begin{eqnarray}[rlqqTl]
+%     x  &= y           & by (\ref{eq:A}) \\
+%     x' &= y'          & by definition \\
+% x + x' &= y + y'      & by Axiom~1
+%\end{eqnarray}
+% \end{demo}
+%
+% The new features also mean that you don't need to mess about with
+% |\lefteqn| any more.  This is handled by the \lit{L} column type:
+%
+% \begin{demo}{Splitting example}
+%\begin{eqnarray*}[Ll]
+%   w+x+y+z = \\
+%    & a+b+c+d+e+ \\
+%    & f+g+h+i+j
+%\end{eqnarray*}
+% \end{demo}
+%
+% Finally, just to prove that the spacing's right at last, here's another one
+% from the \textit{Companion}.
+%
+% \begin{demo}{Spacing demonstration}
+%\begin{equation}
+%  x^2 + y^2 = z^2
+%\end{equation}
+%\begin{eqnarray}[rl]
+%  x^2 + y^2 &= z^2 \\
+%        y^2 &< z^2
+%\end{eqnarray}
+% \end{demo}
+%
+% Well, that was easy enough.  Now on to numbering.  As you've noticed, the
+% equations above are numbered.  You can use the \env{eqnarray$*$}
+% environment to turn off the numbering in the whole environment, or say
+% |\nonumber| on a line to suppress numbering of that one in particular.
+% More excitingly, you can say \syntax{"\\nonumber["<text>"]"} to choose
+% what text to display.
+%
+% A note for cheats: you can use the sparkly new \env{eqnarray} for simple
+% equations simply by specifying \lit{x} as the column description.  Who
+% needs \AmSTeX? |;-)|
+%
+% \end{old-eqnarray}
+%
+% \implementation
+%
+% \section{Implementation}
+%
+% This isn't really complicated (honest) although it is a lot hairier than I
+% think it ought to be.
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+% \subsection{Square roots}
+%
+% \subsubsection{Where is the square root sign?}
+%
+% \LaTeX\ hides the square root sign away somewhere without telling anyone
+% where it is.  I extract it forcibly by peeking inside the |\sqrtsign| macro
+% and scrutinising the contents.  Here we go: prepare for yukkiness.
+%
+%    \begin{macrocode}
+\newcount\sq@sqrt \begingroup \catcode`\|0 \catcode`\\12
+|def|sq@readrad#1"#2\#3|relax{|global|sq@sqrt"#2|relax}
+|expandafter|sq@readrad|meaning|sqrtsign|relax |endgroup
+\def\sq@delim{\delimiter\sq@sqrt\relax}
+%    \end{macrocode}
+%
+% \subsubsection{Drawing fake square root signs}
+%
+% \TeX\ absolutely insists on drawing square root signs with a vinculum over
+% the top.  In order to get the same effect, we have to attempt to emulate
+% \TeX's behaviour.
+%
+% \begin{macro}{\sqrtdel}
+%
+% This does the main job of typesetting a vinculum-free radical.\footnote{^^A
+%   Note for chemists: this is nothing to do with short-lived things which
+%   don't have their normal numbers of electrons.  And it won't reduce the
+%   appearance of wrinkles either.}
+% It's more or less a duplicate of what \TeX\ does internally, so it might be
+% a good plan to have a copy of Appendix~G open while you examine this.
+%
+% We start off by using |\mathpalette| to help decide how big things should
+% be.
+%
+%    \begin{macrocode}
+\def\sqrtdel{\mathpalette\sqrtdel@i}
+%    \end{macrocode}
+%
+% Read the contents of the radical into a box, so we can measure it.
+%
+%    \begin{macrocode}
+\def\sqrtdel@i#1#2{%
+  \setbox\z@\hbox{$\m@th#1#2$}% %%% Bzzzt -- uncramps the mathstyle
+%    \end{macrocode}
+%
+% Now try and sort out the values needed in this calculation.  We'll assume
+% that $\xi_8$ is 0.6\,pt, the way it usually is.  Next try to work out the
+% value of $\varphi$.
+%
+%    \begin{macrocode}
+  \ifx#1\displaystyle%
+    \@tempdima1ex%
+  \else%
+    \@tempdima.6\p@%
+  \fi%
+%    \end{macrocode}
+%
+% That was easy.  Now for $\psi$.
+%
+%    \begin{macrocode}
+  \@tempdimb.6\p@%
+  \advance\@tempdimb.25\@tempdima%
+%    \end{macrocode}
+%
+% Build the `delimiter' in a box of height $h(x)+d(x)+\psi+\xi_8$, as
+% requested.  Box~2 will do well for this purpose.
+%
+%    \begin{macrocode}
+  \dimen@.6\p@%
+  \advance\dimen@\@tempdimb%
+  \advance\dimen@\ht\z@%
+  \advance\dimen@\dp\z@%
+  \setbox\tw@\hbox{%
+    $\left\sq@delim\vcenter to\dimen@{}\right.\n@space$%
+  }%
+%    \end{macrocode}
+%
+% Now we need to do some more calculating (don't you hate it?).  As far as
+% Appendix~G is concerned, $\theta=h(y)=0$, because we want no rule over the
+% top.  
+%
+%    \begin{macrocode}
+  \@tempdima\ht\tw@%
+  \advance\@tempdima\dp\tw@%
+  \advance\@tempdima-\ht\z@%
+  \advance\@tempdima-\dp\z@%
+  \ifdim\@tempdima>\@tempdimb%
+    \advance\@tempdima\@tempdimb%
+    \@tempdimb.5\@tempdima%
+  \fi%
+%    \end{macrocode}
+%
+% Work out how high to raise the radical symbol.  Remember that Appendix~G
+% thinks that the box has a very small height, although this is untrue here.
+%
+%    \begin{macrocode}
+  \@tempdima\ht\z@%
+  \advance\@tempdima\@tempdimb%
+  \advance\@tempdima-\ht\tw@%
+%    \end{macrocode}
+%
+% Build the output (finally).  The brace group is there to turn the output
+% into a mathord, one of the few times that this is actually desirable.
+%
+%    \begin{macrocode}
+  {\raise\@tempdima\box\tw@\vbox{\kern\@tempdimb\box\z@}}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{The new square root command}
+%
+% This is where we reimplement all the square root stuff.  Most of this stuff
+% comes from the \PlainTeX\ macros, although some is influenced by \AmSTeX\
+% and \LaTeXe, and some is original.  I've tried to make the spacing vaguely
+% automatic, so although it's not configurable like \AmSTeX's version, the
+% output should look nice more of the time.  Maybe.
+%
+% \begin{macro}{\sqrt}
+%
+% \LaTeX\ says this must be robust, so we make it robust.  The first thing to
+% do is to see if there's a star and pass the appropriate squareroot-drawing
+% command on to the rest of the code.
+%
+%    \begin{macrocode}
+\DeclareRobustCommand\sqrt{\@ifstar{\sqrt@i\sqrtdel}{\sqrt@i\sqrtsign}}
+%    \end{macrocode}
+%
+% Now we can sort out an optional argument to be displayed on the root.
+%
+%    \begin{macrocode}
+\def\sqrt@i#1{\@ifnextchar[{\sqrt@ii{#1}}{\sqrt@iv{#1}}}
+%    \end{macrocode}
+%
+% Stages~2 and~3 below are essentially equivalents of \PlainTeX's
+% |\root|\dots|\of| and |\r@@t|.  Here we also find the first wrinkle: the
+% |\rootbox| used to store the number is spaced out on the left if necessary.
+% There's a backspace after the end so that the root can slip underneath, and
+% everything works out nicely.  Unfortunately size is fixed here, although
+% doesn't actually seem to matter.
+%
+%    \begin{macrocode}
+\def\sqrt@ii#1[#2]{%
+  \setbox\rootbox\hbox{$\m@th\scriptscriptstyle{#2}$}%
+  \ifdim\wd\rootbox<6\p@%
+    \setbox\rootbox\hb@xt@6\p@{\hfil\unhbox\rootbox}%
+  \fi%
+  \mathpalette{\sqrt@iii{#1}}%
+}
+%    \end{macrocode}
+%
+% Now we can actually build everything.  Note that the root is raised by its
+% depth -- this prevents a common problem with letters with descenders.
+%
+%    \begin{macrocode}
+\def\sqrt@iii#1#2#3{%
+  \setbox\z@\hbox{$\m@th#2#1{#3}$}%
+  \dimen@\ht\z@%
+  \advance\dimen@-\dp\z@%
+  \dimen@.6\dimen@%
+  \advance\dimen@\dp\rootbox%
+  \mkern-3mu%
+  \raise\dimen@\copy\rootbox%
+  \mkern-10mu%
+  \box\z@%
+}
+%    \end{macrocode}
+%
+% Finally handle a non-numbered root.  We read the rooted text in as an
+% argument, to stop problems when people omit the braces.  (\AmSTeX\ does
+% this too.)
+%
+%    \begin{macrocode}
+\def\sqrt@iv#1#2{#1{#2}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\root}
+%
+% We also re-implement \PlainTeX's |\root| command, just in case someone uses
+% it, and supply a star-variant.  This is all very trivial.
+%
+%    \begin{macrocode}
+\def\root{\@ifstar{\root@i\sqrtdel}{\root@i\sqrtsign}}
+\def\root@i#1#2\of{\sqrt@ii{#1}[#2]}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{Modular programming}
+%
+% \begin{macro}{\pmod}
+%
+% Do some hacking if not |\ifouter|.
+%
+%    \begin{macrocode}
+\def\pmod#1{%
+  \ifinner\;\else\allowbreak\mkern18mu\fi%
+  ({\operator@font mod}\,\,#1)%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{Some magic new maths characters}
+%
+% \begin{macro}{\bitor}
+% \begin{macro}{\bitand}
+% \begin{macro}{\dblor}
+% \begin{macro}{\dbland}
+% \begin{macro}{\xor}
+% \begin{macro}{\lor}
+% \begin{macro}{\ror}
+% \begin{macro}{\lsl}
+% \begin{macro}{\lsr}
+%
+% The new boolean operators.
+%
+%    \begin{macrocode}
+\DeclareMathSymbol{&}{\mathbin}{operators}{`\&}
+\DeclareMathSymbol{\bitand}{\mathbin}{operators}{`\&}
+\def\bitor{\mathbin\mid}
+\def\dblor{\mathbin{\mid\mid}}
+\def\dbland{\mathbin{\mathrel\bitand\mathrel\bitand}}
+\let\xor\oplus
+\def\lsl{\mathbin{<\!\!<}}
+\def\lsr{\mathbin{>\!\!>}}
+\def\rol{\mathbin{<\!\!<\!\!<}}
+\def\ror{\mathbin{>\!\!>\!\!>}}
+\AtBeginDocument{\ifx\lll\@@undefined\else
+  \def\lsl{\mathbin{\ll}}
+  \def\lsr{\mathbin{\gg}}
+  \def\rol{\mathbin{\lll}}
+  \def\ror{\mathbin{\ggg}}
+\fi}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\cat}
+% \begin{macro}{\compose}
+% \begin{macro}{\implies}
+% \begin{macro}{\vect}
+% \begin{macro}{\d}
+% \begin{macro}{\jacobi}
+%
+% A mixed bag of stuff.
+%
+%    \begin{macrocode}
+\def\cat{\mathbin{\|}}
+\let\compose\circ
+\def\implies{\Rightarrow}
+\def\vect#1{\mathord{\mathbf{#1}}}
+\def\d{\mathord{\operator@font d}}
+\def\jacobi#1#2{{{#1}\overwithdelims()#2}}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\statclose}
+% \begin{macro}{\compind}
+%
+% Fancy new relations for probability distributions.
+%
+%    \begin{macrocode}
+\def\statclose{\mathrel{\mathop{=}\limits^{\scriptscriptstyle s}}}
+\def\compind{\mathrel{\mathop{\approx}\limits^{\scriptscriptstyle c}}}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\keys}
+% \begin{macro}{\dom}
+% \begin{macro}{\ran}
+% \begin{macro}{\supp}
+% \begin{macro}{\lcm}
+%
+% And the new operator names.
+%
+%    \begin{macrocode}
+\def\keys{\mathop{\operator@font keys}\nolimits}
+\def\dom{\mathop{\operator@font dom}\nolimits}
+\def\ran{\mathop{\operator@font ran}\nolimits}
+\def\supp{\mathop{\operator@font supp}\nolimits}
+\def\lcm{\mathop{\operator@font lcm}\nolimits}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Blackboard bold stuff}
+%
+% \begin{macro}{\Z}
+% \begin{macro}{\Q}
+% \begin{macro}{\R}
+% \begin{macro}{\C}
+% \begin{macro}{\N}
+% \begin{macro}{\F}
+% \begin{macro}{\powerset}
+%
+% First of all, the signs.
+%
+%    \begin{macrocode}
+\def\Z{\mathbb{Z}}
+\def\Q{\mathbb{Q}}
+\def\R{\mathbb{R}}
+\def\C{\mathbb{C}}
+\def\N{\mathbb{N}}
+\def\F{\mathbb{F}}
+\def\powerset{\mathbb{P}}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% And now, define |\mathbb| if it's not there already.
+%
+%    \begin{macrocode}
+\AtBeginDocument{\ifx\mathbb\@@undefined\let\mathbb\mathbf\fi}
+%    \end{macrocode}
+%
+% \subsection{Biggles}
+%
+% Now for some user-controlled delimiter sizing.  The standard bigness of
+% plain \TeX's delimiters are all right, but it's a little limiting.
+%
+% The biggness of delimiters is based on the size of the current |\strut|,
+% which \LaTeX\ keeps up to date all the time.  This will make the various
+% delimiters grow in proportion when the text gets bigger.  Actually, I'm
+% not sure that this is exactly right -- maybe it should be nonlinear,
+%
+% \begin{macro}{\bbigg}
+% \begin{macro}{\bbiggl}
+% \begin{macro}{\bbiggr}
+% \begin{macro}{\bbiggm}
+%
+% This is where the bigness is done.  This is more similar to the plain \TeX\
+% big delimiter stuff than to the \package{amsmath} stuff, although there's
+% not really a lot of difference.
+%
+% The two arguments are a multiplier for the delimiter size, and a small
+% increment applied \emph{before} the multiplication (which is optional).
+%
+% This is actually a front for a low-level interface which can be called
+% directly for efficiency.
+%
+%    \begin{macrocode}
+\def\bbigg{\@bbigg\mathord} \def\bbiggl{\@bbigg\mathopen}
+\def\bbiggr{\@bbigg\mathclose} \def\bbiggm{\@bbigg\mathrel}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@bbigg}
+%
+% This is an optional argument parser providing a front end for the main
+% macro |\bbigg@|.
+%
+%    \begin{macrocode}
+\def\@bbigg#1{\@ifnextchar[{\@bigg@i{#1}}{\@bigg@i{#1}[\z@]}}
+\def\@bigg@i#1[#2]#3#4{#1{\bbigg@{#2}{#3}{#4}}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\bbigg@}
+%
+% This is it, at last.  The arguments are as described above: an addition
+% to be made to the strut height, and a multiplier.  Oh, and the delimiter,
+% of course.
+%
+% This is a bit messy.  The smallest `big' delimiter, |\big|, is the same
+% height as the current strut box.  Other delimiters are~$1\frac12$, $2$
+% and~$2\frac12$ times this height.  I'll set the height of the delimiter by
+% putting in a |\vcenter| of the appropriate size.
+%
+% Given an extra height~$x$, a multiplication factor~$f$ and a strut
+% height~$h$ and depth~$d$, I'll create a vcenter with total height
+% $f(h+d+x)$.  Easy, isn't it?
+%
+%    \begin{macrocode}
+\def\bbigg@#1#2#3{%
+  {\hbox{$%
+    \dimen@\ht\strutbox\advance\dimen@\dp\strutbox%
+    \advance\dimen@#1%
+    \dimen@#2\dimen@%
+    \left#3\vcenter to\dimen@{}\right.\n@space%
+  $}}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\big}
+% \begin{macro}{\Big}
+% \begin{macro}{\bigg}
+% \begin{macro}{\Bigg}
+%
+% Now for the easy macros.
+%
+%    \begin{macrocode}
+\def\big{\bbigg@\z@\@ne}
+\def\Big{\bbigg@\z@{1.5}}
+\def\bigg{\bbigg@\z@\tw@}
+\def\Bigg{\bbigg@\z@{2.5}}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{The `QED' symbol}
+%
+% \begin{macro}{\qed}
+% \begin{macro}{\qedrule}
+% \begin{macro}{\qedsymbol}
+%
+% This is fairly simple.  Just be careful will the glue and penalties.  The
+% size of the little box is based on the current font size.
+%
+% The horizontal list constructed by the macro is like this:
+%
+% \begin{itemize}
+% \item A |\quad| of space.  This might get eaten if there's a break here or
+%   before.  That's OK, though.
+% \item An empty box, to break a run of discardable items.
+% \item A |\penalty 10000| to ensure that the spacing glue isn't discarded.
+% \item |\hfill| glue to push the little rule to the end of the line.
+% \item A little square rule `\qedrule', with some small kerns around it.
+% \item A glue item to counter the effect of glue added at the paragraph
+%   boundary. 
+% \end{itemize}
+%
+% A |\qed| commend ends the paragraph.
+%
+%    \begin{macrocode}
+\providecommand\qed{%
+  \leavevmode%
+  \unskip%
+  \penalty\@M\hfill%
+  \hbox{}\penalty\z@\quad%
+  \hbox{}\penalty\@M\hfill\qedsymbol\hskip-\parfillskip\par%
+}
+\def\qedrule{{%
+  \dimen@\ht\strutbox%
+  \advance\dimen@\dp\strutbox
+  \dimen@ii1ex%
+  \advance\dimen@-\dimen@ii%
+  \divide\dimen@\tw@%
+  \advance\dimen@-\dp\strutbox%
+  \advance\dimen@\dimen@ii%
+  \advance\dimen@ii-\dimen@%
+  \kern\p@%
+  \vrule\@width1ex\@height\dimen@\@depth\dimen@ii%
+  \kern\p@%
+}}
+\providecommand\qedsymbol{\qedrule}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{ignore}
+% The following is the original definition of the enhanced eqnarray
+% environment.  It's not supported, although if you can figure out how to
+% extract it, it's all yours.
+% \end{ignore}
+%
+% \begin{old-eqnarray}
+%
+% \subsection{The sparkly new \env{eqnarray}}
+%
+% Start off by writing a different package.
+%
+%    \begin{macrocode}
+%</package>
+%<*oldeqnarray>
+%    \end{macrocode}
+%
+% \subsubsection{Options handling}
+%
+% We need to be able to cope with \textsf{fleqn} and \textsf{leqno} options.
+% This will adjust our magic modified \env{eqnarray} environment
+% appropriately.
+%
+%    \begin{macrocode}
+\newif\if@fleqn
+\newif\if@leqno
+\DeclareOption{fleqn}{\@fleqntrue}
+\DeclareOption{leqno}{\@leqnotrue}
+\ProcessOptions
+%    \end{macrocode}
+%
+% This is all really different to the \LaTeX\ version.  I've looked at the
+% various \env{tabular} implementations, the original \env{eqnarray} and the
+% \textit{\TeX book} to see how best to do this, and then went my own way.
+% If it doesn't work it's all my fault.
+%
+% \subsubsection{Some useful registers}
+%
+% The old \LaTeX\ version puts the equation numbers in by keeping a count of
+% where it is in the alignment.  Since I don't know how may columns there are
+% going to be, I'll just use a switch in the preamble to tell me to stop
+% tabbing.
+%
+%    \begin{macrocode}
+\newif\if@eqalast
+%    \end{macrocode}
+%
+% Now define some useful length parameters.  First allocate them:
+%
+%    \begin{macrocode}
+\newskip\eqaopenskip
+\newskip\eqacloseskip
+\newskip\eqacolskip
+\newskip\eqainskip
+%    \end{macrocode}
+%
+% Now assign some default values.  Users can play with these if they really
+% want although I can't see the point myself.
+%
+%    \begin{macrocode}
+\if@fleqn
+  \AtBeginDocument{\eqaopenskip\leftmargini}
+\else
+  \eqaopenskip\@centering
+\fi
+\eqacloseskip\@centering
+\eqacolskip\@centering
+\eqainskip\z@
+%    \end{macrocode}
+%
+% We allow the user to play with the style if this is really wanted.  I dunno
+% why, really.  Maybe someone wants very small alignments.
+%
+%    \begin{macrocode}
+\let\eqa@style\displaystyle
+%    \end{macrocode}
+%
+% \subsubsection{The main environments}
+%
+% We define the toplevel commands here.  They just add in default arguments
+% and then call |\@eqnarray| with a preamble string.  The only difference is
+% the last column they add in -- \env{eqnarray$*$} throws away the last
+% column by sticking it in box~0.  (I used to |\@gobble| it but that caused
+% the |\cr| to be lost.)
+%
+%    \begin{macrocode}
+\def\eqnarray{\@ifnextchar[\eqnarray@i{\eqnarray@i[rcl]}}
+\def\eqnarray@i[#1]{%
+  \@eqnarray{#1!{\hb@xt@\z@{\hss##}\tabskip\z@}}
+}
+\@namedef{eqnarray*}{\@ifnextchar[\eqnarray@s@i{\eqnarray@s@i[rcl]}}
+\def\eqnarray@s@i[#1]{%
+  \@eqnarray{#1!{\nonumber\setbox\z@\hbox{##}\tabskip\z@}}%
+}
+%    \end{macrocode}
+%
+% \subsubsection{Set up the initial display}
+%
+% \begin{macro}{\@eqnarray}
+%
+% The |\@eqnarray| command does most of the initial work.  It sets up some
+% flags and things, builds the |\halign| preamble, and returns.
+%
+%    \begin{macrocode}
+\def\@eqnarray#1{%
+%    \end{macrocode}
+%
+% Start playing with the counter here.  The original does some icky internal
+% playing, which isn't necessary.  The |\if@eqnsw| switch is |true| if the
+% user hasn't supplied an equation number.  The |\if@eqalast| switch is
+% |true| in the final equation-number column.
+%
+%    \begin{macrocode}
+  \refstepcounter{equation}%
+  \@eqalastfalse%
+  \global\@eqnswtrue%
+  \m@th%
+%    \end{macrocode}
+%
+% Set things up for the |\halign| which is coming up.
+%
+%    \begin{macrocode}
+  \openup\jot%
+  \tabskip\eqaopenskip%
+  \let\\\@eqncr%
+  \everycr{}%
+  $$%
+%    \end{macrocode}
+%
+% We'll build the real |\halign| and preamble in a token register.  All we
+% need to do is stuff the header in the token register, clear a switch
+% (that'll be explained later), parse the preamble and then expand the
+% tokens we collected.  Easy, no?
+%
+%    \begin{macrocode}
+  \toks@{\halign to\displaywidth\bgroup}%
+  \@tempswafalse%
+  \eqa@preamble#1\end%
+  \the\toks@\cr%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Parsing the preamble}
+%
+% All this actually involves is reading the next character and building a
+% command from it.  That can pull off an argument if it needs it.  Just make
+% sure we don't fall off the end and we'll be OK.
+%
+%    \begin{macrocode}
+\def\eqa@preamble#1{%
+  \ifx\end#1\else\csname eqa@char@#1\expandafter\endcsname\fi%
+}
+%    \end{macrocode}
+%
+% Adding stuff to the preamble tokens is a simple matter of using
+% |\expandafter| in the correct way.\footnote{^^A
+%   I have no idea why \LaTeX\ uses \cmd\edef\ for building its preamble.  It
+%   seems utterly insane to me -- the amount of bodgery that \env{tabular}
+%   has to go through to make everything expand at the appropriate times is
+%   scary.  Maybe Messrs~Lamport and Mittelbach just forgot about token
+%   registers when they were writing the code.  Maybe I ought to rewrite the
+%   thing properly some time.  Sigh.
+%
+%   As a sort of postscript to the above, I \emph{have} rewritten the
+%   \env{tabular} environment, and made a damned fine job of it, in my
+%   oh-so-humble opinion.  All this \env{eqnarray} stuff has been remoulded
+%   in terms of the generic column-defining things in \package{mdwtab}.
+%   You're reading the documentation of the old version, which isn't
+%   supported any more, so any bugs here are your own problem.}
+%
+%    \begin{macrocode}
+\def\eqa@addraw#1{\expandafter\toks@\expandafter{\the\toks@#1}}
+%    \end{macrocode}
+%
+% Now for some cleverness again.  In order to put all the right bits of
+% |\tabskip| glue in the right places we must \emph{not} terminate each
+% column until we know what the next one is.  We set |\if@tempswa| to be
+% |true| if there's a column waiting to be closed (so it's initially
+% |false|).  The following macro adds a column correctly, assuming we're in
+% a formula.  Other column types make their own arrangements.
+%
+%    \begin{macrocode}
+\def\eqa@add#1{%
+  \if@tempswa%
+    \eqa@addraw{\tabskip\eqainskip&#1}%
+  \else%
+    \eqa@addraw{#1}%
+  \fi%
+  \@tempswatrue%
+}
+%    \end{macrocode}
+%
+% Now to defining column types.  Let's define a macro which allows us to
+% define column types:
+%
+%    \begin{macrocode}
+\def\eqa@def#1{\expandafter\def\csname eqa@char@#1\endcsname}
+%    \end{macrocode}
+%
+% Now we can define the column types.  Each column type must loop back to
+% |\eqa@preamble| once it's finished, to read the rest of the preamble
+% string.  Note the positioning of ord atoms in the stuff below.  This will
+% space out relations and binops correctly when they occur at the edges of
+% columns, and won't affect ord atoms at the edges, because ords pack
+% closely.
+%
+% First the easy onces.  Just stick |\hfil| in the right places and
+% everything will be all right.
+%
+%    \begin{macrocode}
+\eqa@def r{\eqa@add{\hfil$\eqa@style##{}$}\eqa@preamble}
+\eqa@def c{\eqa@add{\hfil$\eqa@style{}##{}$\hfil}\eqa@preamble}
+\eqa@def l{\eqa@add{$\eqa@style{}##$\hfil}\eqa@preamble}
+\eqa@def x{\eqa@add{\hfil$\eqa@style##$\hfil}\eqa@preamble}
+%    \end{macrocode}
+%
+% Now for the textual ones.  This is also fairly easy.
+%
+%    \begin{macrocode}
+\eqa@def T#1{%
+  \eqa@add{}%
+  \if#1l\else\eqa@addraw{\hfil}\fi%
+  \eqa@addraw{##}%
+  \if#1r\else\eqa@addraw{\hfil}\fi%
+  \eqa@preamble%
+}
+%    \end{macrocode}
+%
+% Sort of split types of equations.  I mustn't use |\rlap| here, or
+% everything goes wrong -- |\\| doesn't get noticed by \TeX\ in the same way
+% as |\cr| does.
+%
+%    \begin{macrocode}
+\eqa@def L{\eqa@add{\hb@xt@\z@{$\eqa@style##$\hss}\qquad}\eqa@preamble}
+%    \end{macrocode}
+%
+% The \lit{:} column type is fairly simple.  We set |\tabskip| up to make
+% lots of space and close the current column, because there must be one.^^A
+% \footnote{This is an assumption.}
+%
+%    \begin{macrocode}
+\eqa@def :{%
+  \eqa@addraw{\tabskip\eqacolskip&}\@tempswafalse\eqa@preamble%
+}
+\eqa@def q{\eqa@add{\quad}\@tempswafalse\eqa@preamble}
+%    \end{macrocode}
+%
+% The other column types just insert given text in an appropriate way.
+%
+%    \begin{macrocode}
+\eqa@def >#1{\eqa@add{#1}\@tempswafalse\eqa@preamble}
+\eqa@def <#1{\eqa@addraw{#1}\eqa@preamble}
+%    \end{macrocode}
+%
+% Finally, the magical \lit{!} column type, which sets the equation number.
+% We set up the |\tabskip| glue properly, tab on, and set the flag which
+% marks the final column.
+%
+%    \begin{macrocode}
+\eqa@def !#1{%
+  \eqa@addraw{\tabskip\eqacloseskip&\@eqalasttrue#1}\eqa@preamble%
+}
+%    \end{macrocode}
+%
+% \subsubsection{Newline codes}
+%
+% Newline sequences (|\\|) get turned into calls of |\@eqncr|.  The job is
+% fairly simple, really.  However, to avoid reading `|&|' characters
+% prematurely, we set up a magic brace (from the \package{array} package --
+% this avoids creating ord atoms and other nastyness).
+%
+%    \begin{macrocode}
+\def\@eqncr{%
+  \iffalse{\fi\ifnum0=`}\fi%
+  \@ifstar{\eqacr@i{\@M}}{\eqacr@i{\interdisplaylinepenalty}}%
+}
+\def\eqacr@i#1{\@ifnextchar[{\eqacr@ii{#1}}{\eqacr@ii{#1}[\z@]}}
+\def\eqacr@ii#1[#2]{%
+  \ifnum0=`{}\fi%
+  \eqa@eqnum%
+  \noalign{\penalty#1\vskip#2\relax}%
+}
+%    \end{macrocode}
+%
+% \subsubsection{Setting equation numbers}
+%
+% Before we start, we need to generalise the flush-left number handling bits.
+% The macro |\eqa@eqpos| will put its argument in the right place.
+%
+%    \begin{macrocode}
+\if@leqno
+  \def\eqa@eqpos#1{%
+    \hb@xt@.01\p@{}\rlap{\normalfont\normalcolor\hskip-\displaywidth#1}%
+  }
+\else
+  \def\eqa@eqpos#1{\normalfont\normalcolor#1}
+\fi
+%    \end{macrocode}
+%
+% First we need to move into the right column.  Then we just set the equation
+% number appropriately.  There is some subtlety here, ish.  The |\relax| is
+% important, to delay expansion of the |\if|\dots\ until the new column has
+% been started.  The two helper macros are important too, to hide `|&|'s and
+% `|\cr|'s from \TeX's scanner until the right time.
+%
+%    \begin{macrocode}
+\def\eqa@eqnum{%
+  \relax%
+  \if@eqalast\expandafter\eqa@eqnum@i\else\expandafter\eqa@eqnum@ii\fi%
+}
+\def\eqa@eqnum@i{%
+  \if@eqnsw%
+    \eqa@eqpos{(\theequation)}\stepcounter{equation}%
+  \else%
+    \eqa@eqpos\eqa@number%
+  \fi%
+  \global\@eqnswtrue%
+  \cr%
+}
+\def\eqa@eqnum@ii{&\eqa@eqnum}
+%    \end{macrocode}
+%
+% \subsubsection{Numbering control}
+%
+% This is trivial.  We set the |\if@eqnsw| flag to be |false| and store the
+% text in a macro.
+%
+%    \begin{macrocode}
+\let\nonumber\relax
+\newcommand\nonumber[1][]{\global\@eqnswfalse\global\def\eqa@number{#1}}
+%    \end{macrocode}
+%
+% \subsubsection{Closing the environments off}
+%
+% This is really easy.  Set the final equation number, close the |\halign|,
+% tidy up the equation counter (it's been stepped once too many times) and
+% close the display.
+%
+%    \begin{macrocode}
+\def\endeqnarray{%
+  \eqa@eqnum%
+  \egroup%
+  \global\advance\c@equation\m@ne%
+  $$%
+  \global\@ignoretrue%
+}
+\expandafter\let\csname endeqnarray*\endcsname\endeqnarray
+%    \end{macrocode}
+%
+% Now start up the other package again.
+%
+%    \begin{macrocode}
+%</oldeqnarray>
+%<*package>
+%    \end{macrocode}
+%
+% \end{old-eqnarray}
+%
+% That's all there is.  Byebye.
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+\endinput
diff --git a/mdwtab.dtx b/mdwtab.dtx
new file mode 100644
index 0000000..86afbdc
--- /dev/null
+++ b/mdwtab.dtx
@@ -0,0 +1,5525 @@
+% \begin{meta-comment}
+%
+% $Id: mdwtab.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
+%
+% Another rewrite of the tabular environment, and maths alignments
+%
+% (c) 1996 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: mdwtab.dtx,v $
+% Revision 1.1  2002/02/03 20:49:03  mdw
+% Checkin for new build system.
+%
+% Revision 1.8  1996/12/09 23:20:42  mdw
+% (\tab@setstrut): Fixed so that it uses \dimen@ii for the strut depth,
+% as advertised.
+%
+% Revision 1.7  1996/11/29 21:59:16  mdw
+% Fixed a little formatting mistake in a syntax diagram, and switched over
+% to the new syntax diagram commands on the grounds that they're slightly
+% less messy.  Maybe.
+%
+% Revision 1.6  1996/11/19 20:54:33  mdw
+% Entered into RCS
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% mdwtab package -- another rewrite of the tabular environment, etc.
+%% Copyright (c) 1996 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preambles>
+%<+mdwtab>\NeedsTeXFormat{LaTeX2e}
+%<+mdwtab>\ProvidesPackage{mdwtab}
+%<+mdwtab>                [1998/04/28 1.9 Table typesetting with style]
+%<+mathenv>\NeedsTeXFormat{LaTeX2e}
+%<+mathenv>\ProvidesPackage{mathenv}
+%<+mathenv>                [1998/04/28 1.9 Various maths environments]
+% \end{meta-comment}
+%
+% \CheckSum{2876}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{mdwtab}
+\describespackage{mathenv}
+\addcontents{lot}{\listoftables}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+%^^A-------------------------------------------------------------------------
+% \renewcommand{\tabstyle}{\small}
+%
+% \section{User guide}
+%
+%
+% The \package{mdwtab} package contains a reimplementation of the standard
+% \LaTeX\ \env{tabular} and \env{array} environments.  This is not just an
+% upgraded version: it's a complete rewrite.  It has several advantages over
+% the official \package{array} package (not raw \LaTeX's, which is even less
+% nice), and it's more-or-less compatible.  Most of these are rather
+% technical, I'll admit.
+%
+% \begin{itemize}
+%
+% \item The newcolumn system is properly and perfectly integrated into the
+%       system.  There are now \emph{no} `primitive' column types -- all the
+%       standard types are created as user-defined columns.
+%
+% \item You can define entirely different table-like environments using the
+%       equipment here.  It's still hard work, although less so than before.
+%       I'll do an example of this some time.
+%
+% \item Construction of the preamble is generally much tidier.  I've used
+%       token registers rather than |\edef|, and it's all done very nicely.
+%
+% \item Fine spacing before and after rules (described by DEK as `a mark of
+%       quality') is now utterly trivial, since the preamble-generator will
+%       store the appropriate information.
+%
+% \item You can use \env{array} in LR and paragraph modes without having
+%       to surround it with `|$|' signs.
+%
+% \item Usually you don't want tables in the middle of paragraphs.  For these
+%       cases, I've provided a simpler way to position the table
+%       horizontally.
+%
+% \item Footnotes work properly inside \env{tabular} environments (hoorah!).
+%       You can `catch' footnotes using the \env{minipage} environment if
+%       you like.  (It uses an internal version of the \package{footnote}
+%       package to handle footnotes, which doesn't provide extra goodies like
+%       the \env{footnote} environment; you'll need to load the full package
+%       explicitly to get them.)
+%
+% \item Standard \LaTeX\ tabular environments have a problem with lining up
+%       ruled tables.  The |\firsthline| command given in the \textit{\LaTeX\
+%       Companion} helps a bit, but it's not really good enough, and besides,
+%       it doesn't \emph{actually} line the text up right after all.  The
+%       \package{mdwtab} package does the job properly to begin with, so you
+%       don't need to worry.
+%
+% \end{itemize}
+%
+% I've tested the following packages with \package{mdwtab}, and they all
+% work.  Some of the contortions required to make them work weren't pleasant,
+% but you don't need to know about them.  By a strange coincidence, all the
+% packages were written by David Carlisle.  Anyway, here's the list:
+% \begin{itemize}
+% \item The quite nice \package{dcolumn} package.
+% \item The more useful \package{delarray} package.
+% \item The rather spiffy \package{hhline} package.
+% \item The truly wonderful \package{tabularx} package.
+% \item The utterly magnificent \package{longtable} package.
+% \end{itemize}
+%
+% Note that I've looked at \package{supertabular} as well: it won't work, so
+% use \package{longtable} instead, 'cos it's much better.
+%
+%
+% \subsection{The downside}
+%
+% There's no such thing as a free lunch.  The \package{mdwtab} environment
+% is not 100\% compatible with the \env{tabular} environment found in
+% \LaTeXe\ or the \package{array} package.
+%
+% The differences between \package{mdwtab} and \LaTeXe's \env{tabular}
+% environment are as follows:
+%
+% \begin{itemize} \synshorts \let\`=\lq
+%
+% \item The vertical spacing in \env{array} environments is different to
+%       that in \env{tabular} environments.  This produces more attractive
+%       results in most mathematical uses of \env{array}s, in the author's
+%       opinion.  The spacing can be modified by playing with length
+%       parameters.
+%
+% \item The presence of horizontal and vertical rules will alter the spacing
+%       of the table (so a pair of columns separated by a `|' is wider than
+%       a pair with no separation by "\\arrayrulewidth".  This does mean that
+%       horizontal and vertical rules match up properly -- the usual \LaTeX\
+%       environment makes the horizontal rules stop just short of the edge
+%       of the table, making an ugly mess (check out the \textit{\LaTeX\
+%       book} if you don't believe me -- page~62 provides a good example).
+%       The \package{array} package handles rules in the same way as
+%       \package{mdwtab}.
+%
+% \setbox0=\hbox{\footnotesize`\\def\\xcs{\\tabskip=\\fill}'}
+% \setbox2=\hbox{\footnotesize`...@{\\span\\xcs}...'}
+% \item In common with the \package{array} package, there are some
+%       restrictions on the use of the "\\extracolsep" command in preambles:
+%       you may use at most one "\\extracolsep" command in each `@' or `!'
+%       expression.  Also, you can't say
+%       \begin{listing}
+%\newcommand{\xcs}{\extracolsep{\fill}}
+%       \end{listing}
+%       and then expect something like `...@{\\xcs}...' to actually work --
+%       the "\\extracolsep" mustn't be hidden inside any other
+%       commands.  Because things like `@' expressions aren't expanded at
+%       the time, "\\extracolsep" has to be searched and processed
+%       \`by hand'.\footnote{^^A
+%         All \cs{extracolsep} does is modify the \cs{tabskip} glue, so
+%         if you were an evil \TeX\ hacker like me, you could just say
+%         \unhbox0\ and put \unhbox2\ in your preamble.  That'd work nicely.
+%         It also works with the \package{array} package.}
+%
+% \item Control sequences (commands) in a table's preamble aren't expanded
+%       before the preamble is read.  In fact, commands in the preamble are
+%       considered to be column types, and their names are entirely
+%       independent of normal \LaTeX\ commands.  No column types of this
+%       nature have yet been defined\footnote{^^A
+%         There used to be an internal \cs{@magic} type used by
+%         \env{eqnarray}, but you're not supposed to know about that.
+%         Besides, it's not there any more.}
+%       but the possibility's always there.  Use the "\\newcolumntype" or
+%       "\\coldef" commands to define new column types.
+%
+% \item The preamble parsing works in a completely different way.  There is
+%       a certain amount of compatibility provided, although it's heavily
+%       geared towards keeping \package{longtable} happy and probably won't
+%       work with other packages.
+%
+% \item Obscure constructs which were allowed by the old preamble parser but
+%       violate the syntax shown in the next section (e.g., `|@{}|' to
+%       suppress the "\\doublerulesep" space between two vertical rules,
+%       described in \textit{The \LaTeX\ Companion} as \`a misuse of the
+%       `@{...}' qualifier') are now properly outlawed.  You will be given
+%       an error message if you attempt to use such a construction.
+%
+% \item The `*' forms (which repeat column types) are now expanded at a
+%       different time.  Previously, preambles like `c@*{4}{{:}@}{--}c'
+%       were considered valid (the example would expand to
+%       `c@{:}@{:}@{:}@{:}@{--}c'), because `*'s were expanded before the
+%       preamble was actually parsed.  In the new system, `*' is treated
+%       just like any other preamble character (it just has a rather odd
+%       action), and preambles like this will result in an error (and
+%       probably a rather confusing one).
+%
+% \end{itemize}
+%
+% There are also several incompatibilities between \package{mdwtab} and
+% \package{array}:
+%
+% \begin{itemize} \synshorts \let\`=\lq
+%
+% \item Because of the way "\\newcolumntype" works in the \package{array}
+%       package, a horrid construction like
+%       \begin{listing}
+%\newcolumntype{x}{{:}}
+%\begin{tabular}{|c!xc|}
+%       \end{listing}
+%       is considered to be valid, and is interpreted as `|c!{:}c|'.  My
+%       reading of pages~54 and~55 of the \textit{\LaTeX\ book} tells me
+%       that this sort of thing is forbidden in normal \LaTeX\ commands.
+%       The \package{mdwtab} preamble parser now treats column type letters
+%       much more like commands with the result that the hacking above won't
+%       work any more.  The construction above would actually be interpreted
+%       as `|c!{x}c|' (i.e., the `x' column type wouldn't be expanded to
+%       `{:}' because the parser noticed that it was the argument to the
+%       `!' modifier\footnote{^^A
+%         This is a direct result of the way \TeX\ treats undelimited
+%         arguments.  See chapters~5 and~20 of \textit{The \TeX book} for
+%         more information about how grouping affects argument reading.}).
+%
+% \item Most of the points above, particularly those relating to the
+%       handling of the preamble, also apply to the \package{array} package.
+%       it's not such an advance over the \LaTeXe\ version as everyone said
+%       it was.
+%
+% \end{itemize}
+%
+%
+% \subsection{Syntax}
+%
+% \DescribeEnv{tabular}
+% \DescribeEnv{tabular*}
+% \DescribeEnv{array}
+% So that everyone knows where I stand, here's a complete syntax for my
+% version of the \env{tabular} environment, and friends
+%
+% \begin{grammar}
+%
+% <tabular-env>	::= \[[
+%   "\\begin"
+%   \begin{stack}
+%     "{tabular}" \\ "{tabular*}" "{" <length> "}" \\
+%     "{array}" \\ "{smarray}"
+%   \end{stack}
+%   \[ "[" <position-arg> "]" \]
+%   "{" <preamble> "}" <text>
+%   "\\end"
+%   \( "{tabular}" \\ "{tabular*}" \\ "{array}" \\ "{smarray}" \)
+% \]]
+%
+% <position-arg> ::= (see below)
+%
+% <preamble>	::= \[[
+%   <first-column>
+%   \[ \< <column> \> \]
+% \]]
+%
+% <first-column> ::= \[[ \[ <rule> \] <column> \]]
+%
+% <column>	::= \[[
+%   \[ <spacing> \] \[ \< <user-pre-text> \> \] <column-type>
+%   \[ \< <user-post-text> \> \] \[ <spacing> \] \[ <rule> \]
+% \]]
+%
+% <spacing>	::= \[[ "@" "{" <text> "}" \]]
+%
+% <user-pre-text> ::= \[[ ">" "{" <text> "}" \]]
+%
+% <column-type>	::= \[[
+%   \begin{stack}
+%     \[ "T" \\ "M" \] \( "l" \\ "c" \\ "r" \) \\
+%     \( "p" \\ "m" \\ "b" \) "{" <length> "}" \\
+%     "#" "{" <raw-pre-text> "}" "{" <raw-post-text> "}"
+%   \end{stack}
+% \]]
+%
+% <user-post-text> ::= \[[ "<" "{" <text> "}" \]]
+%
+% <rule>	::= \[[ \( "|" \\ "!" "{" <text> "}" \) \]]
+%
+% \end{grammar}
+%
+% If you examine the above very carefully, you'll notice a slight deviation
+% from the original -- an |@|-expression \emph{following} a rule is
+% considered to be part of the \emph{next} column, not the current one.  This
+% is, I think, an almost insignificant change, and essential for some of the
+% new features.  You'll also notice the new |#| column type form, which
+% allows you to define new real column types instead of just modifying
+% existing ones.  It's not intended for direct use in preambles -- it's
+% there mainly for the benefit of people who know what they're doing and
+% insist on using |\newcolumntype| anyway.
+%%
+% The actual column types are shown in table~\ref{tbl:columns}.
+%
+% \begin{table}
+% \begin{tabular}[C]{| >{\synshorts} c | m{3in} |}	   \hlx{hv[1]}
+%
+% \multicolumn{2}{|c|}{\bf Column types}		\\ \hlx{v[1]hv}
+% \bf Name	& \bf Meaning				\\ \hlx{vhv.}
+% "l"		& Left aligned text (\env{tabular}) or
+%		  equation (\env{array}).		\\ \hlx{.}
+% "c"		& Centred text (\env{tabular}) or
+%		  equation (\env{array}).		\\ \hlx{.}
+% "r"		& Right aligned text (\env{tabular}) or
+%		  equation (\env{array}).		\\ \hlx{vhv.}
+% "Ml", "Mc" and "Mr" & Left, centre and right aligned
+%		  equations.*				\\ \hlx{.}
+% "Tl", "Tc" and "Tr" & Left, centre and right aligned
+%		  text.*				\\ \hlx{vhv.}
+% "p{"<width>"}" & Top aligned paragraph with the given
+%		  width.				\\ \hlx{.}
+% "m{"<width>"}" & Vertically centred paragraph with
+%		  the given width.			\\ \hlx{.}
+% "b{"<width>"}" & Bottom aligned paragraph with the
+%		  given width.				\\ \hlx{vhv.}
+% "#{"<pre>"}{"<post>"}" & User defined column type:
+%		  \<pre> is inserted before the
+%		  cell entry, \<post> is inserted
+%		  afterwards.*				\\ \hlx{vhhv[1]}
+%
+% \multicolumn{2}{|c|}{\bf Other modifier characters}	\\ \hlx{v[1]hv}
+% \bf Name	& \bf Meaning				\\ \hlx{vhv.}
+% "|"		& Inserts a vertical rule between
+%		  columns.				\\ \hlx{.}
+% "$*["<width>"]" & Inserts a vertical rule of given
+%                 width between columns; "*" selects
+%                 "\arraythickrulewidth".               \\ \hlx{.}
+% "!{"<text>"}"	& Inserts \<text> between columns,
+%		  treating it as a vertical rule.	\\ \hlx{vhv.}
+% "@{"<text>"}"	& Inserts \<text> instead of the
+%		  usual intercolumn space.		\\ \hlx{vhv.}
+% ">{"<text>"}"	& Inserts \<text> just before the
+%		  actual column entry.			\\ \hlx{.}
+% "<{"<text>"}"	& Inserts \<text> just after the
+%		  actual column entry.			\\ \hlx{vhv.}
+% "*{"<count>"}{"<chars>"}" & Inserts \<count>
+%		  copies of the \<chars> into the
+%		  preamble.				\\ \hlx{vhs}
+%
+% \multicolumn{2}{@{}l}{* This column type is a new feature}
+% \end{tabular}
+%
+% \caption{\package{array} and \package{tabular} column types and modifiers}
+% \label{tbl:columns}
+% \end{table}
+%
+% Now that's sorted everything out, there shouldn't be any arguments at all
+% about what a column means.
+%
+% The lowercase \<position-arg>s \lit{t}, \lit{c} and \lit{b} do exactly
+% what they did before: control the vertical positioning of the table.  The
+% uppercase ones control the \emph{horizontal} positioning -- this is how you
+% create \emph{unboxed} tables.  You can only create unboxed tables in
+% paragraph mode.
+%
+% Note that unboxed tables still can't be broken across pages.  Use
+% the \package{longtable} package for this, because it already does an
+% excellent job.
+%
+% \DescribeMacro{\tabpause}
+% One thing you can to with unboxed tables, however, is to `interrupt' them,
+% do some normal typesetting, and then continue.  This is achieved by the
+% |\tabpause| command: its argument is written out in paragraph mode, and
+% the table is continued after the argument finishes.
+% Note that it isn't a real argument as far as commands like |\verb| are
+% concerned -- they'll work inside |\tabpause| without any problems.
+%
+% \DescribeMacro{\vline}
+% \DescribeMacro{\vline*}
+% The |\vline| command draws a vertical rule the height of the current table
+% cell (unless the current cell is being typeset in paragraph mode -- it
+% only works in the simple LR-mode table cells, or in \lit{@} or \lit{!}
+% modifiers).  It's now been given an optional argument which gives the
+% width of the rule to draw.  The |*|-version uses the |\arraythickrulewidth|
+% thickness rather than the default.
+%
+% { \let\tabstyle=\relax
+% \begin{demo}{An example of \cmd\vline}
+%\large
+%\begin{tabular}
+%  {| c !{\vline[5pt]} c | c |}
+%  \hlx{hv}
+%  \bf A & \it B & \sf C \\
+%  \hlx[2pt]{vhv}
+%  \bf D & \it E & \sf F \\
+%  \hlx{vh}
+%\end{tabular}
+% \end{demo}
+% }
+%
+% \DescribeMacro{smarray}
+% You've probably noticed that there's an unfamiliar environment mentioned
+% in the syntax shown above.  The \env{smarray} environment produces a
+% `small' array, with script size cells rather than the normal full text
+% size cells.  I've seen examples of this sort of construction\footnote{^^A
+%   There's a nasty use of \env{smallmatrix} in the |testmath.tex| file which
+%   comes with the \package{amslatex} distribution.  It's actually there to
+%   simulate a `smallcases' environment, which the \package{mathenv} package
+%   includes, based around \env{smarray}.}
+% being implemented by totally unsuitable commands.  Someone may find it
+% handy.
+%
+%
+% \subsection{An updated \cs{cline} command}
+%
+% \DescribeMacro{\cline}
+% \DescribeMacro{\hline}
+% The standard \LaTeX\ |\cline| command has been updated.  As well as just
+% passing a range of columns to draw lines through, you can now pass a comma
+% separated list of column numbers and ranges:
+%
+% \begin{grammar}
+% <cline-cmd>	::= \[[
+%   "\\cline"
+%   \[ "*" \\ \tok{"["<width>"]"} \]
+%   "{" \< <number> \[ "-" <number> \] \\ "," \> "}"
+% \]]
+% \end{grammar}
+%
+% The thickness of the rules may be modified.  The default is given by the
+% |\arrayrulewidth| length parameter.  The |\cline*| command uses the
+% |\arraythickrulewidth| parameter instead.  If neither of these does what
+% you want, then you can give a length yourself as an optional argument.
+% This feature is also available in the |\hline| and |\hlx| commands, and
+% (for vertical rules) in the |$| column type.\footnote{I couldn't use the
+% \texttt{\char`\|} type, because that would break old documents which
+% expect \texttt{\char`\| *\char`\{...\char`\}} to work properly.}
+%
+% The positioning of the horizontal lines has also been improved a bit, so
+% that they meet up with the vertical lines properly.  Displays like the one
+% in the example below don't look good unless this has been done properly.
+%
+% {\let\tabstyle\relax
+% \begin{demo}[w]{A \cs{cline} example}
+%\newcommand{\mc}{\multicolumn{1}}
+%\begin{tabular}[C]{|c|c|c|c|}           \cline{2,4}
+%  \mc{c|}{one} & two & three & four   \\ \hline
+%  five & six & seven & \mc{c}{eight}  \\ \cline{1,3}
+%\end{tabular}
+% \end{demo}
+% }
+%
+% \subsection{Spacing control}
+%
+% One of the most irritating things about \LaTeX's tables is that there isn't
+% enough space around horizontal rules.  Donald Knuth, in \textit{The
+% \TeX book}, describes addition of some extra vertical space here as `a mark
+% of quality', and since \TeX\ was designed to produce `beautiful documents'
+% it seems a shame that \LaTeX\ doesn't allow this to be done nicely.  Well,
+% it does now.
+%
+% \DescribeMacro{\vgap}
+% The extra vertical space is added using a command |\vgap|, with the
+% following syntax:
+%
+% \begin{grammar}
+%
+% <vgap-cmd>	::= \[[
+%   "\\vgap" \[ "[" <which-cols> "]" \] "{" <length> "}"
+% \]]
+%
+% <which-cols>	::= \[[ \< <number> \[ "-" <number> \] \\ "," \> \]]
+%
+% \end{grammar}
+%
+% This command must appear either immediately after the beginning of the
+% table or immediately after the |\\| which ends a row.  (Actually, there are
+% other commands which also have this requirement -- you can specify a
+% collection of them wherever you're allowed to give any one.)  It adds some
+% vertical space (the amount is given by the \<length>) to the table,
+% making sure that the vertical rules of the table are extended correctly.
+%
+% The |\vgap| command relies on information stored while your table preamble
+% is being examined.  However, it's possible that you might not want some
+% of the rules drawn (e.g., if you've used |\multicolumn|).  The optional
+% \<which-cols> argument allows you to specify which rules are \emph{not}
+% to be drawn.  You can specify either single column numbers or ranges.  The
+% rule at the very left hand side is given the number~0; the rules at the
+% end of column~$n$ are numbered~$n$.  It's easy really.
+%
+% \DescribeMacro{\hlx}
+% Using |\vgap| is all very well, but it's a bit cumbersome, and takes up a
+% lot of typing, especially when combined with |\hline| commands.  The |\hlx|
+% command tries to tidy things.
+%
+% The syntax is simple:
+% \begin{grammar}
+%
+% <hlx-cmd>	::= \[[
+%   "\\hlx"
+%   \[ "*" \\ \tok{"["<width>"]"} \]
+%   "{"
+%   \begin{rep}
+%     \begin{stack}
+%       "h" \\
+%       \tok{"v["<which-cols>"]["<length>"]"} \\
+%       \tok{"s["<length>"]"} \\
+%       \tok{"c{"<which-cols>"}"} \\
+%       "b" \\
+%       \tok{"/["<number>"]"} \\
+%       "."
+%     \end{stack}
+%   \end{rep}
+%   "}"
+% \]]
+%
+% \end{grammar}
+% The |*| or optional \<width> specify the width of horizontal rules to be
+% drawn, as for |\hline| and |\cline|.  (Note that you can't pass a |*| or
+% optional argument to the |h| or |c| subcommands.)
+%
+% The argument works a bit like a table preamble, really.  Each letter is a
+% command.  The following are supported:
+%
+% \begin{description}
+%
+% \item [\lit*{h}] Works just like |\hline|.  If you put two adjacent to each
+%       other, a gap will be put between them.
+%
+% \item [\lit*{v[}\<which-cols>\lit*{][}\<length>\lit*{]}]  Works
+%       like \syntax{"\\vgap["<which-cols>"]{"<length>"}"}.  If the
+%       \<length> is omitted, the value of |\doublerulesep| is used.
+%       This usually looks right.
+%
+% \item [\lit*{s[}\<length>\lit*{]}]  Leaves a vertical gap with the
+%       given size.  If you omit the \<length> then |\doublerulesep| is
+%       used.  This is usually right.
+%
+% \item [\lit*{c\char`\{}\<which-cols>\lit*{\char`\}}]  Works just like
+%       |\cline|.
+%
+% \item [\lit*{b}] Inserts a backspace the width of a rule.  This is useful
+%       when doing \package{longtable}s.
+%
+% \item [\lit*{/[}\<number>\lit*{]}]  Allows a page break in a table.  Don't
+%       use this except in a \env{longtable} environment.  The \<number>
+%       works exactly the same as it does in the |\pagebreak| command,
+%       except that the default is 0, which just permits a break without
+%       forcing it.
+%
+% \item [\lit*{.}]  (That's a dot)  Starts the next row of the table.  No
+%       more characters may follow the dot, and no |\hline|, |\hlx|, |\vgap|
+%       or |\multicolumn| commands may be used after it.  You don't have to
+%       include it, and most of the time it's totally useless.  It can be
+%       handy for some macros, though.  I used it in (and in fact added it
+%       especially for) the table of column types.
+%
+% \end{description}
+%
+% An example of the use of |\hlx| is given, so you can see what's going on.
+%
+% \begin{figure}
+% \let\tabstyle\relax
+% \begin{demo}[w]{Beautiful table example}
+%\newcommand{\zerowidth}[1]{\hbox to 0pt{\hss#1\hss}}
+%\setlength{\tabcolsep}{1.5em}
+%\begin{tabular}[C]{| r | c | r |}                  \hlx{hv[1,2]}
+%  \multicolumn{3}{|c|}{\bf AT\&T Common Stock}  \\ \hlx{v[1,2]hv}
+%  \multicolumn{1}{|c|}{\zerowidth{\bf Year}} &
+%  \multicolumn{1}{c|}{\zerowidth{\bf Price}} &
+%  \multicolumn{1}{c|}{\zerowidth{\bf Dividend}} \\ \hlx{vhv}
+%  1971 & 41--54 & \$2.60                        \\
+%     2 & 41--54 &   2.70                        \\
+%     3 & 46--55 &   2.87                        \\
+%     4 & 40--53 &   3.24                        \\
+%     5 & 45--52 &   3.40                        \\
+%     6 & 51--59 &    .95\rlap{*}                \\ \hlx{vhs}
+%  \multicolumn{3}{@{}l}{* (first quarter only)}
+%\end{tabular}
+% \end{demo}
+% \end{figure}
+%
+%
+% \subsection{Creating beautiful long tables}
+%
+% You can use the |\vgap| and |\hlx| commands with David Carlisle's
+% stunning \package{longtable} package.  However, there are some things you
+% should be away of to ensure that your tables always come out looking
+% lovely.
+%
+% The \package{longtable} package will break a table at an |\hline| command,
+% leaving a rule at the bottom of the page and another at the top of the
+% next page.  This means that a constructions like |\hlx{vhv}| will be
+% broken into something like |\hlx{vh}| at the bottom of the page and
+% |\hlx{hv}| at the top of the next.  You need to design the table headers
+% and footers with this in mind.
+%
+% However, there appears to be a slight problem:\footnote
+%   {You might very well call it a bug.  I couldn't possibly comment.}
+% if the footer starts with an |\hline|, and a page is broken at an |\hline|,
+% then you get an extra thick rule at the bottom of the page.  This is a bit
+% of a problem, because if the rule isn't there in the footer and you get
+% a break between two rows \emph{without} a rule between them, then the page
+% looks very odd.  
+%
+% If you want to do ruled longtables, I'd recommend that you proceed as
+% follows:
+% \begin{itemize}
+% \item End header sections with an |\hlx{vh}|.
+% \item Begin footer sections with an |\hlx{bh}|.
+% \item Begin the main table with |\hlx{v}|.
+% \item Insert |\hlx{vhv}| commands in the main table body as usual.
+% \end{itemize}
+% If \package{longtable} gets modified appropriately, the use of the \lit{b}
+% command won't be necessary.
+%
+% Here's an example of the sort of thing you'd type.
+%
+% \begin{listinglist} \listingsize
+% \verb"\begin{longtable}[c]{|c|l|}           \hlx{hv}" \\
+% \verb"\bf Heading & \bf Also heading     \\ \hlx{vh}" \\
+% \verb"\endhead" \\
+% \verb"\hlx{bh}" \\
+% \verb"\endfoot" \\
+% \verb"\hlx{v}" \\
+% \verb"First main & table line            \\ \hlx{vhv}" \\
+% \verb"Lots of text & like this           \\ \hlx{vhv}" \\
+% \null\quad\vdots \\
+% \verb"Lots of text & like this           \\ \hlx{vhv}" \\
+% \verb"Last main & table line             \\ \hlx{vh}" \\
+% \verb"\end{longtable}"
+% \end{listinglist}
+%
+%
+% \subsection{Rules and vertical positioning}
+%
+% In the \LaTeXe\ and \package{array.sty} versions of \env{tabular}, you run
+% into problems if you try to use ruled tables together with the \lit{[t]} or
+% \lit{[b]} position specifiers -- the top or bottom rule ends up being
+% nicely lined up with the text baseline, giving you an effect which is
+% nothing like the one you expected.  The \textit{\LaTeX\ Companion} gives
+% two commands |\firsthline| and |\lasthline| which are supposed to help with
+% this problem.  (These commands have since migrated into the \package{array}
+% package.)  Unfortunately, |\firsthline| doesn't do its job properly --
+% it gets the text position wrong by exactly the width of the table rules.
+%
+% The \package{mdwtab} package makes all of this automatic.  It gets the
+% baseline positions exactly right, whether or not you use rules.  Earlier
+% versions of this package required that you play with a length parameter
+% called |\rulefudge|; this is no longer necessary (or even possible -- the
+% length parameter no longer exists).  The package now correctly compensates
+% for all sorts of rules and |\vgap|s at the top and bottom of a table and
+% it gets the positioning right all by itself.  You've never had it so good.
+%
+%
+% \subsection{User serviceable parts}
+%
+% There are a lot of parameters which you can modify in order to make arrays
+% and tables look nicer.  They are all listed in table~\ref{tbl:config}.
+%
+% \begin{table}
+% \begin{tabular}[C]{| l | m{3in} |}				   \hlx{hv}
+% \bf Parameter		& \bf Meaning				\\ \hlx{vhv}
+% |\tabstyle|		& A command executed at the beginning of
+%			  a \env{tabular} or \env{tabular$*$}
+%			  environment.  By default does nothing.
+%			  Change using |\renewcommand|.		\\ \hlx{vhv}
+% |\extrarowheight|	& A length added to the height of every
+%			  row, used to stop table rules
+%			  overprinting ascenders.  Default 0\,pt.
+%			  Usage is deprecated now: use |\hlx|
+%			  instead.				\\ \hlx{vhv}
+% |\tabextrasep|	& Extra space added between rows in a
+%			  \env{tabular} or \env{tabular$*$}
+%			  environment (added \emph{before} any
+%			  following |\hline|).  Default 0\,pt.	\\
+% |\arrayextrasep|	& Analogous to |\tabextrasep|, but for
+%			  \env{array} environments.  Default
+%			  1\,jot (3\,pt).			\\
+% |\smarrayextrasep|	& Analogous to |\tabextrasep|, but for
+%			  \env{smarray} environments.  Default
+%			  1\,pt.				\\ \hlx{vhv}
+% |\tabcolsep|		& Space added by default on each side of
+%			  a table cell (unless suppressed by an
+%			  \lit{@}-expression) in \env{tabular}
+%			  environments.  Default is defined by
+%			  your document class.			\\
+% |\arraycolsep|	& Analogous to |\tabcolsep|, but for
+%			  \env{array} environments.  Default is
+%			  defined by your document class.	\\
+% |\smarraycolsep|	& Analogous to |\tabcolsep|, but for
+%			  \env{smarray} environments.  Default
+%			  is 3\,pt.				\\ \hlx{vhv}
+% |\arrayrulewidth|	& The width of horizontal and vertical
+%			  rules in tables.			\\
+% |\arraythickrulewidth|& The width of starred rules in tables.	\\
+% |\doublerulesep|	& Space added between two adjacent
+%			  vertical or horizontal rules.  Also
+%			  used by |\hlx{v}|.			\\ \hlx{vhv}
+% |\arraystretch|	& Command containing a factor to
+%			  multiply the default row height.
+%			  Default is defined by your document
+%			  class (usually 1).			\\ \hlx{vh}
+% \end{tabular}
+%
+% \caption{Parameters for configuring table environments}
+% \label{tbl:config}
+%
+% \end{table}
+%
+%
+% \subsection{Defining column types}
+%
+% \DescribeMacro{\newcolumntype}
+% The easy way to define new column types is using |\newcolumntype|.  It
+% works in more or less the same way as |\newcommand|:
+%
+% \begin{grammar}
+%
+% <new-col-type-cmd> ::= \[[
+%   "\\newcolumntype"
+%   "{" <column-name> "}"
+%   \[ "[" <num-args> "]" \]
+%   \[ "[" <default-arg> "]" \]
+%   "{" <first-column> \[ \< <column> \> \] "}"
+% \]]
+%
+% \end{grammar}
+%
+% (The \env{array.sty} implementation doesn't accept the \<default-arg>
+% argument.  I've no idea why not, 'cos it was very easy to implement.)
+%
+% \DescribeMacro{\colset}
+% This implementation allows you to define lots of different sets of columns.
+% You can change the current set using the |\colset| declaration:
+% \begin{grammar}
+% <colset-cmd>	::= \[[ "\\colset" "{" <set-name> "}" \]]
+% \end{grammar}
+% This leaves a problem, though: at any particular moment, the current
+% column set could be anything, since other macros and packages can change
+% it.
+%
+% \DescribeMacro{\colpush}
+% \DescribeMacro{\colpop}
+% What actually happens is that a stack of column sets is maintained.  The
+% |\colset| command just replaces the item at the top of the stack.  The
+% command |\colpush| pushes its argument onto the top of the stack, making
+% it the new current set.  The corresponding |\colpop| macro (which doesn't
+% take any arguments) removes the top item from the stack, reinstating the
+% previous current column set.
+%
+% \begin{grammar}
+% <colpush-cmd>	::= \[[ "\\colpush" "{" <set-name> "}" \]]
+% <colpop-cmd>	::= \[[ "\\colpop" \]]
+% \end{grammar}
+%
+% The macros which manipulate the column set stack work \emph{locally}.
+% The contents of the stack are saved when you open a new group.
+%
+% To make sure everyone behaves themselves properly, these are the rules for
+% using the column set stack:
+%
+% \begin{itemize}
+%
+% \item Packages defining column types must ensure that they preserve the
+%       current column set.  Either they must push their own column type
+%       and pop it off when they're finished defining columns, or they must
+%       avoid changing the stack at all, and use the optional arguments to
+%       |\coldef| and |\collet|.
+%
+% \item Packages must not assume that any particular column set is current
+%       unless they have made sure of it themselves.
+%
+% \item Packages must ensure that they pop exactly as much as they push.
+%       There isn't much policing of this (perhaps there should be more),
+%       so authors are encouraged to behave responsibly.
+%
+% \item Packages must change the current column set (using |\colset|) when
+%       they start up their table environment.  This will be restored when
+%       the environment closes.
+%
+% \end{itemize}
+%
+% \DescribeMacro{\coldef}
+% |\newcolumntype| is probably enough for most purposes.  However, Real
+% \TeX nicians, and people writing new table-generating environments, require
+% something lower-level.
+%
+% \begin{grammar}
+% <coldef-cmd>	::= \[[
+%   "\\coldef"
+%     \[ "[" <set-name> "]" \]
+%     <col-name> <arg-template> "{" <replacement-text> "}"
+% \]]
+% \end{grammar}
+%
+% Note that this defines a column type in the current colset.  It works
+% almost exactly the same way as \TeX's primitive |\def|.  There is a
+% potential gotcha here: a |\tab@mkpream| token is inserted at the end of
+% your replacement text.  If you need to read an optional argument or
+% something, you'll need to gobble this token before you carry on.  The
+% |\@firstoftwo| macro could be handy here:
+% \begin{listing}
+%\coldef x{\@firstoftwo{\@ifnextchar[\@xcolumn@i\@xcolumn@ii}}}
+% \end{listing}
+% This isn't a terribly pretty state of affairs, and I ought to do something
+% about it.  I've not seen any use for an optional argument yet, though.
+% Note that if you do gobble the |\tab@mkpream|, it's your responsibility to
+% insert another one at the very end of your macro's expansion (so that
+% further preamble characters can be read).
+% 
+% The replacement text is inserted directly.  It's normal to insert preamble
+% elements here.  There are several to choose from:
+%
+% \begin{description}
+%
+% \item [Column items] provide the main `meat' of a column.  You insert a
+%       column element by saying
+%       \syntax{"\\tabcoltype{"<pre-text>"}{"<post-text>"}"}.
+%       The user's text gets inserted between these two.  (So do user pre-
+%       and post-texts.  Bear this in mind.)
+%
+% \item [User pre-text items] work like the \lit{>} preamble command.  You
+%       use the \syntax{"\\tabuserpretype{"<text>"}"} command to insert it.
+%       User pre-texts are written in \emph{reverse} order between the
+%       pre-text of the column item and the text from the table cell.
+%
+% \item [User post-text items] work like the \lit{<} preamble command.  You
+%       use the \syntax{"\\tabuserposttype{"<text>"}"} command to insert it.
+%       Like user pre-texts, user post-texts are written in reverse order,
+%       between the table cell text and the column item post-text.
+%
+% \item [Space items] work like the \lit{@} preamble command.  They're
+%       inserted with the \syntax{"\\tabspctype{"<text>"}"} command.
+%
+% \item [Rule items] work like the `\verb"|"' and \lit{!} commands.  You
+%       insert them with the \syntax{"\\tabruletype{"<text>"}"} command.
+%       Note that the text is inserted by |\vgap| too, so it should contain
+%       things which adjust their vertical size nicely.  If you really need
+%       to, you can test |\iftab@vgap| to see if you're in a |\vgap|.
+%
+% \end{description}
+%
+% \DescribeMacro{\collet}
+% As well as defining columns, you can copy definitions (rather like |\let|
+% allows you to copy macros).  The syntax is like this:
+%
+% \begin{grammar}
+%
+% <collet-cmd>	::= \[[
+%   \[ "[" <set-name> "]" \] <col-name> \[ "=" \] \[ "[" <set-name> "]" \]
+%   <col-name>
+% \]]
+%
+% \end{grammar}
+%
+% (In other words, you can copy definitions from other column sets.)
+%
+%
+% \subsection{Defining new table-generating environments}
+%
+% Quite a few routines are provided specifically to help you to define new
+% environments which do alignment in a nice way.
+%
+% \subsubsection{Reading preambles}
+%
+% The main tricky bit in doing table-like environments is parsing preambles.
+% No longer.
+%
+% \DescribeMacro{\tab@readpreamble}
+% \DescribeMacro{\tab@doreadpream}
+% The main parser routine is called |\tab@doreadpream|.  Given a user
+% preamble string as an argument, it will build an |\halign| preamble to
+% return to you.  However, the preamble produced won't be complete.  This is
+% because you can actually make multiple calls to |\tab@doreadpream| with
+% bits of user preambles.  The |\newcolumntype| system uses this mechanism,
+% as does the \lit{*} (repeating) modifier.  When there really is no more
+% preamble to read, you need to \emph{commit} the heldover tokens to the
+% output.  The |\tab@readpreamble| routine will do this for you -- given a
+% user preamble, it builds a complete output from it.
+%
+% A token register |\tab@preamble| is used to store the generated preamble.
+% Before starting, you must initialise this token list to whatever you want.
+% There's another token register, |\tab@shortline|, which is used to store
+% tokens used by |\vgap|.  For each column in the table, the list contains
+% an |\omit| (to override the standard preamble) and an |\hfil| space taking
+% up most of the column.  Finally, for each rule item in the user preamble,
+% the shortline list contains an entry of the form:
+% \begin{quote} \synshorts
+%   "\\tab@ckr{"<column-number>"}{"<rule-text>"}"
+% \end{quote}
+% This is used to decide whether to print the rule or an empty thing of the
+% same width.  You probably ought to know that the very first column does
+% \emph{not} have a leading |\omit| -- this is supplied by |\vgap| so that
+% it can then look for optional arguments.
+%
+% \DescribeMacro{\tab@initread}
+% As well as initialising |\tab@preamble| and emptying |\tab@shortline|,
+% there are several other operations required to initialise a preamble read.
+% These are all performed by the |\tab@initread| macro, although you may want
+% to change some of the values for your specific application.  For reference,
+% the actions performed are:
+% \begin{itemize}
+% \item initialising the parser state by setting $|\tab@state| =
+%       |\tab@startstate|$;
+% \item clearing the token lists |\tab@preamble| and |\tab@shortlist|;
+% \item initialising the macros |\tab@tabtext|, |\tab@midtext|, and
+%       |\tab@multicol| to their default values of `|&|',
+%       `|\ignorespaces#\unskip|' and the empty token list respectively.^^A
+%       \footnote{^^A
+%         These are macros rather than token lists to avoid hogging all
+%         the token list registers.  Actually, the package only allocates
+%         two, although it does use almost all of the temporary registers as
+%         well.  Also, there's a lie: \cs{unskip} is too hamfisted to remove
+%         trailing spaces properly;  I really use a macro called
+%         \cs{@maybe@unskip}}
+% \item clearing the internal token list registers |\tab@pretext|,
+%       |tab@userpretext| and |\tab@posttext|;
+% \item clearing the column counter |\tab@columns| to zero;
+% \item clearing the action performed when a new column is started (by making
+%       the |\tab@looped| macro equal to |\relax|; this is used to make
+%       |\multicolumn| macro raise an error if you try to do more than one
+%       column); and
+% \item setting up some other switches used by the parser (|\iftab@rule|,
+%       |\iftab@initrule| and |\iftab@firstcol|, all of which are set to be
+%       |true|).
+% \end{itemize}
+%
+% The macro |\tab@multicol| is used by the |\multicolumn| command to insert
+% any necessary items (e.g., struts) before the actual column text.  If you
+% set this to something non-empty, you should probably consider adding a
+% call to the macro to the beginning of |\tab@preamble|.
+%
+% When parsing is finally done, the count register |\tab@columns| contains
+% the number of columns in the alignment.  Don't corrupt this value, because
+% it's used for handling |\hline| commands.
+%
+% \subsubsection{Starting new lines}
+%
+% The other messy bit required by table environments is the newline command
+% |\\|.  There are nasty complications involved with starting new lines, some
+% of which can be handled by this package, and some on which I can only give
+% advice.
+%
+% \DescribeMacro{\tab@cr}
+% The optional arguments and star-forms etc. can be read fairly painlessly
+% using the |\tab@cr| command:
+%
+% \begin{grammar}
+% <tabcr-cmd>	::= \[[
+%   "\\tab@cr" <command> "{" <non-star-text> "}" "{" <star-text> "}"
+% \]]
+% \end{grammar}
+%
+% This will call your \<command> with two arguments.  The first is the
+% contents of the optional argument, or `|\z@|' if there wasn't one.  The
+% second is either \<star-text> or \<non-star-text> depending on
+% whether the user wrote the $*$-form or not.
+%
+% Somewhere in your \<command>, you'll have to use the |\cr| primitive to
+% end the table row.  After you've done this, you \emph{must} ensure that you
+% don't do anything that gets past \TeX's mouth without protecting it --
+% otherwise |\hline| and co.\ won't work.  I usually wrap things up in a
+% |\noalign| to protect them, although there are other methods.  Maybe.
+%
+% You might like to have a look at the \env{eqnarray} implementation provided
+% to see how all this gets put into practice.
+%
+%
+% \subsection{The \env{mathenv} package alignment environments}
+%
+% The \env{mathenv} package provides several environments for aligning
+% equations in various ways.  They're mainly provided as a demonstration of
+% the table handling macros in \package{mdwtab}, so don't expect great
+% things.  If you want truly beautiful mathematics, use
+% \package{amsmath}.\footnote{^^A
+%   Particularly since nice commands like \cmd\over\ are being reactivated
+%   in a later release of \package{amsmath}.}
+% However, the various environments do nest in an approximately useful way.
+% I also think that the \env{matrix} and \env{script} environments provided
+% here give better results than their \package{amsmath} equivalents, and
+% they are certainly more versatile.
+%
+% \subsubsection{The new \env{eqnarray} environment}
+%
+% \DescribeEnv{eqnarray}
+% \DescribeEnv{eqnarray*}
+% As an example of the new column defining features, and because the original
+% isn't terribly good, I've included a rewritten version of the
+% \env{eqnarray} environment.  The new implementation closes the gap between
+% \env{eqnarray} and \AmSTeX\ alignment features.  It's in a separate,
+% package called \package{mathenv}, to avoid wasting your memory.
+%
+% \begin{grammar}
+%
+% <eqnarray-env> ::= \[[
+%   <begin-eqnarray> \< <row> \\ "\\\\" \> <end-eqnarray>
+% \]]
+%
+% <begin-eqnarray> ::= \[[
+%   "\\begin" \( "{eqnarray}" \\ "{eqnarray*}" \)
+%   \[ "[" \< <eqa-column> \> "]" \]
+% \]]
+%
+% <eqa-column>	::= \[[
+%   \[ "q" \\ ":" \]
+%   \[ \< ">" "{" <pre-text> "}" \> \]
+%   \begin{stack}
+%     \[ "T" \] \( "r" \\ "c" \\ "l" \) \\
+%     "L" \\
+%     "x"
+%   \end{stack}
+%   \[ \< "<" "{" <post-text> "}" \> \]
+% \]]
+%
+% <end-eqnarray> ::= \[[
+%   "\\end" \begin{stack} "{eqnarray}" \\ "{eqnarray*}" \end{stack}
+% \]]
+%
+% \end{grammar}
+%
+% Descriptions of the various column types are given in
+% table~\ref{tbl:eqnarray}.
+%
+% \begin{table}
+% \begin{tabular}[C]{| >{\synshorts} c | m{3in} |}	   \hlx{hv[1]}
+%
+% \multicolumn{2}{|c|}{\bf Column types}		\\ \hlx{v[1]hv}
+% \bf Name	& \bf Meaning				\\ \hlx{vhv.}
+% "l"		& Left aligned piece of equation.	\\ \hlx{.}
+% "c"		& Centred piece of equation.		\\ \hlx{.}
+% "x"		& Centred or flush-left whole equation
+%		  (depending on \textsf{fleqn} option).	\\ \hlx{.}
+% "r"		& Right aligned piece of equation.	\\ \hlx{vhv.}
+% "L"		& Left aligned piece of equation whose
+%		  width is considered to be 2\,em.	\\ \hlx{vhv.}
+% "Tl", "Tc" and "Tr" & Left, centre and right aligned
+%		  text.					\\ \hlx{vhhv[1]}
+%
+% \multicolumn{2}{|c|}{\bf Other modifier characters}	\\ \hlx{v[1]hv}
+% \bf Name	& \bf Meaning				\\ \hlx{vhv.}
+% ":"		& Leaves a big gap between equations.
+%		  By default, the `chunks' separated by
+%		  \lit{:}s are equally spaced on the
+%		  line.					\\ \hlx{.}
+% "q"		& Inserts 1\,em of space		\\ \hlx{vhv.}
+% ">{"<text>"}"	& Inserts \<text> just before the
+%		  actual column entry.			\\ \hlx{.}
+% "<{"<text>"}"	& Inserts \<text> just after the
+%		  actual column entry.			\\ \hlx{vhv.}
+% "*{"<count>"}{"<chars>"}" & Inserts \<count>
+%		  copies of the \<chars> into the
+%		  preamble.				\\ \hlx{vh}
+% \end{tabular}
+%
+% \caption{\package{eqnarray} column types and modifiers}
+% \label{tbl:eqnarray}
+% \end{table}
+%
+% The default preamble, if you don't supply one of your own, is \lit{rcl}.
+% Most of the time, \lit{rl} is sufficient, although compatibility is more
+% important to me.
+%
+% By default, there is no space between columns, which makes formul\ae\ in an
+% \env{eqnarray} environment look just like formul\ae\ typeset on their own,
+% except that things get aligned in columns.  This is where the default
+% \env{eqnarray} falls down: it leaves |\arraycolsep| space between each
+% column making the thing look horrible.
+%
+% An example would be good here, I think.  This one's from exercise 22.9 of
+% the \textit{\TeX book}.
+%
+% \begin{demo}[w]{Simultaneous equations}
+%\begin{eqnarray}[*3{rc}rl]
+%  10w & + &  3x & + & 3y & + & 18z & = 1 \\
+%   6w & - & 17x &   &    & - &  5z & = 2
+%\end{eqnarray}
+% \end{demo}
+%
+% Choosing a more up-to-date example, here's some examples from  the
+% \textit{\LaTeX\ Companion}.
+%
+% \begin{demo}[w]{Lots of equations}
+%\begin{eqnarray}[rl:rl:lq]
+% V_i &= v_i - q_i v_j,	& X_i &= x_i - q_i x_j,	&
+%       U_i = u_i, \qquad \mbox{for $i \ne j$}  \\
+% V_j &= v_j,           & X_j &= x_j            &
+%       U_j u_j + \sum_{i \ne j} q_i u_i. \label{eq:A}
+%\end{eqnarray}
+% \end{demo}
+%
+% \begin{figure}
+% \begin{demo}[w]{Plain text column and \cs{tabpause}}
+%\begin{eqnarray}[rlqqTl]
+%     x  &= y           & by (\ref{eq:A}) \\
+%     x' &= y'          & by definition \\
+%\tabpause{and}
+% x + x' &= y + y'      & by Axiom~1
+%\end{eqnarray}
+% \end{demo}
+% \end{figure}
+%
+% The new features also mean that you don't need to mess about with
+% |\lefteqn| any more.  This is handled by the \lit{L} column type:
+%
+% \begin{demo}{Splitting example}
+%\begin{eqnarray*}[Ll]
+%   w+x+y+z = \\
+%    & a+b+c+d+e+ \\
+%    & f+g+h+i+j
+%\end{eqnarray*}
+% \end{demo}
+%
+% Finally, just to prove that the spacing's right at last, here's another one
+% from the \textit{Companion}.
+%
+% \begin{demo}{Spacing demonstration}
+%\begin{equation}
+%  x^2 + y^2 = z^2
+%\end{equation}
+%\begin{eqnarray}[rl]
+%  x^2 + y^2 &= z^2 \\
+%        y^2 &< z^2
+%\end{eqnarray}
+% \end{demo}
+%
+% Well, that was easy enough.  Now on to numbering.  As you've noticed, the
+% equations above are numbered.  You can use the \env{eqnarray$*$}
+% environment to turn off the numbering in the whole environment, or say
+% |\nonumber| on a line to suppress numbering of that one in particular.
+%
+% \DescribeMacro{\eqnumber}
+% More excitingly, you can say |\eqnumber| to enable numbering for a
+% particular equation, or \syntax{"\\eqnumber["<text>"]"} to choose what to
+% show instead of the line number.  This works for both starred and unstarred
+% versions of the environment.  Now |\nonumber| becomes merely a synonym for
+% `|\eqnumber[]|'.
+%
+% A note for cheats: you can use the sparkly new \env{eqnarray} for simple
+% equations by specifying \lit{x} as the column description.  Who needs
+% \AmSTeX?\ |;-)|
+%
+% \DescribeEnv{eqlines}
+% \DescribeEnv{eqlines*}
+% In fact, there's a separate environment \env{eqlines}, which is equivalent
+% to \env{eqnarray} with a single \lit{x} column; the result is that you can
+% insert a collection of displayed equations separated by |\\| commands.  If
+% you don't like numbering, use \env{eqlines$*$} instead.
+%
+% \subsubsection{The \env{eqnalign} environment}
+%
+% \DescribeEnv{eqnalign}
+% There's a new environment, \env{eqnalign}, which does almost the same
+% thing as \env{eqnarray} but not quite.  It doesn't do equation numbers,
+% and it wraps its contents up in a box.  The result of this is that:
+%
+% \begin{itemize}
+%
+% \item You can use \env{eqnalign} for just a part of a formula.
+%       The \env{eqnarray} environment must take up the whole display.
+%
+% \item You can use \env{eqnalign} within \env{eqnarray} for extra fine
+%       alignment of subsidiary bits.
+%
+% \item You can break off from doing an \env{eqnarray} using the |\tabpause|
+%       command.  You can't use |\tabpause| inside
+%       \env{eqnalign}.\footnote{^^A
+%         Well, technically speaking there's nothing to stop you.  However,
+%         the results won't be pretty.}
+%
+% \end{itemize}
+%
+% The \env{eqnalign} environment works like this:
+%
+% \begin{grammar}
+%
+% <eqnalign-env> ::= \[[
+%   <begin-eqnalign> <contents> <end-eqnalign>
+% \]]
+%
+% <begin-eqnalign> ::= \[[
+%   "\\begin" "{eqnalign}"
+%   \[ "[" \< <eqa-column> \> "]" \]
+%   \[ "[" \( "t" \\ "c" \\ "b" \) "]" \]
+% \]]
+%
+% <end-eqnalign> ::= \[[ "\\end" "{eqnalign}" \]]
+%
+% \end{grammar}
+%
+% As the syntax suggests, the preamble for the \env{eqnalign} environment
+% works exactly the same way as for \env{eqnarray}.  Example time: another
+% one from the \textit{\TeX book}.
+%
+% \begin{figure}
+% \begin{demo}[w]{Example of \env{eqnalign}}
+%\[
+%  \left\{ \begin{eqnalign}[rl]
+%    \alpha &= f(z) \\ \beta  &= f(z^2) \\
+%    \gamma &= f(z^3)
+%  \end{eqnalign} \right\}
+%  \qquad
+%  \left\{ \begin{eqnalign}[rl]
+%    x &= \alpha^2 - \beta \\ y &= 2\gamma
+%  \end{eqnalign} \right\}.
+%\]
+% \end{demo}
+% \end{figure}
+%
+% \DescribeMacro{\multicolumn}
+% The |\multicolumn| command works correctly in both the \env{eqnarray} and
+% \env{eqnalign} environments, although you should bear in mind that you
+% should give \env{eqnarray} column types, not \env{array} ones.
+%
+% \subsubsection{A note on spacing in alignment environments}
+%
+% Most of the time, equations in \env{eqnarray} and \env{eqnalign}
+% environments will be beautiful.  However, there are some things you should
+% bear in mind when you produce beautiful equations.
+%
+% The main problem with spacing is making sure that binary relations and
+% binary operators have the correct amount of space on each side of them.
+% The alignment environments insert `hidden' objects at the ends of table
+% cells to assist with the spacing: \lit{l} column types have a hidden object
+% on the left, \lit{r} types have a hidden object on the right, and \lit{c}
+% types have a hidden object on \emph{both} ends.  These hidden objects add
+% the correct space when there's a binary operator or relation next to them.
+% If some other sort of object is lurking there, no space is added.  So far,
+% so good.
+%
+% The only problem comes when you have something like this:
+%
+% \begin{demo}{How not to do an \env{eqnarray}}
+%\begin{eqnarray*}[rcl]
+%  x +  y & = & 12 \\
+% 2x - 5y & = & -6
+%\end{eqnarray*}
+% \end{demo}
+%
+% The `$-$' sign in the second equation has been treated as a binary operator
+% when really it should be a unary prefix operator, but \TeX\ isn't clever
+% enough to know the difference.  (Can you see the difference in the spacing
+% between $-6$~and~${}-6$?)  There are two possible solutions to the
+% problem.  You could wrap the `|-6|' up in a group (`|{-6}|'), or just the
+% $-$ sign (`|{-}6|').  A better plan, though, is to get rid of the middle
+% column altogether:
+%
+% \begin{demo}{How to do an \env{eqnarray}}
+%\begin{eqnarray*}[rl]
+%  x +  y & = 12 \\
+% 2x - 5y & = -6
+%\end{eqnarray*}
+% \end{demo}
+%
+% Since the things in the middle column were the same width, it's not
+% actually doing any good.  Also, now that \TeX\ can see that the thing on
+% the left of the `$-$' sign is a relation (the `$=$' sign), it will space
+% the formula correctly.
+%
+% In this case, it might be even better to add some extra columns, and line
+% up the $x$ and $y$ terms in the left hand side:
+%
+% \begin{demo}{Extra beautiful \env{eqnarray}}
+%\begin{eqnarray*}[rrl]
+%  x + &  y & = 12 \\
+% 2x - & 5y & = -6
+%\end{eqnarray*}
+% \end{demo}
+%
+% ^^A Some hacking now to display box sizes.
+%
+% {
+% \catcode`p=12 \catcode`t=12
+% \gdef\magni#1pt{#1}
+% }
+%
+% \newcommand{\widthof}[1]{^^A
+%   \settowidth{\dimen0 }{#1}^^A
+%   \expandafter\magni\the\dimen0\,pt^^A
+% }
+%
+% ^^A The text below makes an assumption which looks correct to me (I asked
+% ^^A TeX, and it agreed with me), although in case anything changes, I want
+% ^^A to be informed.
+%
+% \sbox0{$+$} \sbox2{$-$} \ifdim\wd0=\wd2\else%
+%   \errmessage{Assertion failed: `+' and `-' are different widths!}
+% \fi
+%
+% There's no need to put the `$+$' and `$-$' operators in their own column
+% here, because they're both \widthof{$+$} wide, even though they don't
+% look it.
+%
+% \subsubsection{Configuring the alignment environments}
+%
+% There are a collection of parameters you can use to make the equation
+% alignment environments (\env{eqnarray} and \env{eqnalign}) look the way
+% you like them.  These are all shown in table~\ref{tbl:eqnparms}.
+%
+% \begin{table}
+% \begin{tabular}[C]{| l | p{3in} |}				   \hlx{hv}
+% \bf Parameter		& \bf Use				\\ \hlx{vhv}
+% |\eqaopenskip|	& Length put on the left of an
+%			  \env{eqnarray} environment.  By
+%			  default, this is |\@centering| (to
+%			  centre the alignment) or |\mathindent|
+%			  (to left align) depending on whether
+%			  you're using the \textsf{fleqn}
+%			  document class option.		\\
+% |\eqacloseskip|	& Length put on the right of an
+%			  \env{eqnarray} environment.  By
+%			  default, this is |\@centering|, to
+%			  align the environment correctly.	\\ \hlx{vhv}
+% |\eqacolskip|		& Space added by the \lit{:} column
+%			  modifier.  This should be a rubber
+%			  length, although it only stretches in
+%			  \env{eqnarray}, not in \env{eqnalign}.
+%			  The default value is 1\smallf1/2\,em
+%			  with 1000\,pt of stretch.		\\
+% |\eqainskip|		& Space added at each side of a normal
+%			  column.  By default this is 0\,pt.	\\ \hlx{vhv}
+% |\eqastyle|		& The maths style used in the alignment.
+%			  By default, this is |\textstyle|,
+%			  and you probably won't want to change
+%			  it.					\\ \hlx{vh}
+% \end{tabular}
+%
+% \caption{Parameters for the \env{eqnarray} and \env{eqnalign} environments}
+% \label{tbl:eqnparms}
+% \end{table}
+%
+%
+% \subsection{Other multiline equations}
+%
+% Sometimes there's no sensible alignment point for splitting equations.  The
+% normal thing to do under these circumstances is to put the first line way
+% over to the left of the page, and the last line over to the right.  (If
+% there are more lines, I imagine we put them in the middle.)
+%
+% \DescribeEnv{spliteqn}
+% \DescribeEnv{spliteqn*}
+% The \env{spliteqn} environment allows you to do such splitting of
+% equations.  Rather than tediously describe it, I'll just give an example,
+% because it's really easy.  The $*$-version works the same, except it
+% doesn't put an equation number in.
+%
+% \begin{figure}
+% \begin{demo}[w]{A split equation}
+%\begin{spliteqn}
+%  \sum_{1\le j\le n}
+%  \frac {1} { (x_j - x_1) \ldots (x_j - x_{j-1})
+%              (x - x_j) (x_j - x_{j+1}) \ldots (x_j - x_n) }
+%  \\
+%  = \frac {1} { (x - x_1) \ldots (x - x_n) }.
+%\end{spliteqn}
+% \end{demo}
+% \end{figure}
+%
+% \DescribeEnv{subsplit}
+% If you have a very badly behaved equation, you might want to split a part
+% of it (say, a bit of a fraction), particularly if you're doing things in
+% narrow columns.
+%
+% \begin{figure}
+% \begin{demo}[w]{A \env{subsplit} environment}
+%\begin{equation}
+%  \frac{
+%    \begin{subsplit}
+%      q^{\frac{1}{2} n(n+1)}(ea; q^2)_\infty (eq/a; q^2)_\infty \\
+%                 (caq/e; q^2)_\infty (cq^2/ae; q^2)_\infty
+%    \end{subsplit}
+%  }{
+%    (e; q)_\infty (cq/e; q)_\infty
+%  }
+%\end{equation}
+% \end{demo}
+% \end{figure}
+%
+% \subsection{Matrices}
+%
+% Also included in the \package{mathenv} package is a collection of things
+% for typesetting matrices.  The standard \env{array} doesn't (in my opinion)
+% provide the right sort of spacing for matrices.  \PlainTeX\ provides some
+% quite nice matrix handling macros, but they don't work in the appropriate
+% \LaTeX\ way.
+%
+% \textbf{Warning:} These definitions will make old versions of
+% \package{plain.sty} unhappy; newer versions correctly restore the
+% Plain~\TeX\ macros |\matrix| and |\pmatrix|.
+%
+% \DescribeEnv{matrix}
+% The simple way to do matrices is with the \env{matrix} environment.
+%
+% \begin{grammar}
+%
+% <matrix-env>	::= \[[ <begin-matrix> <contents> <end-matrix> \]]
+%
+% <begin-matrix> ::= \[[ "\\begin{matrix}" \[ "[" <matrix-cols> "]" \] \]]
+%
+% <matrix-cols>	::= \[[
+%   \< \[ "[" \] \[ "T" \] \( "l" \\ "c" \\ "r" \) \>
+% \]]
+%
+% <end-matrix>	::= \[[ "\\end{stack}" \]]
+%
+% \end{grammar}
+%
+% The \lit{l}, \lit{c} and \lit{r} columns are fairly obvious -- they align
+% their contents in the appropriate way.  The \lit{[} character is more
+% complicated.  It means `repeat the remaining column types forever', so a
+% preamble of \lit{cc[lr} means `two centred columns, then alternating left-
+% and right-aligned columns for as often as needed'.  The default preamble,
+% if you don't specify one, is \lit{[c} -- `any number of centred columns'.
+%
+% \DescribeMacro{\multicolumn}
+% The |\multicolumn| command works correctly in matrices, although you should
+% bear in mind that you should give \env{matrix} column types, not
+% \env{array} ones.
+%
+% \DescribeEnv{pmatrix}
+% The standard \env{matrix} environment doesn't put any delimiters around the
+% matrix.  You can use the standard |\left| and |\right| commands, although
+% this is a bit nasty.  The \env{pmatrix} environment will put parentheses
+% around the matrix it creates; it's otherwise exactly the same as
+% \env{matrix}.
+%
+% \DescribeEnv{dmatrix}
+% A \env{dmatrix} environment is also provided.  It takes two extra
+% arguments: the left and right delimiter characters (without |\left| or
+% |\right|).
+%
+% \begin{figure}
+% \begin{demo}[w]{Various \env{matrix} environments}
+%\[ \begin{matrix} 1 & 0 \\ 0 & -1 \end{matrix} \quad
+%   \begin{pmatrix}
+%     \cos\theta & \sin\theta \\
+%    -\sin\theta & \cos\theta
+%   \end{pmatrix} \quad
+%   \begin{dmatrix}[] 0 & -i \\ i & 0 \end{dmatrix}
+%\]
+% \end{demo}
+% \end{figure}
+%
+% \DescribeEnv{smatrix}
+% Normal matrices always come out the same size; they don't change size
+% according to the surrounding context (unfortunately).  However, it can be
+% occasionally useful to put matrices in running text, so you can talk about
+% $A$ being $\bigl( \begin{smatrix} a & b \\ b & c \end{smatrix} \bigr)$
+% being its own transpose (i.e., $A = A^T$).  This is accomplished using the
+% \env{smatrix} (the `s' stands for `small' -- I thought that `smallmatrix'
+% was too big to type inline).  As well as inline text, the \env{smatrix}
+% can be useful in displays, if the matrix is deep in a subformula.  I can't
+% think of any examples offhand, though.
+%
+% \DescribeEnv{spmatrix}
+% \DescribeEnv{sdmatrix}
+% The \env{smatrix} environment doesn't supply any delimiters, like
+% \env{matrix}.  There are \env{spmatrix} and \env{sdmatrix} environments
+% which do, though.  Note that delimiters have a tendency to get too big and
+% mess up the line spacing -- I had to use explicitly |\big| delimiters
+% in the above example.
+%
+% \DescribeEnv{pmatrix*}
+% \DescribeEnv{spmatrix*}
+% \DescribeEnv{sdmatrix*}
+% All the small matrix environments have starred versions, which are more
+% suitable for use in displays, since they have more space between the rows.
+% They're intended for typesetting really big matrices in displays.
+%
+% \DescribeMacro{\ddots}
+% \DescribeMacro{\vdots}
+% The standard |\vdots| and |\ddots| commands don't produce anything at all
+% nice in small matrices, so this package redefines them so that they scale
+% properly to smaller sizes.
+%
+% \DescribeEnv{genmatrix}
+% Actually, all these environments are special cases of one: \env{genmatrix}.
+% This takes oodles of arguments:
+% \begin{quote} \synshorts
+% "\\begin{genmatrix}{"<matrix-style>"}{"<outer-style>"}" \\
+% \null \qquad "{"<spacing>"}{"<left-delim>"}{"<right-delim>"}" \\
+% \null \quad\vdots \\
+% "\\end{genmatrix}"
+% \end{quote}
+% The two `style' arguments should be things like |\textstyle| or
+% |\scriptstyle|; the first, \<matrix-style>, is the style to use for the
+% matrix elements, and the second, \<outer-style>, is the style to assume
+% for the surrounding text (this affects the spacing within the matrix; it
+% should usually be the same as \<matrix-style>).  The \<spacing> is inserted
+% between the matrix and the delimiters, on each side of the matrix.  It's
+% usually `|\,|' in full-size matrices, and blank for small ones.  The
+% delimiters are inserted around the matrices, and sized appropriately.
+%
+% \DescribeEnv{newmatrix}
+% You can create your own matrix environments if you like, using the
+% |\newmatrix| command.  It takes two arguments, although they're a bit
+% odd.  The first is the name of the environment, and the second contains
+% the arguments to pass to \env{genmatrix}.  For example, the \env{pmatrix}
+% environment was defined by saying
+%
+% \begin{listing}
+%\newmatrix{pmatrix}{{\textstyle}{\textstyle}{\,}{(}{)}}
+% \end{listing}
+%
+% If you don't pass all three arguments, then you end up requiring the
+% user to specify the remaining ones.  This is how \env{dmatrix} works.
+%
+% \DescribeEnv{script}
+% Finally, although it's not really a matrix, stacked super- and subscripts
+% follow much the same sorts of spacing rules.  The \env{script} environment
+% allows you to do this sort of thing very easily.  It essentially provides
+% a `matrix' with the right sort of spacing.  The default preamble string is
+% \lit{c}, giving you centred scripts, although you can say
+% |\begin{script}[l]| for left-aligned scripts, which is better if the
+% script is being placed to the right of its operator.  If you're really
+% odd, you can have more than one column.
+%
+% \begin{demo}{Example of \env{script}}
+%\[ \mathop{{\sum}'}_{x \in A}
+%   f(x)
+%   \stackrel{\mathrm{def}}{=}
+%   \sum_{\begin{script}
+%     x \in A \\ x \ne 0
+%   \end{script}} f(x)
+%\]
+% \end{demo}
+%
+%
+% \subsection{Other \package{mathenv} environments}
+%
+% The \package{mathenv} package contains some other environments which may
+% be useful, based on the enhanced \env{tabular} and \env{array}
+% environments.
+%
+% \DescribeEnv{cases}
+% The \env{cases} environment lets you say things like the following:
+%
+% \begin{demo}[w]{Example of \env{cases}}
+%\[ P_{r-j} = \begin{cases}
+%               0 & if $r-j$ is odd \\
+%               r!\,(-1)^{(r-j)/2} & if $r-j$ is even
+%             \end{cases}
+%\]
+% \end{demo}
+%
+% The spacing required for this is a bit messy, so providing an environment
+% for it is quite handy.
+%
+% \DescribeEnv{smcases}
+% The \env{smcases} environment works the same way as \env{cases}, but with
+% scriptsize lettering.
+%
+% \implementation
+%
+%
+%^^A-------------------------------------------------------------------------
+% \section{Implementation of table handling}
+%
+%
+% Here we go.  It starts horrid and gets worse.  However, it does stay nicer
+% than the original, IMHO.
+%
+%    \begin{macrocode}
+%<*mdwtab>
+%    \end{macrocode}
+%
+%
+% \subsection{Registers, switches and things}
+%
+% We need lots of these.  It's great fun.
+%
+% The two count registers are simple enough:
+%
+% \begin{description}
+% \item [\cs{tab@state}] contains the current parser state.  Since we
+%       probably won't be parsing preambles recursively, this is a global
+%       variable.
+% \item [\cs{tab@columns}] contains the number of the current column.
+% \item [\cs{tab@hlstate}] contains the state required for hline management.
+% \end{description}
+%
+%    \begin{macrocode}
+\newcount\tab@state
+\newcount\tab@columns
+%    \end{macrocode}
+%
+% We need \emph{lots} of token registers.  Fortunately, most of them are only
+% used during parsing.  We'll use \PlainTeX's scratch tokens for this.  Note
+% that |\toks\tw@| isn't used here.  It, and |\toks@|, are free for use by
+% column commands.
+%
+%    \begin{macrocode}
+\newtoks\tab@preamble
+\newtoks\tab@shortline
+\toksdef\tab@pretext 4
+\toksdef\tab@posttext 6
+\toksdef\tab@userpretext 8
+%    \end{macrocode}
+%
+% The dimens are fairly straightforward.  The inclusion of |\col@sep| is a
+% sacrifice to compatibility -- judicious use of |\let| in \package{array}
+% would have saved a register.
+%
+%    \begin{macrocode}
+\newdimen\extrarowheight
+\newdimen\tabextrasep
+\newdimen\arrayextrasep
+\newdimen\smarraycolsep
+\newdimen\smarrayextrasep
+\newdimen\tab@width
+\newdimen\col@sep
+\newdimen\tab@endheight
+\newdimen\arraythickrulewidth
+\newdimen\tab@rulewidth
+%    \end{macrocode}
+%
+% Some skip registers too.  Phew.
+%
+%    \begin{macrocode}
+\newskip\tab@leftskip
+\newskip\tab@rightskip
+%    \end{macrocode}
+%
+% And some switches.  The first three are for the parser.
+%
+%    \begin{macrocode}
+\newif\iftab@firstcol
+\newif\iftab@initrule
+\newif\iftab@rule
+\newif\iftab@vgap
+%    \end{macrocode}
+%
+% Now assign some default values to new dimen parameters.  These definitions
+% are essentially the equivalent of an |\openup 1\jot| in \env{array}, but
+% not in \env{tabular}.  This looks nice, I think.
+%
+%    \begin{macrocode}
+\tabextrasep\z@
+\arrayextrasep\jot
+\smarraycolsep\thr@@\p@
+\smarrayextrasep\z@
+\arraythickrulewidth\p@
+%    \end{macrocode}
+%
+% Set some things up for alien table environments.
+%
+%    \begin{macrocode}
+\let\tab@extrasep\tabextrasep
+\let\tab@penalty\relax
+%    \end{macrocode}
+%
+%
+% \subsection{Some little details}
+%
+% \begin{macro}{\@maybe@unskip}
+%
+% This macro solves a little problem.  In an alignment (and in other places)
+% it's desirable to suppress trailing space.  The usual method, to say
+% |\unskip|, is a little hamfisted, because it removes perfectly reasonable
+% aligning spaces like |\hfil|s.  While as a package writer I can deal with
+% this sort of thing by saying |\kern\z@| in appropriate places, it can
+% annoy users who are trying to use |\hfill| to override alignment in funny
+% places.
+%
+% My current solution seems to be acceptable.  I'll remove the natural width
+% of the last glue item, so that it can still stretch and shrink if
+% necessary.  The implementation makes use of the fact that multiplying
+% a \<skip> by a \<number> kills off the stretch.  (Bug fix: don't do this
+% when we're in vertical mode.)
+%
+%    \begin{macrocode}
+\def\@maybe@unskip{\ifhmode\hskip\m@ne\lastskip\relax\fi}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\q@delim}
+%
+% Finally, for the sake of niceness, here's a delimiter token I can use
+% for various things.  It's a `quark', for what it's worth (i.e., it expands
+% to itself) although I'm not really sure why this is a good thing.  As far
+% as I'm concerned, it's important that it has a unique meaning (i.e., that
+% it won't be |\ifx|-equal to other things, or something undefined) and that
+% it won't be used where I don't expect it to be used.  \TeX\ will loop
+% horridly if it tries to expand this, so I don't think that quarks are
+% wonderfully clever thing to use.  (Maybe it should really expand to
+% something like `\syntax{<quark>"."}', which will rapidly fill \TeX's memory
+% if it gets accidentally expanded.  Still, I'll leave it as it is until
+% such time as I understand the idea more.)
+%
+%    \begin{macrocode}
+\def\q@delim{\q@delim}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Parser states}
+% 
+% Now we start on the parser.  It's really simple, deep down.  We progress
+% from state to state, extracting tokens from the preamble and building
+% command names from them.  Each command calls one of the element-building
+% routines, which works out which state it should be in.  We go through each
+% of the states in between (see later) doing default things for the ones we
+% missed out.
+% 
+% Anyway, here's some symbolic names for the states.  It makes my life
+% easier.
+%
+%    \begin{macrocode}
+\chardef\tab@startstate 0
+\chardef\tab@loopstate 1
+\chardef\tab@rulestate 1
+\chardef\tab@prespcstate 2
+\chardef\tab@prestate 3
+\chardef\tab@colstate 4
+\chardef\tab@poststate 5
+\chardef\tab@postspcstate 6
+\chardef\tab@limitstate 7
+%    \end{macrocode}
+%
+%
+% \subsection{Adding things to token lists}
+%
+% Define some macros for adding stuff to the beginning and end of token
+% lists.  This is really easy, actually.  Here we go.
+%
+%    \begin{macrocode}
+\def\tab@append#1#2{#1\expandafter{\the#1#2}}
+\def\tab@prepend#1#2{%
+  \toks@{#2}#1\expandafter{\the\expandafter\toks@\the#1}%
+}
+%    \end{macrocode}%
+%
+%
+% \subsection{Committing a column to the preamble}
+%
+% Each time we pass the `rule' state, we `commit' the tokens we've gathered
+% so far to the main preamble token list.  This is how we do it.  Note the
+% icky use of |\expandafter|.
+%
+%    \begin{macrocode}
+\def\tab@commit{%
+%    \end{macrocode}
+%
+% If this isn't the first column, then we need to put in a column separator.
+%
+%    \begin{macrocode}
+  \iftab@firstcol\else%
+    \expandafter\tab@append\expandafter\tab@preamble%
+      \expandafter{\tab@tabtext}%
+  \fi%
+%    \end{macrocode}
+%
+% Now we spill the token registers into the main list in a funny order (which
+% is why we're doing it in this strange way in the first place.
+%
+%    \begin{macrocode}
+  \toks@\expandafter{\tab@midtext}%
+  \tab@preamble\expandafter{%
+    \the\expandafter\tab@preamble%
+    \the\expandafter\tab@pretext%
+    \the\expandafter\tab@userpretext%
+    \the\expandafter\toks@%
+    \the\tab@posttext%
+  }%
+%    \end{macrocode}
+%
+% Now reset token lists and things for the next go round.
+%
+%    \begin{macrocode}
+  \tab@firstcolfalse%
+  \tab@pretext{}%
+  \tab@userpretext{}%
+  \tab@posttext{}%
+}
+%    \end{macrocode}
+%
+%
+% \subsection{Playing with parser states}
+%
+% \begin{macro}{\tab@setstate}
+%
+% This is how we set new states.  The algorithm is fairly simple, really.
+%
+% ^^A Let's see how good my TeX really is... ;-)
+% ^^A Actually, it doesn't seem to have worked out too badly.  Maybe I should
+% ^^A write a package to do this automatically.  It's rather tricky, though.
+%
+% \def\qq{\mbox{\quad}}
+% \sbox{0}{\itshape\textunderscore}\def\_{\usebox{0}}
+%
+% \begin{quote}
+% {\bf while} $\it tab\_state \ne s$ {\bf do} \\
+% \qq $\mathit{tab\_state = tab\_state}+1$; \\
+% \qq {\bf if} $\it tab\_state = tab\_limitState$ {\bf then}
+%				$\it tab\_state=tab\_loopState$; \\
+% \qq {\bf if} $\it tab\_state = tab\_preSpcState$ {\bf then} \\
+% \qq \qq {\bf if} $\it tab\_initRule$ {\bf then} \\
+% \qq \qq \qq $\it tab\_initRule = {\bf false}$; \\
+% \qq \qq {\bf else} \\
+% \qq \qq \qq {\bf if} $\it tab\_inMultiCol$ {\bf then moan}; \\
+% \qq \qq \qq $\it commit$; \\
+% \qq \qq \qq $\it append(tab\_shortLine,\hbox{`|&\omit|')}$; \\
+% \qq \qq {\bf end\,if}; \\
+% \qq {\bf end\,if}; \\
+% \qq {\bf if} $\it tab\_state \ne s$ {\bf then}
+%				$\it do\_default(tab\_state)$; \\
+% {\bf end\,while};
+% \end{quote}
+%
+% First we decide if there's anything to do.  If so, we call another macro to
+% do it for us.
+%
+%    \begin{macrocode}
+\def\tab@setstate#1{%
+  \ifnum#1=\tab@state\else%
+    \def\@tempa{\tab@setstate@i{#1}}%
+    \@tempa%
+  \fi%
+}
+%    \end{macrocode}
+%
+% This is where the fun is.  First we bump the state by one, and loop back
+% if we fall off the end.
+%
+%    \begin{macrocode}
+\def\tab@setstate@i#1{%
+  \global\advance\tab@state\@ne%
+  \ifnum\tab@state>\tab@limitstate%
+    \global\tab@state\tab@loopstate%
+  \fi%
+%    \end{macrocode}
+%
+% Now, if we've just passed the ruleoff state, we commit the current text
+% \emph{unless} this was the strange initial rule at the very beginning.  We
+% provide a little hook here so that |\multicolumn| can moan if you try and
+% give more than one column there.  We also add another tab/omit pair to the
+% list we use for |\vgap|.
+%
+%    \begin{macrocode}
+  \ifnum\tab@state=\tab@prespcstate%
+    \iftab@initrule%
+      \tab@initrulefalse%
+    \else%
+      \tab@looped%
+      \tab@commit%
+      \tab@append\tab@shortline{&\omit}%
+    \fi%
+  \fi%
+%    \end{macrocode}
+%
+% Now we decide whether to go round again.  If not, we do the default thing
+% for this state.  This is mainly here so that we can put the |\tabcolsep| or
+% whatever in if the user didn't give an \lit{@} expression.
+%
+%    \begin{macrocode}
+  \ifnum#1=\tab@state%
+    \let\@tempa\relax%
+  \else%
+    \csname tab@default@\number\tab@state\endcsname%
+  \fi%
+  \@tempa%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% Now we set up the default actions for the various states.
+%
+% In state~2 (pre-space) we add in the default gap if either we didn't have
+% an \lit{@} expression in the post-space state or there was an explicit
+% intervening rule.
+%
+%    \begin{macrocode}
+\@namedef{tab@default@2}{%
+  \iftab@rule%
+    \tab@append\tab@pretext{\hskip\col@sep}%
+  \fi%
+}
+%    \end{macrocode}
+%
+% If the user omits the column type, we insert an `l'-type column and moan
+% a lot.
+%
+%    \begin{macrocode}
+\@namedef{tab@default@4}{%
+  \tab@err@misscol%
+  \tab@append\tab@pretext{\tab@bgroup\relax}%
+  \tab@append\tab@posttext{\relax\tab@egroup\hfil}%
+  \tab@append\tab@shortline{\hfil}%
+  \advance\tab@columns\@ne%
+}
+%    \end{macrocode}
+%
+% Finally we deal with the post-space state.  We set a marker so that we
+% put in the default space in the pre-space state later too.
+%
+%    \begin{macrocode}
+\@namedef{tab@default@6}{%
+  \tab@append\tab@posttext{\hskip\col@sep}%
+  \tab@ruletrue%
+}
+%    \end{macrocode}
+%
+%
+% \subsection{Declaring token types}
+%
+% \begin{macro}{\tab@extracol}
+%
+% Before we start, we need to handle |\extracolsep|.  This is a right pain,
+% because the original version of \env{tabular} worked on total expansion,
+% which is a Bad Thing.  On the other hand, turning |\extracolsep| into a
+% |\tabskip| is also a major pain.
+%
+%    \begin{macrocode}
+\def\tab@extracol#1#2{\tab@extracol@i#1#2\extracolsep{}\extracolsep\end}
+\def\tab@extracol@i#1#2\extracolsep#3#4\extracolsep#5\end{%
+  \ifx @#3@%
+    \def\@tempa{#1{#2}}%
+  \else%
+    \def\@tempa{#1{#2\tabskip#3\relax#4}}%
+  \fi%
+  \@tempa%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% This is where we do the work for inserting preamble elements.
+%
+% \begin{macro}{\tabruletype}
+%
+% Inserting rules is interesting, because we have to decide where to put
+% them.  If this is the funny initial rule, it goes in the pre-text list,
+% otherwise it goes in the post-text list.  We work out what to do first
+% thing:
+%
+%    \begin{macrocode}
+\def\tabruletype#1{\tab@extracol\tabruletype@i{#1}}%
+\def\tabruletype@i#1{%
+  \iftab@initrule%
+    \let\tab@tok\tab@pretext%
+  \else%
+    \let\tab@tok\tab@posttext%
+  \fi%
+%    \end{macrocode}
+%
+% Now if we're already in the rule state, we must have just done a rule.
+% This means we must put in the |\doublerulesep| space, both here and in the
+% shortline list.  Otherwise we just stick the rule in.
+%
+% This is complicated, because |\vgap| needs to be able to remove some bits
+% of rule.  We pass each one to a macro |\tab@ckr|, together with the column
+% number, which is carefully bumped at the right times, and this macro will
+% vet the rules and output the appropriate ones.  There's lots of extreme
+% |\expandafter| nastiness as a result.  Amazingly, this actually works.
+%
+%    \begin{macrocode}
+  \ifnum\tab@state=\tab@rulestate%
+    \tab@append\tab@tok{\hskip\doublerulesep\begingroup#1\endgroup}%
+    \expandafter\tab@append\expandafter\tab@shortline\expandafter{%
+      \expandafter\hskip\expandafter\doublerulesep%
+      \expandafter\tab@ckr\expandafter{\the\tab@columns}%
+        {\begingroup#1\endgroup}%
+    }%
+  \else%
+    \tab@setstate\tab@rulestate%
+    \tab@append\tab@tok{\begingroup#1\endgroup}%
+    \expandafter\tab@append\expandafter\tab@shortline\expandafter{%
+      \expandafter\tab@ckr\expandafter{\the\tab@columns}%
+        {\begingroup#1\endgroup}%
+    }%
+  \fi%
+%    \end{macrocode}
+%
+% Finally, we say there was a rule here, so that default space gets put in
+% after this.  Otherwise we lose lots of generality.
+%
+%    \begin{macrocode}
+  \tab@ruletrue%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tabspctype}
+%
+% We need to work out which space-state we should be in.  Then we just put
+% the text in.  Easy, really.
+%
+%    \begin{macrocode}
+\def\tabspctype#1{\tab@extracol\tabspctype@i{#1}}%
+\def\tabspctype@i#1{%
+  \tab@rulefalse%
+  \ifnum\tab@state>\tab@prespcstate%
+    \tab@setstate\tab@postspcstate%
+    \let\tab@tok\tab@posttext%
+  \else%
+    \tab@setstate\tab@prespcstate%
+    \let\tab@tok\tab@pretext%
+  \fi%
+  \tab@append\tab@tok{\begingroup#1\endgroup}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tabcoltype}
+%
+% If we're already in the column state, we bump the state and loop round
+% again, to get all the appropriate default behaviour.  We bump the column
+% counter, and add the bits of text we were given to appropriate token lists.
+% We also add the |\hfil| glue to the shortline list, to space out the rules
+% properly.
+%
+%    \begin{macrocode}
+\def\tabcoltype#1#2{%
+  \ifnum\tab@state=\tab@colstate%
+    \global\advance\tab@state\@ne%
+  \fi%
+  \advance\tab@columns\@ne%
+  \tab@setstate\tab@colstate%
+  \tab@append\tab@pretext{#1}%
+  \tab@append\tab@posttext{#2}%
+  \tab@append\tab@shortline{\hfil}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tabuserpretype}
+% \begin{macro}{\tabuserposttype}
+%
+% These are both utterly trivial.
+%
+%    \begin{macrocode}
+\def\tabuserpretype#1{%
+  \tab@setstate\tab@prestate%
+  \tab@prepend\tab@userpretext{#1}%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\tabuserposttype#1{%
+  \tab@setstate\tab@poststate%
+  \tab@prepend\tab@posttext{#1}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsection{The colset stack}
+%
+% Let's start with something fairly easy.  We'll keep a stack of column sets
+% so that users don't get confused by package authors changing the current
+% column set.  This is fairly easy, really.
+%
+% \begin{macro}{\tab@push}
+% \begin{macro}{\tab@pop}
+% \begin{macro}{\tab@head}
+%
+% These are the stack management routines.  The only important thing to note
+% is that |\tab@head| must take place \emph{only} in \TeX's mouth, so we can
+% use it in |\csname|\dots|\endcsname| constructions.
+%
+%    \begin{macrocode}
+\def\tab@push#1#2{%
+  \toks@{{#2}}%
+  \expandafter\def\expandafter#1\expandafter{\the\expandafter\toks@#1}%
+}
+\def\tab@pop#1{\edef#1{\expandafter\@gobble#1}}
+\def\tab@head#1{\expandafter\tab@head@i#1\relax}
+\def\tab@head@i#1#2\relax{#1}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\colset}
+% \begin{macro}{\colpush}
+% \begin{macro}{\colpop}
+%
+% Now we can define the user macros.
+%
+%    \begin{macrocode}
+\def\tab@colstack{{tabular}}
+\def\colset{\colpop\colpush}
+\def\colpush{\tab@push\tab@colstack}
+\def\colpop{\tab@pop\tab@colstack}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\tab@colset}
+%
+% Now we define a shortcut for reading the top item off the stack.
+%
+%    \begin{macrocode}
+\def\tab@colset{\tab@head\tab@colstack}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{The main parser routine}
+%
+% \begin{macro}{\tab@initread}
+%
+% This macro sets up lots of variables to their normal states prior to
+% parsing a preamble.  Some things may need changing, but not many.
+%
+%    \begin{macrocode}
+\def\tab@initread{%
+%    \end{macrocode}
+%
+% First, reset the parser state to the start state.
+%
+%    \begin{macrocode}
+  \global\tab@state\tab@startstate%
+%    \end{macrocode}
+%
+% We clear the token lists to sensible values, mostly.  The midtext macro
+% contains what to put in the very middle of each template -- |\multicolumn|
+% will insert its argument here.
+%
+%    \begin{macrocode}
+  \tab@preamble{}%
+  \tab@shortline{}%
+  \def\tab@tabtext{&}%
+  \def\tab@midtext{\ignorespaces####\@maybe@unskip}%
+  \tab@pretext{}%
+  \tab@userpretext{}%
+  \tab@posttext{}%
+  \let\tab@multicol\@empty%
+  \def\tab@startpause{\penalty\postdisplaypenalty\medskip}%
+  \def\tab@endpause{\penalty\predisplaypenalty\medskip}%
+%    \end{macrocode}
+%
+% Finally, reset the column counter, don't raise errors when we loop, and set
+% some parser flags to their appropriate values.
+%
+%    \begin{macrocode}
+  \tab@columns\z@%
+  \let\tab@looped\relax%
+  \tab@ruletrue%
+  \tab@initruletrue%
+  \tab@firstcoltrue%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@readpreamble}
+%
+% This is the main macro for preamble handling.  Actually, all it does is
+% gobble its argument's leading brace and call another macro, but it does it
+% with style.
+%
+%    \begin{macrocode}
+\def\tab@readpreamble#1{%
+  \tab@doreadpream{#1}%
+  \iftab@initrule\global\tab@state\tab@prespcstate\fi%
+  \tab@setstate\tab@rulestate%
+  \tab@commit%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@doreadpream}
+%
+% The preamble is in an argument.  Previous versions used a nasty trick using
+% |\let| and |\afterassignment|.  Now we use an explicit end token, to allow
+% dodgy column type handlers to scoop up the remaining preamble tokens
+% and process them.  Not that anyone would want to do that, oh no (see
+% the \lit{[} type in the \env{eqnarray} environment |;-)|).
+%
+%    \begin{macrocode}
+\def\tab@doreadpream#1{\tab@mkpreamble#1\q@delim}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@mkpreamble}
+%
+% This is the main parser routine.  It takes each token in turn, scrutinises
+% it carefully, and does the appropriate thing with it.
+%
+% The preamble was given as an argument to |\tab@doreadpream|, and that has
+% helpfully stripped off the initial |{| character.  We need to pick off the
+% next token (whatever it is) so we can examine it.  We'll use |\futurelet|
+% so we can detect groups and things in funny places.
+%
+%    \begin{macrocode}
+\def\tab@mkpreamble{\futurelet\@let@token\tab@mkpreamble@i}
+%    \end{macrocode}
+%
+% If we find a space token, we'll go off and do something a bit special,
+% since spaces are sort of hard to handle.  Otherwise we'll do it in the old
+% fashioned way.
+%
+%    \begin{macrocode}
+\def\tab@mkpreamble@i{%
+  \ifx\@let@token\@sptoken%
+    \expandafter\tab@mkpreamble@spc%
+  \else%
+    \expandafter\tab@mkpreamble@ii%
+  \fi%
+}
+%    \end{macrocode}
+%
+% If we find a |\@@endpreamble| token, that's it and we're finished.  We just
+% gobble it and return.  Otherwise, if it's an open group character, we'll
+% complain because someone's probably tried to put an argument in the wrong
+% place.  Finally, if none of the other things apply, we'll deal with the
+% character below.
+%
+%    \begin{macrocode}
+\def\tab@mkpreamble@ii{%
+  \ifx\@let@token\q@delim%
+    \def\@tempa{\let\@let@token}%
+  \else%
+    \ifcat\bgroup\noexpand\@let@token%
+      \tab@err@oddgroup%
+      \def\@tempa##1{\tab@mkpreamble}%
+    \else%
+      \let\@tempa\tab@mkpreamble@iii%
+    \fi%
+  \fi%
+  \@tempa%
+}
+%    \end{macrocode}
+%
+% Handle a character.  This involves checking to see if it's actually
+% defined, and then doing it.  Doing things this way means we won't get
+% stranded in mid-preamble unless a package author has blown it.
+%
+%    \begin{macrocode}
+\def\tab@mkpreamble@iii#1{%
+  \@ifundefined{\tab@colset!col.\string#1}{%
+    \tab@err@undef{#1}\tab@mkpreamble%
+  }{%
+    \@nameuse{\tab@colset!col.\string#1}%
+  }%
+}
+%    \end{macrocode}
+%
+% If we get given a space character, we'll look up the command name as
+% before.  If no-one's defined the column type we'll just skip it silently,
+% which lets users do pretty formatting if they like.
+%
+%    \begin{macrocode}
+\@namedef{tab@mkpreamble@spc} {%
+  \@ifundefined{\tab@colset!col. }{%
+    \tab@mkpreamble%
+  }{%
+    \@nameuse{\tab@colset!col. }%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\coldef}
+%
+% Here's how to define column types the nice way.  Some dexterity is required
+% to make everything work right, but it's simple really.
+%
+%    \begin{macrocode}
+\def\coldef{\@ifnextchar[\coldef@i{\coldef@i[\tab@colset]}}
+\def\coldef@i[#1]#2#3#{\coldef@ii[#1]{#2}{#3}}
+\def\coldef@ii[#1]#2#3#4{%
+  \expandafter\def\csname#1!col.\string#2\endcsname#3{%
+    #4\tab@mkpreamble%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\collet}
+%
+% We'd like to let people copy column types from other places.  This is how
+% to do it.
+%
+%    \begin{macrocode}
+\def\collet{\@ifnextchar[\collet@i{\collet@i[\tab@colset]}}
+\def\collet@i[#1]#2{%
+  \@ifnextchar=%
+    {\collet@ii[#1]{#2}}%
+    {\collet@ii[#1]{#2}=}%
+}
+\def\collet@ii[#1]#2={%
+  \@ifnextchar[%
+    {\collet@iii[#1]{#2}}%
+    {\collet@iii[#1]{#2}[\tab@colset]}%
+}
+\def\collet@iii[#1]#2[#3]#4{%
+  \expandafter\let\csname#1!col.\string#2\expandafter\endcsname%
+                  \csname#3!col.\string#4\endcsname%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\newcolumntype}
+%
+% We just bundle the text off to |\newcommand| and expect it to cope.  It
+% ought to.  The column type code inserts the user's tokens directly, rather
+% than calling |\tab@doreadpream| recursively.  The magic control sequence
+% is the one looked up by the parser.
+%
+% There's some additional magic here for compatibility with the obscure way
+% that \package{array} works.
+%
+%    \begin{macrocode}
+\def\newcolumntype#1{\@ifnextchar[{\nct@i{#1}}{\nct@i#1[0]}}
+\def\nct@i#1[#2]{\@ifnextchar[{\nct@ii{#1}[#2]}{\nct@iii{#1}{[#2]}}}
+\def\nct@ii#1[#2][#3]{\nct@iii{#1}{[#2][#3]}}
+\def\nct@iii#1#2#3{%
+  \expandafter\let\csname\tab@colset!col.\string#1\endcsname\relax%
+  \expandafter\newcommand\csname\tab@colset!col.\string#1\endcsname#2{%
+    \tab@deepmagic{#1}%
+    \tab@mkpreamble%
+    #3%
+  }%
+}
+%    \end{macrocode}
+%
+% Now for some hacking for compatibility with \package{tabularx}.
+%
+%    \begin{macrocode}
+\def\newcol@#1[#2]{\nct@iii{#1}{[#2]}}
+%    \end{macrocode}
+%
+% And now some more.  This is seriously deep magic.  Hence the name.
+%
+%    \begin{macrocode}
+\def\tab@deepmagic#1{%
+  \csname NC@rewrite@\string#1\endcsname\NC@find\tab@@magic@@%
+}
+\def\NC@find#1\tab@@magic@@{}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Standard column types}
+%
+% First, make sure we're setting up the right columns.  This also sets the
+% default for the user.  Other packages must not use the |\colset| command
+% for defining columns -- they should use the stack operations defined above.
+%
+%    \begin{macrocode}
+\colset{tabular}
+%    \end{macrocode}
+%
+% Now do the simple alignment types.  These are fairly simple.  The
+% mysterious kern in the \lit{l} type is to stop the |\col@sep| glue from
+% vanishing due to the |\unskip| inserted by the standard |\tab@midtext| if
+% the column contains no text.  (Thanks for spotting this bug go to that
+% nice Mr~Carlisle.)
+%
+%    \begin{macrocode}
+\coldef l{\tabcoltype{\kern\z@\tab@bgroup}{\tab@egroup\hfil}}
+\coldef c{\tabcoltype{\hfil\tab@bgroup}{\tab@egroup\hfil}}
+\coldef r{\tabcoltype{\hfil\tab@bgroup}{\tab@egroup}}
+%    \end{macrocode}
+%
+% Some extensions now.  These are explicitly textual or mathematical
+% columns.  Can be useful if you're providing column types for other people.
+% I've inserted a kern here for exactly the same reason as for the \lit{l}
+% column type above.
+%
+%    \begin{macrocode}
+\coldef T#1{\tab@aligncol{#1}{\tab@btext}{\tab@etext}}
+\coldef M#1{\tab@aligncol{#1}{\tab@bmaths}{\tab@emaths}}
+\def\tab@aligncol#1#2#3{%
+  \if#1l\tabcoltype{\kern\z@#2}{#3\hfil}\fi%
+  \if#1c\tabcoltype{\hfil#2}{#3\hfil}\fi%
+  \if#1r\tabcoltype{\hfil#2}{#3}\fi%
+}
+%    \end{macrocode}
+%
+% Now for the default rules.
+%
+%    \begin{macrocode}
+\coldef ${\expandafter\tab@rulewd\expandafter\tab@vrule\@gobble}
+\def\tab@vrule{%
+  \expandafter\tabruletype\expandafter{%
+    \expandafter\vrule\expandafter\@width\the\tab@rulewidth%
+  }%
+  \tab@mkpreamble%
+}
+\coldef |{\tabruletype{\vrule\@width\arrayrulewidth}}
+\coldef !#1{\tabruletype{#1}}
+%    \end{macrocode}
+%
+% Deal with \lit{@} expressions.
+%
+%    \begin{macrocode}
+\coldef @#1{\tabspctype{#1}}
+%    \end{macrocode}
+%
+% And the paragraph types.  I've added things to handle footnotes here.
+%
+%    \begin{macrocode}
+\coldef p#1{\tabcoltype%
+             {\savenotes\vtop\tab@bpar{#1}}%
+             {\tab@epar\spewnotes\hfil}}
+\coldef m#1{\tabcoltype%
+             {\savenotes$\vcenter\tab@bpar{#1}}%
+             {\tab@epar$\spewnotes\hfil}}
+\coldef b#1{\tabcoltype%
+             {\savenotes\vbox\tab@bpar{#1}}%
+             {\tab@epar\spewnotes\hfil}}
+%    \end{macrocode}
+%
+% Phew.  Only a few more left now.  The user text ones.
+%
+%    \begin{macrocode}
+\coldef >#1{\tabuserpretype{#1}}
+\coldef <#1{\tabuserposttype{#1}}
+%    \end{macrocode}
+%
+% The strange column type.
+%
+%    \begin{macrocode}
+\coldef ##1#2{\tabcoltype{#1}{#2}}
+%    \end{macrocode}
+%
+% And \lit{*}, which repeats a preamble spec.  This is really easy, and not
+% at all like the original one.
+%
+%    \begin{macrocode}
+\coldef *#1#2{%
+  \count@#1%
+  \loop\ifnum\count@>0\relax%
+    \tab@doreadpream{#2}%
+    \advance\count@\m@ne%
+  \repeat%
+}
+%    \end{macrocode}
+%
+%
+% \subsection{Paragraph handling}
+%
+% First of all, starting new paragraphs: the vbox token is already there, and
+% we have the width as an argument.
+%
+% \begin{macro}{\tab@bpar}
+%
+% There are some gymnastics to do here to support lists which form the
+% complete text of the parbox.  One of the odd things I'll do here is to
+% not insert a strut on the first line: instead, I'll put the text into a
+% box register so that I can inspect it later.  So that I have access to
+% the height of the first line, I'll use a |\vtop| -- I can get at the
+% final depth by using |\prevdepth|, so this seems to be the most general
+% solution.
+%
+%    \begin{macrocode}
+\def\tab@bpar#1{%
+  \bgroup%
+  \setlength\hsize{#1}%
+  \@arrayparboxrestore%
+  \setbox\z@\vtop\bgroup%
+  \global\@minipagetrue%
+  \global\@noskipsecfalse%
+  \everypar\expandafter{\the\everypar%
+    \global\@minipagefalse%
+    \everypar{}%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@epar}
+%
+% To end the paragraph, close the box.  That sounds easy, doesn't it?
+% I need to space out the top and bottom of the box so that it looks as if
+% struts have been applied.
+%
+%    \begin{macrocode}
+\def\tab@epar{%
+%    \end{macrocode}
+%
+% Anyway, I should end the current paragraph if I'm still in horizontal
+% mode.  A simple |\par| will do this nicely.  I'll also remove any trailing
+% vertical glue (which may be left there by a list environment), because
+% things will look very strange otherwise.
+%
+%    \begin{macrocode}
+  \ifhmode\@maybe@unskip\par\fi%
+  \unskip%
+%    \end{macrocode}
+%
+% Now I'll look at the depth of the last box: if it's less deep than my
+% special strut, I'll cunningly backpedal by a bit, and add a box with the
+% appropriate depth.  Since this will lie on the previous baseline, it won't
+% alter the effective height of the box.  There's a snag here.  |\prevdepth|
+% may be wrong for example if the last thing inserted was a rule, or the
+% box is just empty.  Check for this specially.  (Thanks to Rowland for
+% spotting this.)
+%
+%    \begin{macrocode}
+  \ifdim\prevdepth>-\@m\p@\ifdim\prevdepth<\dp\@arstrutbox%
+    \kern-\prevdepth%
+    \nointerlineskip%
+    \vtop to\dp\@arstrutbox{}%
+  \fi\fi%
+%    \end{macrocode}
+%
+% I've finished the bottom of the box now: I'll close it, and start work on
+% the top again.
+%
+%    \begin{macrocode}
+  \egroup%
+%    \end{macrocode}
+%
+% For top-alignment to work, the first item in the box must be another box.
+% (This is why I couldn't just set |\prevdepth| at the beginning.)  If the
+% box isn't high enough, I'll add a box of the right height and then kern
+% backwards so that the `real' first box ends up in the right place.
+%
+%    \begin{macrocode}
+  \ifdim\ht\z@<\ht\@arstrutbox%
+    \vbox to\ht\@arstrutbox{}%
+    \kern-\ht\z@%
+  \fi%
+  \unvbox\z@%
+  \egroup%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Gentle persuasion}
+%
+% To persuade \package{longtable} to work, we emulate some features of
+% the \package{array} way of doing things.  It's a shame, but we have to do
+% it, because \package{longtable} came first.
+%
+% Note the horribleness with the grouping here.  In order to get everything
+% expanded at the right time, |\@preamble| just replaces itself with the (not
+% expanded!) preamble string, using |\the|.  This means that the preamble
+% string must be visible in the group just above us.  Now,
+% \package{longtable} (and \package{array} for that matter) does
+% |\@mkpreamble| immediately after opening a new group.  So all we need to do
+% is close that group, do our stuff, and reopen the group again.  (Evil
+% laughter\dots)
+%
+%    \begin{macrocode}
+\def\@mkpream#1{%
+  \endgroup%
+  \colset{tabular}%
+  \tab@initread%
+  \def\tab@multicol{\@arstrut}%
+  \tab@preamble{\tab@multicol}%
+  \def\tab@midtext{\ignorespaces\@sharp\@sharp\@maybe@unskip}%
+  \tab@readpreamble{#1}%
+  \gdef\@preamble{\the\tab@preamble}%
+  \let\tab@bgroup\begingroup%
+  \let\tab@egroup\endgroup%
+  \begingroup%
+}
+%    \end{macrocode}
+%
+%
+% \subsection{Debugging}
+%
+% This macro just parses a preamble and displays it on the terminal.  It
+% means I can see whether the thing's working.
+%
+%    \begin{macrocode}
+\def\showpream#1{%
+  \tab@initread%
+  \tab@readpreamble{#1}%
+  \showthe\tab@preamble%
+  \showthe\tab@shortline%
+}
+%    \end{macrocode}
+%
+% A quick macro for showing column types.
+%
+%    \begin{macrocode}
+\def\showcol#1{%
+  \expandafter\show\csname\tab@colset!col.\string#1\endcsname%
+}
+%    \end{macrocode}
+%
+%
+% \subsection{The \env{tabular} and \env{array} environments}
+%
+% This is where we define the actual environments which users play with.
+%
+% \subsubsection{The environment routines}
+%
+% The real work is done in the |\@array| macro later.  We just set up lots
+% (and I mean \emph{lots}) of parameters first, and then call |\@array|.
+%
+% \begin{macro}{\tab@array}
+%
+% The |\tab@array| macro does most of the common array things.
+%
+%    \begin{macrocode}
+\def\tab@array{%
+  \tab@width\z@%
+  \let\tab@bgroup\tab@bmaths%
+  \let\tab@egroup\tab@emaths%
+  \@tabarray%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@btext}
+% \begin{macro}{\tab@bmaths}
+% \begin{macro}{\tab@etext}
+% \begin{macro}{\tab@emaths}
+%
+% These macros contain appropriate things to use when typesetting
+% text or maths macros.  They're all trivial.  They're here only for
+% later modification by funny things like the \env{smarray} environment.
+%
+%    \begin{macrocode}
+\def\tab@btext{\begingroup}
+\def\tab@bmaths{$}
+\def\tab@etext{\endgroup}
+\def\tab@emaths{\m@th$}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{environment}{array}
+%
+% Now for the \env{array} environment.  The `|$|' signs act as a group, so we
+% don't need to do extra grouping this time.  Closing the environment is
+% easy.
+%
+%    \begin{macrocode}
+\def\array{%
+  \col@sep\arraycolsep%
+  \let\tab@extrasep\arrayextrasep%
+  \tab@normalstrut%
+  \tab@array%
+}
+\def\endarray{%
+  \crcr%
+  \egroup%
+  \tab@right%
+  \tab@restorehlstate%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{environment}{smarray}
+%
+% Now for something a little different.  The \env{smarray} environment
+% gives you an array with lots of small text.
+%
+%    \begin{macrocode}
+\def\smarray{%
+  \extrarowheight\z@%
+  \col@sep\smarraycolsep%
+  \let\tab@extrasep\smarrayextrasep%
+  \def\tab@bmaths{$\scriptstyle}%
+  \def\tab@btext{\begingroup\scriptsize}%
+  \setbox\z@\hbox{\scriptsize\strut}%
+  \dimen@\ht\z@\dimen@ii\dp\z@\tab@setstrut%
+  \tab@array%
+}
+\let\endsmarray\endarray
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{macro}{\tabstyle}
+%
+% This is a little hook that document designers can use to modify the
+% appearance of tables throughout a document.  For example, I've set it to
+% make the text size |\small| in all tables in this document.  Macro writers
+% shouldn't try to use it as a hook for their own evilness, though.  I've
+% used |\providecommand| to avoid nobbling an existing definition.
+%
+%    \begin{macrocode}
+\providecommand\tabstyle{}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\@tabular}
+%
+% The two \env{tabular} environments share lots of common code, so we
+% separate that out.  (This needs to be done better.)  All we really do here
+% is set up the |\tab@bgroup| and |\tab@egroup| to localise things properly,
+% and then go.
+%
+%    \begin{macrocode}
+\def\@tabular#1{%
+  \tabstyle%
+  \setlength\tab@width{#1}%
+  \let\tab@bgroup\tab@btext%
+  \let\tab@egroup\tab@etext%
+  \col@sep\tabcolsep%
+  \let\tab@extrasep\tabextrasep%
+  \tab@normalstrut%
+  \@tabarray%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{tabular}
+% \begin{environment}{tabular*}
+%
+% These environments just call a macro which does all the common stuff.
+%
+%    \begin{macrocode}
+\def\tabular{\@tabular\z@}
+\expandafter\let\csname tabular*\endcsname\@tabular
+\let\endtabular\endarray
+\expandafter\let\csname endtabular*\endcsname\endarray
+%    \end{macrocode}
+%
+% \end{environment}
+% \end{environment}
+%
+% \subsubsection{Setting the strut height}
+%
+% \begin{macro}{\tab@setstrut}
+%
+% We use a magical strut, called |\@arstrut|, which keeps the table from
+% collapsing around our heads.  This is where we set it up.
+%
+% It bases the array strut size on the given values of |\dimen@| and
+% |\dimen@ii|, amended by various appropriate fiddle values added in by
+% various people.
+%
+%    \begin{macrocode}
+\def\tab@setstrut{%
+  \setbox\@arstrutbox\hbox{%
+    \vrule%
+      \@height\arraystretch\dimen@%
+      \@depth\arraystretch\dimen@ii%
+      \@width\z@%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@normalstrut}
+%
+% This sets the strut the normal way, from the size of |\strutbox|.
+%
+%    \begin{macrocode}
+\def\tab@normalstrut{%
+  \dimen@\ht\strutbox\advance\dimen@\extrarowheight%
+  \dimen\tw@\dp\strutbox%
+  \tab@setstrut%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Setting up the alignment}
+%
+% The following bits are mainly for other packages to hook themselves onto.
+%
+%    \begin{macrocode}
+\let\@arrayleft\relax%
+\let\@arrayright\relax%
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\@tabarray{%
+  \let\@arrayleft\relax%
+  \let\@arrayright\relax%
+  \@ifnextchar[\@array{\@array[c]}%
+}
+%    \end{macrocode}
+%
+% \begin{macro}{\@array}
+%
+% The |\@array| macro does most of the real work for the environments.  The
+% first job is to set up the row strut, which keeps the table rows at the
+% right height.  We just take the normal strut box, and extend its height by
+% the |\extrarowheight| length parameter.
+%
+%    \begin{macrocode}
+\def\@array[#1]#2{%
+%    \end{macrocode}
+%
+% Sort out the hline state variable.  We'll store the old value in a
+% control sequence to avoid wasting any more count registers.
+%
+%    \begin{macrocode}
+  \edef\tab@restorehlstate{%
+    \global\tab@endheight\the\tab@endheight%
+    \gdef\noexpand\tab@hlstate{\tab@hlstate}%
+  }%
+  \def\tab@hlstate{n}%
+%    \end{macrocode}
+%
+% Now we read the preamble.  All the clever things we've already done are
+% terribly useful here.
+%
+% The |\tab@setcr| sets up |\\| to be a newline even if users have changed it
+% using something like |\raggedright|.
+%
+%    \begin{macrocode}
+  \colset{tabular}%
+  \tab@initread%
+  \def\tab@midtext{\tab@setcr\ignorespaces####\@maybe@unskip}%
+  \def\tab@multicol{\@arstrut\tab@startrow}%
+  \tab@preamble{\tab@multicol\tabskip\z@skip}%
+  \tab@readpreamble{#2}%
+%    \end{macrocode}
+%
+% Set up the default tabskip glue.  This is easy: there isn't any.
+%
+%    \begin{macrocode}
+  \tab@leftskip\z@skip%
+  \tab@rightskip\z@skip%
+%    \end{macrocode}
+%
+% Now set up the positioning of the table.  This is put into a separate macro
+% because it's rather complicated.
+%
+%    \begin{macrocode}
+  \tab@setposn{#1}%
+%    \end{macrocode}
+%
+% Now work out how to start the alignment.
+%
+%    \begin{macrocode}
+  \ifdim\tab@width=\z@%
+    \def\tab@halign{}%
+  \else%
+    \def\tab@halign{to\tab@width}%
+  \fi%
+%    \end{macrocode}
+%
+% Finally, do all the normal things we need to do before an alignment.  Note
+% that we define |\tabularnewline| first, then set |\\| from that (using
+% |\tab@setcr|).  Since |\\| is reset in the |\tab@midtext| of every table
+% cell, it becomes secondary to |\tabularnewline|.  Doing things this way
+% avoids the problems with declarations like |\raggedright| which redefine
+% |\\| in their own (usually rather strange) way, so you don't need to mess
+% about with things like the |\PreserveBackslash| command given in the
+% \textit{\LaTeX\ Companion}.
+%
+%    \begin{macrocode}
+  \lineskip\z@\baselineskip\z@%
+  \m@th%
+  \def\tabularnewline{\tab@arraycr\tab@penalty}%
+  \tab@setcr%
+  \let\par\@empty%
+  \everycr{}\tabskip\tab@leftskip%
+  \tab@left\halign\tab@halign\expandafter\bgroup%
+    \the\tab@preamble\tabskip\tab@rightskip\cr%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% You've no doubt noticed the |\tab@left| and |\tab@right| macros above.
+% These are set up here and elsewhere to allow other things to gain control
+% at various points of the table (they include and take the place of the
+% |\@arrayleft| and |\@arrayright| hooks in \package{array}, put in for
+% \package{delarray}'s use.
+%
+% \subsubsection{Positioning the table}
+%
+% \begin{macro}{\tab@setposn}
+%
+% This macro sets everything up for the table's positioning.  It's rather
+% long, but not all that complicated.  Honest.
+%
+% First, we set up some defaults (for centring).  If anything goes wrong, we
+% just do the centring things.
+%
+%    \begin{macrocode}
+\def\tab@setposn#1{%
+  \def\tab@left{%
+    \savenotes%
+    \leavevmode\hbox\bgroup$\@arrayleft\vcenter\bgroup%
+  }%
+  \def\tab@right{%
+    \egroup%
+    \m@th\@arrayright$\egroup%
+    \spewnotes%
+  }%
+  \global\tab@endheight\z@%
+%    \end{macrocode}
+%
+% For the standard positioning things, we just do appropriate boxing things.
+% Note that the dollar signs are important, since \package{delarray} might
+% want to put its delimiters in here.
+%
+% The |\if@tempswa| switch it used to decide if we're doing an unboxed
+% tabular.  We'll set it if we find an unbox-type position code, and then
+% check that everything's OK for this.
+%
+%    \begin{macrocode}
+  \@tempswafalse%
+  \let\tab@penalty\relax%
+  \if#1t%
+    \def\tab@left{%
+      \savenotes%
+      \leavevmode\setbox\z@\hbox\bgroup$\@arrayleft\vtop\bgroup%
+    }%
+    \def\tab@right{%
+      \egroup%
+      \m@th\@arrayright$\egroup%
+      \tab@raisebase%
+      \spewnotes%
+    }%
+    \gdef\tab@hlstate{t}%
+    \global\tab@endheight\ht\@arstrutbox%
+  \else\if#1b%
+    \def\tab@left{%
+      \savenotes%
+      \leavevmode\setbox\z@\hbox\bgroup$\@arrayleft\vbox\bgroup%
+    }%
+    \def\tab@right{%
+      \egroup%
+      \m@th\@arrayright$\egroup%
+      \tab@lowerbase%
+      \spewnotes%
+    }%
+    \gdef\tab@hlstate{b}%
+  \else%
+    \if#1L\@tempswatrue\fi%
+    \if#1C\@tempswatrue\fi%
+    \if#1R\@tempswatrue\fi%
+  \fi\fi%
+%    \end{macrocode}
+%
+% Now for some tests to make sure we're allowed to do the unboxing.  We text
+% for |\@arrayleft| being defined, because people trying to hook us won't
+% understand unboxed tabulars.
+%
+%    \begin{macrocode}
+  \if@tempswa\ifhmode%
+    \ifinner\tab@err@unbrh\@tempswafalse\else\par\fi%
+  \fi\fi%
+  \if@tempswa\ifmmode\tab@err@unbmm\@tempswafalse\fi\fi%
+  \if@tempswa\ifx\@arrayleft\relax\else%
+    \tab@err@unbext\@tempswafalse%
+  \fi\fi%
+%    \end{macrocode}
+%
+% Finally, if we're still doing an unboxed alignment, we need to sort out the
+% spacing.  We know that no-one's tried to hook on to the environment, so we
+% clear |\tab@left| and |\tab@right|.
+%
+%    \begin{macrocode}
+  \if@tempswa%
+    \def\tab@left{\vskip\parskip\medskip}%
+    \def\tab@right{\par\@endpetrue\global\@ignoretrue}%
+%    \end{macrocode}
+%
+% Now we need to sort out the alignment.  The only way we can do this is by
+% playing with tabskip glue.  There are two possibilities:
+%
+% \begin{itemize}
+%
+% \item If this is a straight \env{tabular} or an \env{array}, we just use
+%       infinite glue.  This is reasonable, I think.
+%
+% \item If we have a width for the table, we calculate the fixed values of
+%       glue on either side.  This is fairly easy, and forces the table to
+%       the required width.
+%
+% \end{itemize}
+%
+% First, set up the left and right glues to represent the prevailing
+% margins set up by \env{list} environments.  I think this is the right
+% thing to do.
+%
+%    \begin{macrocode}
+    \tab@leftskip\@totalleftmargin%
+    \tab@rightskip\hsize%
+    \advance\tab@rightskip-\linewidth%
+    \advance\tab@rightskip-\@totalleftmargin%
+%    \end{macrocode}
+%
+% First of all, deal with the simple case.  I'm using 10000\,fill glue here,
+% in an attempt to suppress |\extracolsep| glue from making the table the
+% wrong width.  It can always use filll glue if it really needs to, though.
+%
+%    \begin{macrocode}
+    \ifdim\tab@width=\z@%
+      \if#1L\else\advance\tab@leftskip\z@\@plus10000fill\fi%
+      \if#1R\else\advance\tab@rightskip\z@\@plus10000fill\fi%
+%    \end{macrocode}
+%
+% Now for the fun bit.  This isn't too hard really.  The extra space I must
+% add around the table adds up to $|\linewidth| - |\tab@width|$.  I just
+% need to add this onto the appropriate sides of the table.
+%
+%    \begin{macrocode}
+    \else%
+      \dimen@\linewidth%
+      \advance\dimen@-\tab@width%
+      \if#1L\advance\tab@rightskip\dimen@\fi%
+      \if#1R\advance\tab@leftskip\dimen@\fi%
+      \if#1C%
+        \advance\tab@leftskip.5\dimen@%
+        \advance\tab@rightskip.5\dimen@%
+      \fi%
+    \fi%
+%    \end{macrocode}
+%
+% Don't allow page breaks.  David Carlisle's wonderful \env{longtable}
+% package does page breaks far better than I could possibly do here, and
+% we're compatible with it (wahey!).
+%
+%    \begin{macrocode}
+    \def\tab@penalty{\penalty\@M}%
+%    \end{macrocode}
+%
+% Finally, set the new width of the table, and leave.
+%
+%    \begin{macrocode}
+    \tab@width\hsize%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Handling tops and bottoms}
+%
+% This is how the tops and bottoms of tables are made to line up with the
+% text on the same line, in the presence of arbitrary rules and space.  The
+% old method, based on the way the \package{array} package worked, wasn't
+% terribly good.  This new version copes much better with almost anything
+% that gets thrown at it.
+%
+% I'll keep a state in a macro (|\tab@hlstate|), which tells me what I'm
+% meant to be doing.  The possible values are \lit{n}, which means I don't
+% have to do anything, \lit{t}, which means that I'm meant to be handling
+% top-aligned tables, and \lit{b}, which means that I'm meant to be lining
+% up the bottom.  There are several other `substates' which have various
+% magic meanings.
+%
+%    \begin{macrocode}
+\def\tab@hlstate{n}
+%    \end{macrocode}
+%
+% When all's said and done, I extract the box containing the table, and
+% play with the height and depth to try and make it correct.
+%
+% \begin{macro}{\tab@addruleheight}
+%
+% This macro is called by `inter-row' things to add their height to our
+% dimen register.
+%
+% Only do this if the state indicates that it's sensible.
+%
+%    \begin{macrocode}
+\def\tab@addruleheight#1{%
+  \if\tab@hlstate n\else%
+    \global\advance\tab@endheight#1\relax%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@startrow}
+%
+% This is called at the start of a row, from within the array preamble.
+% Currently, this assumes that the rows aren't bigger than their struts:
+% this is reasonable, although slightly limiting, and it could be done better
+% if I was willing to rip the alignment apart and put it back together
+% again.
+%
+%    \begin{macrocode}
+\def\tab@startrow{%
+  \if\tab@hlstate t%
+    \gdef\tab@hlstate{n}%
+  \else\if\tab@hlstate b%
+    \global\tab@endheight\dp\@arstrutbox%
+  \fi\fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@raisebase}
+%
+% This macro is called at the end of it all, to set the height and depth
+% of the box correctly.  It sets the height to |\tab@endheight|, and the
+% depth to everything else.  The box is in |\box|~0 currently.
+%
+%    \begin{macrocode}
+\def\tab@raisebase{%
+  \global\advance\tab@endheight-\ht\z@%
+  \raise\tab@endheight\box\z@%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@lowerbase}
+%
+% And, for symmetry's sake, here's how to set the bottom properly instead.
+%
+%    \begin{macrocode}
+\def\tab@lowerbase{%
+  \global\advance\tab@endheight-\dp\z@%
+  \lower\tab@endheight\box\z@%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Breaking tables into bits}
+%
+% Unboxed tables have a wonderful advantage over boxed ones: you can stop
+% halfway through and do something else for a bit.  Here's how:
+%
+% \begin{macro}{\tabpause}
+%
+% I'd like to avoid forbidding catcode changes here.  I'll use |\doafter|
+% now I've got it, to ensure that colour handling and things occur
+% \emph{inside} the |\noalign| (otherwise they'll mess up the alignment
+% very seriously).  We selectively include lots of stuff from
+% |\arrayparboxrestore|.
+%
+% We have to be careful here to ensure that everything works correctly within
+% lists.  (The \package{amsmath} package had this problem in its
+% |\intertext| macro, so I'm not alone here.)
+%
+%    \begin{macrocode}
+\def\tabpause#{%
+  \noalign{\ifnum0=`}\fi%
+  \let\if@nobreak\iffalse
+  \let\if@noskipsec\iffalse
+  \let\par\@@par
+  \let\-\@dischyph
+  \let\'\@acci\let\`\@accii\let\=\@acciii
+  \everypar{}%
+  \lineskip\normallineskip%
+  \let\\\@normalcr%
+  \tab@startpause%
+  \vskip-\parskip%
+  \parshape\@ne\@totalleftmargin\linewidth%
+  \noindent%
+  \doafter\tabpause@i%
+}
+\def\tabpause@i{%
+  \nobreak%
+  \tab@endpause%
+  \ifnum0=`{\fi}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{The wonderful world of \cmd\multicolumn}
+%
+% \begin{macro}{\multicolumn}
+%
+% This is actually fantastically easy.  Watch and learn.  Make sure you
+% notice the |\long|s here: remember that some table cells can contain
+% paragraphs, so it seems sensible to allow |\par| into the argument.
+% (As far as I know, most other |\multicolumn| commands don't do this,
+% which seems a little silly.  Then again, I forgot to do it the first
+% time around.)
+%
+%    \begin{macrocode}
+\long\def\multicolumn#1#2#3{%
+  \multispan{#1}%
+  \begingroup%
+    \tab@multicol%
+    \tab@initread%
+    \tab@preamble{}%
+    \long\def\tab@midtext{#3}%
+    \let\tab@looped\tab@err@multi%
+    \tab@readpreamble{#2}%
+    \the\tab@preamble%
+  \endgroup%
+  \ignorespaces%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Interlude: range lists}
+%
+% For processing arguments to |\vgap| and |\cline|, we need to be able to
+% do things with lists of column ranges.  To save space, and to make my
+% fingers do less typing, here's some routines which do range handling.
+%
+% \begin{macro}{\ranges}
+%
+% Given a macro name and a comma separated list of ranges and simple numbers,
+% this macro will call the macro giving it each range in the list in turn.
+% Single numbers~$n$ will be turned into ranges $n$--$n$.
+%
+% The first job is to read the macro to do (which may already have some
+% arguments attached to it).  We'll also start a group to make sure that
+% our changes to temp registers don't affect anyone else.
+%
+% There's a space before the delimiting |\q@delim| to stop numbers being
+% parsed to far and expanding our quark (which will stop \TeX\ dead in its
+% tracks).  Since we use |\@ifnextchar| to look ahead, spaces in range lists
+% are perfectly all right.
+%
+%    \begin{macrocode}
+\def\ranges#1#2{%
+  \gdef\ranges@temp{#1}%
+  \begingroup%
+  \ranges@i#2 \q@delim%
+}
+%    \end{macrocode}
+%
+%
+% We're at the beginning of the list.  We expect either the closing marker
+% (if this is an empty list) or a number, which we can scoop up into a
+% scratch register.
+%
+%    \begin{macrocode}
+\def\ranges@i{%
+  \@ifnextchar\q@delim\ranges@done{\afterassignment\ranges@ii\count@}%
+}
+%    \end{macrocode}
+%
+% We've read the first number in the range.  If there's another number, we'll
+% expect a `|-|' sign to be next.  If there is no `|-|', call the user's code
+% with the number duplicated and then do the rest of the list.
+%
+%    \begin{macrocode}
+\def\ranges@ii{%
+  \@ifnextchar-\ranges@iii{\ranges@do\count@\count@\ranges@v}%
+}
+%    \end{macrocode}
+%
+% Now we strip the `|-|' off and read the other number into a temporary
+% register.
+%
+%    \begin{macrocode}
+\def\ranges@iii-{\afterassignment\ranges@iv\@tempcnta}
+%    \end{macrocode}
+%
+% We have both ends of the range now, so call the user's code, passing it
+% both ends of the range.
+%
+%    \begin{macrocode}
+\def\ranges@iv{\ranges@do\count@\@tempcnta\ranges@v}
+%    \end{macrocode}
+%
+% We've finished doing an item now.  If we have a `|,|' next, then start
+% over with the next item.  Otherwise, if we're at the end of the list,
+% we can end happily.  Finally, if we're totally confused, raise an
+% error.
+%
+%    \begin{macrocode}
+\def\ranges@v{%
+  \@ifnextchar,%
+    \ranges@vi%
+    {%
+      \@ifnextchar\q@delim%
+        \ranges@done%
+        {\tab@err@range\ranges@vi,}%
+    }%
+}
+%    \end{macrocode}
+%
+% We had a comma, so gobble it, read the next number, and go round again.
+%
+%    \begin{macrocode}
+\def\ranges@vi,{\afterassignment\ranges@ii\count@}
+%    \end{macrocode}
+%
+% Here's how we call the user's code, now.  We close the group, so that the
+% user's code doesn't have to do global things to remember its results, and
+% we expand the two range ends from their count registers.  We also ensure
+% that the range is the right way round.
+%
+%    \begin{macrocode}
+\def\ranges@do#1#2{%
+  \ifnum#1>#2\else%
+    \expandafter\endgroup%
+    \expandafter\ranges@temp%
+    \expandafter{%
+    \the\expandafter#1%
+    \expandafter}%
+    \expandafter{%
+    \the#2%
+    }%
+    \begingroup%
+  \fi%
+}
+%    \end{macrocode}
+%
+% And finishing the scan is really easy.  We close the group after gobbling
+% the close token.
+%
+%    \begin{macrocode}
+\def\ranges@done\q@delim{\endgroup}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\ifinrange}
+%
+% Something a little more useful, now.  |\ifinrange| takes four arguments:
+% a number, a range list (as above), and two token lists which I'll call
+% \emph{then} and \emph{else}.  If the number is in the list, I'll do
+% \emph{then}, otherwise I'll do \emph{else}.
+%
+%    \begin{macrocode}
+\def\ifinrange#1#2{%
+  \@tempswafalse%
+  \count@#1%
+  \ranges\ifinrange@i{#2}%
+  \if@tempswa%
+    \expandafter\@firstoftwo%
+  \else%
+    \expandafter\@secondoftwo%
+  \fi%
+}
+\def\ifinrange@i#1#2{%
+  \ifnum\count@<#1 \else\ifnum\count@>#2 \else\@tempswatrue\fi\fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Horizontal rules OK}
+%
+% This is where all the gubbins for |\vgap| and friends is kept, lest it
+% contaminate fairly clean bits of code found elsewhere.
+%
+% \subsubsection{Common parsing for vertical rule width twiddling}
+%
+% \begin{macro}{\tab@rulewd}
+%
+% Given a macro name, set |\tab@rulewidth| to be the chosen rule thickness
+% and call the macro.  We parse a `|*|' to mean |\arraythickrulewidth|, an
+% optional argument which should be something |\setlength| can understand, or
+% nothing, which gives the default |\arrayrulewidth|.
+%
+%    \begin{macrocode}
+\def\tab@rulewd#1{%
+  {\ifnum0=`}\fi\@ifstar{\tab@rulewd@star{#1}}{\tab@rulewd@what{#1}}%
+}
+\def\tab@rulewd@what#1{%
+  \@ifnextchar[{\tab@rulewd@opt{#1}}{\tab@rulewd@done\arrayrulewidth#1}%
+}
+\def\tab@rulewd@star#1{\tab@rulewd@done\arraythickrulewidth#1}
+\def\tab@rulewd@opt#1[#2]{\setlength\dimen@{#2}\tab@rulewd@done\dimen@#1}
+\def\tab@rulewd@done#1{\global\tab@rulewidth#1\ifnum0=`{\fi}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Drawing horizontal rules}
+%
+% \begin{macro}{\hline}
+%
+% Note the funny use of |\noalign| to allow \TeX\ stomach ops like
+% |\futurelet| without starting a new table row.  This lets us see if there's
+% another |\hline| coming up, so we can see if we need to insert extra
+% vertical space.
+%
+%    \begin{macrocode}
+\def\hline{\noalign\tab@rulewd\hline@prep}
+\def\hline@prep{%
+  \tab@dohline%
+  \noalign{\ifnum0=`}\fi%
+  \tab@penalty%
+  \futurelet\@let@token\hline@i%
+}
+%    \end{macrocode}
+%
+% We check here for another |\hline| command, and insert glue if there is.
+% This looks terrible, though, and |\hlx{hvh}| is much nicer.  Still\dots
+%
+%    \begin{macrocode}
+\def\hline@i{%
+  \@tempswafalse%
+  \ifx\@let@token\hline\@tempswatrue\fi%
+  \ifx\@let@token\hline@prep\@tempswatrue\fi%
+  \if@tempswa%
+    \vskip\doublerulesep%
+    \tab@addruleheight\doublerulesep%
+  \fi%
+  \ifnum0=`{\fi}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@dohline}
+%
+% This is where hlines actually get drawn.  
+% Drawing lines is more awkward than it used to be, particularly in unboxed
+% tables.  It used to be a case simply of saying |\noalign{\hrule}|.
+% However, since unboxed tables are actually much wider than they look, this
+% would make the rules stretch right across the page and look generally
+% horrible.
+%
+% The solution is simple: we basically do a dirty big |\cline|.
+%
+%    \begin{macrocode}
+\def\tab@dohline{%
+  \multispan{\tab@columns}%
+  \leaders\hrule\@height\tab@rulewidth\hfil%
+  \tab@addruleheight\arrayrulewidth%  
+  \cr%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Vertical rules}
+%
+% I couldn't fit these in anywhere else, so they'll have to go here.  I'll
+% provide a new optional argument which specifies the width of the rule; this
+% gets rid of the problem described in the \emph{Companion}, where to get
+% an unusually wide vertical rule, you have to play with things like
+% \syntax{"\\vrule width" <dimen>} which really isn't too nice.
+%
+% \begin{macro}{\vline}
+%
+% Now uses the general |\tab@rulewd| parser.
+%
+%    \begin{macrocode}
+\def\vline{%
+  \begingroup%
+  \dimen@\tab@rulewidth%
+  \tab@rulewd{%
+    \vrule\@width\tab@rulewidth%
+    \global\tab@rulewidth\dimen@%
+    \endgroup%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Drawing bits of lines}
+%
+% Just for a bit of fun, here's an extended version of |\cline| which takes
+% a list of columns to draw lines under, rather than just a single range.
+%
+% \begin{macro}{\cline}
+%
+% Not a single line of code written yet, and we already have a dilemma on
+% our hands.  Multiple consecutive |\cline| commands are meant to draw
+% on the same vertical bit of table.  But horizontal lines are meant to have
+% thickness now.  Oh, well [sigh], we'll skip back on it after all.
+%
+% Now the problem remains how best to do the job.  The way I see it, there
+% are three possibilities:
+%
+% \begin{itemize}
+%
+% \item We can start a table row, and then for each column of the table
+%       (as recorded in |\tab@columns|) we look to see if that column is
+%       listed in the range list and if so draw the rule.  This requires
+%       lots of scanning of the range list.
+%
+% \item We can take each range in the list, and draw rules appropriately,
+%       just like the old |\cline| used to do, and starting a new table row
+%       for each.
+%
+% \item We can start a table row, and then for each range remember where we
+%       stopped drawing the last row, move to the start of the new one, and
+%       draw it.  If we start moving backwards, we close the current row
+%       and open a new one.
+%
+% \end{itemize}
+%
+% The last option looks the most efficient, and the most difficult.  This
+% is therefore what I shall do |;-)|.
+%
+% The first thing to do is to add in a little negative space, and start a
+% table row (omitting the first item).  Then scan the range list, and finally
+% close the table row and add some negative space again.
+%
+% We need a global count register to keep track of where we are.  Mixing
+% local and global assignments causes all sorts of tragedy, so I shall hijack
+% |\tab@state|.
+%
+%    \begin{macrocode}
+\def\cline{\noalign\tab@rulewd\cline@prep}
+\def\cline@prep#1{%
+  \noalign{\kern-.5\tab@rulewidth\tab@penalty}%
+  \omit%
+  \global\tab@state\@ne%
+  \ranges\cline@i{#1}%
+  \cr%
+  \noalign{\kern-.5\tab@rulewidth\tab@penalty}%
+}
+%    \end{macrocode}
+%
+% Now for the tricky bit.  When we're given a range, we look to see if the
+% first number is less than |\tab@state|.  If so, we quickly close the
+% current row, kern backwards and start again with an |\omit| and reset
+% |\tab@state| to 1, and try again.
+%
+%    \begin{macrocode}
+\def\cline@i#1#2{%
+  \ifnum#1<\tab@state\relax%
+    \tab@@cr%
+    \noalign{\kern-\tab@rulewidth\tab@penalty}%
+    \omit%
+    \global\tab@state\@ne%
+  \fi%
+%    \end{macrocode}
+%
+% We are now either at or in front of the column position required.  If
+% we're too far back, we must |\hfil&\omit| our way over to the correct%
+% column.
+%
+%    \begin{macrocode}
+  \@whilenum\tab@state<#1\do{%
+    \hfil\tab@@tab@omit%
+    \global\advance\tab@state\@ne%
+  }%
+%    \end{macrocode}
+%
+% We've found the start correctly.  We must deal with a tiny problem now:
+% if this is not the first table cell, the left hand vertical rule is in the
+% column to the left, so our horizontal rule won't match up properly.  So
+% we skip back by a bit to compensate.  If there isn't actually a vertical
+% rule to line up with, no-one will notice, because the rules are so thin.
+% This adds a little touch of quality to the whole thing, which is after all
+% the point of this whole exercise.
+%
+%    \begin{macrocode}
+  \ifnum\tab@state>\@ne%
+    \kern-\arrayrulewidth%
+  \fi%
+%    \end{macrocode}
+%
+% Now we must stretch this table cell to the correct width.
+%
+%    \begin{macrocode}
+  \@whilenum\tab@state<#2\do{%
+    \tab@@span@omit%
+    \global\advance\tab@state\@ne%
+  }%
+%    \end{macrocode}
+%
+% We're ready.  Draw the rule.  Note that this is |\hfill| glue, just in case
+% we start putting in |\hfil| glue when we step onto the next cell.
+%
+%    \begin{macrocode}
+  \leaders\hrule\@height\tab@rulewidth\hfill%
+}
+%    \end{macrocode}
+%
+% Some alignment primitives are hidden inside macros so they don't get seen
+% at the wrong time.  This is what they look like:
+%
+%    \begin{macrocode}
+\def\tab@@cr{\cr}
+\def\tab@@tab@omit{&\omit}
+\def\tab@@span@omit{\span\omit}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Drawing short table rows}
+%
+% Before I start on a description of more code, I think I'll briefly discuss
+% my reasons for leaving the |\vgap| command in its current state.  There's a
+% reasonable case for introducing an interface between |\vgap| and
+% |\multicolumn|, to avoid all the tedious messing about with column
+% ranges.  There are good reasons why I'm not going to do this:
+%
+% \begin{itemize}
+%
+% \item It's very difficult to do: it requires either postprocessing of
+%       the table or delaying processing of each row until I know exactly
+%       what's in it; a |\multicolumn| in a row should be able to affect
+%       a |\vgap| before the row, which gets very nasty.  This package is
+%       probably far too large already, and adding more complexity and
+%       running the risk of exhausting \TeX's frustratingly finite capacity
+%       for the sake of relieving the user of a fairly trivial job doesn't
+%       seem worthwhile.
+%
+% \item Perhaps more importantly, there are perfectly valid occasions when
+%       it's useful to have the current vgap behaviour.  For example, the
+%       \texttt{MIX} word layout diagrams found in \emph{The Art of
+%       Computer Programming} use the little `stub lines' to show where
+%       data items cross byte boundaries:
+%
+%	^^A This actually looks terrifyingly similar to the original.
+%	^^A The leading @{} is there to stop the table looking off-centre,
+%	^^A because there's no left hand rule telling you where the table
+%	^^A starts, like there is on the right, just the \tabcolsep glue.
+%
+%	\begingroup
+%	\newcommand{\wide}[2]{\multicolumn{#1}{c|}{\ttfamily #2}}
+%	\begin{tabular}[C]{@{} r @{\qquad} | Mc | *{5}{c|}} \hlx{c{2-7} v}
+%          empty & - & 1 & 0 & 0 & 0 & 0		\\ \hlx{v c{2-7} v}
+%	occupied & + & \wide{2}{LINK} & \wide{3}{KEY}	\\ \hlx{v c{2-7}}
+%	\end{tabular}
+%	\endgroup
+%
+% \end{itemize}
+%
+% That's my excuses out of the way; now I'll press on with the actual
+% programming.
+%
+% \begin{macro}{\tab@checkrule}
+%
+% We have a range list in |\tab@xcols| and a number as an argument.  If we
+% find the number in the list, we just space out the following group,
+% otherwise we let it be.
+%
+%    \begin{macrocode}
+\def\tab@checkrule#1{%
+  \count@#1\relax%
+  \expandafter\ifinrange%
+  \expandafter\count@%
+  \expandafter{\tab@xcols}%
+    {\tab@checkrule@i}%
+    {}%
+}
+\def\tab@checkrule@i#1{\setbox\z@\hbox{#1}\hb@xt@\wd\z@{}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\vgap}
+%
+% We must tread carefully here.  A single misplaced stomach operation can
+% cause error messages.  We therefore start with an |\omit| so we can search
+% for optional arguments.
+%
+% So that |\hlx| can get control after |\vgap| has finished, we provide a
+% hook called |\vgap@after| which is expanded after |\vgap| has finished.
+% Here we make it work like |\@empty|, which expands to nothing.  (Note that
+% |\relax| will start a new table row, so we can't use that.)  There are
+% some penalty items here to stick the |\vgap| row to the text row and
+% |\hline| that are adjacent to it.  The \package{longtable} package will
+% split an |\hline| in half, so this is the correct thing to do.
+%
+%    \begin{macrocode}
+\def\vgap{%
+  \noalign{\nobreak}%
+  \omit%
+  \global\let\vgap@after\@empty%
+  \iffalse{\fi\ifnum0=`}\fi%
+  \@ifnextchar[\vgap@i\vgap@simple%
+}
+%    \end{macrocode}
+%
+% We set up two different sorts of |\vgap| -- a simple one which allows all
+% rules to be passed through, and a specific one which carefully vets each
+% one (and is therefore slower).  We decide which to so based on the presence
+% of an optional argument.
+%
+% The optional argument handler just passes its argument to an interface
+% routine which is used by |\hlx|.
+%
+%    \begin{macrocode}
+\def\vgap@i[#1]{\vgap@spec{#1}}
+%    \end{macrocode}
+%
+% Now we handle specified columns.  Since we're in an omitted table cell, we
+% must set things up globally.  Assign the column spec to a macro, and set up
+% vetting by the routine above.  Then just go and do the job.
+%
+%    \begin{macrocode}
+\def\vgap@spec#1#2{%
+  \gdef\tab@xcols{#1}%
+  \global\let\tab@ckr\tab@checkrule%
+  \vgap@do{#2}%
+}
+%    \end{macrocode}
+%
+% Handle all columns.  Just gobble the column number for each rule, and let
+% the drawing pass unharmed.  Easy.
+%
+%    \begin{macrocode}
+\def\vgap@simple#1{%
+  \global\let\tab@ckr\@gobble%
+  \vgap@do{#1}%
+}
+%    \end{macrocode}
+%
+% This is where stuff actually gets done.  We set the |\vgap| flag on while
+% we do the short row.  Then just expand the token list we built while
+% scanning the preamble.
+%
+% Note that the flag is cleared at the end of the last column, to allow other
+% funny things like |\noalign| and |\omit| before a new row is started.
+%
+%    \begin{macrocode}
+\def\vgap@do#1{%
+  \ifnum0=`{}\fi%
+  \global\tab@vgaptrue%
+  \the\tab@shortline%
+    \vrule\@height#1\@width\z@%
+    \global\tab@vgapfalse
+    \tab@addruleheight{#1}%
+    \cr%
+  \noalign{\nobreak}%
+  \vgap@after%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Prettifying syntax}
+%
+% \begin{macro}{\hlx}
+%
+% This is like a poor cousin to the preamble parser.  The whole loop is
+% carefully written to take place \emph{only} in \TeX's mouth, so the
+% alignment handling bits half way down the gullet don't see any of this.
+%
+% First, pass the string to another routine.
+%
+%    \begin{macrocode}
+\def\hlx{\noalign\tab@rulewd\hlx@prep}
+\def\hlx@prep#1{\hlx@loop#1\q@delim}
+%    \end{macrocode}
+%
+% Now peel off a token, and dispatch using |\csname|.  We handle
+% undefinedness of the command in a fairly messy way, although it probably
+% works.  Maybe.
+%
+%    \begin{macrocode}
+\def\hlx@loop#1{%
+  \ifx#1\q@delim\else%
+    \@ifundefined{hlx@cmd@\string#1}{%
+      \expandafter\hlx@loop%
+    }{%
+      \csname hlx@cmd@\string#1\expandafter\endcsname%
+    }%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\hlxdef}
+%
+% New |\hlx| commands can be defined using |\hlxdef|.  This is a simple
+% abbreviation.
+%
+%    \begin{macrocode}
+\def\hlxdef#1{\@namedef{hlx@cmd@#1}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\hlx h}
+%
+% Handle an \lit{h} character.  Just do an |\hline| and return to the loop.
+% We look ahead to see if there's another \lit{h} coming up, and if so
+% insert two |\hline| commands.  This strange (and inefficient) behaviour
+% keeps packages which redefine |\hline| happy.
+%
+%    \begin{macrocode}
+\hlxdef h#1{%
+  \noalign{%
+    \ifx#1h%
+      \def\@tempa{\hline@prep\hline@prep\hlx@loop}%
+    \else%
+      \def\@tempa{\hline@prep\hlx@loop#1}%
+    \fi%
+    \expandafter
+  }%
+  \@tempa%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\hlx b}
+%
+% The \lit{b} character does a nifty backspace, for \package{longtable}'s
+% benefit.
+%
+%    \begin{macrocode}
+\hlxdef b{\noalign{\kern-\arrayrulewidth}\hlx@loop}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\hlx /}
+%
+% The `"/"' character allows a page break at the current position.
+%
+%    \begin{macrocode}
+\hlxdef /{%
+  \noalign{\ifnum0=`}\fi%
+  \@ifnextchar[\hlx@cmd@break@i{\hlx@cmd@break@i[0]}%
+}
+\def\hlx@cmd@break@i[#1]{\ifnum0=`{\fi}\pagebreak[0]\hlx@loop}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\hlx v}
+%
+% Handle a \lit{v} character.  This is rather like the |\vgap| code above,
+% although there are syntactic differences.
+%
+%    \begin{macrocode}
+\hlxdef v{%
+  \noalign{\nobreak}%
+  \omit%
+  \iffalse{\fi\ifnum0=`}\fi%
+  \global\let\vgap@after\hlx@loop%
+  \@ifnextchar[\hlx@vgap@i{\hlx@vgap@ii\vgap@simple}%
+}
+\def\hlx@vgap@i[#1]{%
+  \ifx!#1!%
+    \def\@tempa{\hlx@vgap@ii\vgap@simple}%
+  \else%
+    \def\@tempa{\hlx@vgap@ii{\vgap@spec{#1}}}%
+  \fi%
+  \@tempa%
+}
+\def\hlx@vgap@ii#1{%
+  \@ifnextchar[{\hlx@vgap@iii{#1}}{\hlx@vgap@iii{#1}[\doublerulesep]}%
+}
+\def\hlx@vgap@iii#1[#2]{#1{#2}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\hlx s}
+%
+% Allow the user to leave a small gap using the \lit{s} command.
+%
+%    \begin{macrocode}
+\hlxdef s{%
+  \noalign{\ifnum0=`}\fi%
+  \nobreak%
+  \@ifnextchar[\hlx@space@i{\hlx@space@i[\doublerulesep]}%
+}
+\def\hlx@space@i[#1]{%
+  \vskip#1%
+  \tab@addruleheight{#1}%
+  \ifnum0=`{\fi}%
+  \hlx@loop%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\hlx c}
+%
+% We might as well allow a \lit{c} command to do a |\cline|.
+%
+%    \begin{macrocode}
+\hlxdef c#1{\cline@prep{#1}\hlx@loop}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\hlx .}
+%
+% The \lit{.} character forces a start of the new column.  There's a little
+% problem here.  Since the \lit{.} character starts the next column, we need
+% to gobble any spaces following the |\hlx| command before the cell contents
+% actually starts.  Unfortunately, |\ignorespaces| will start the column for
+% us, so we can't put it in always.  We'll handle it here, then.  We'll take
+% the rest of the `preamble' string, and warn if it's not empty.  Then we'll
+% |\ignorespaces| -- this will start the column for us, so we don't need to
+% |\relax| any more.
+%
+%    \begin{macrocode}
+\hlxdef .#1\q@delim{%
+  \ifx @#1@\else%
+    \PackageWarning{mdwtab}{%
+      Ignoring \protect\hlx\space command characters following a
+      `.'\MessageBreak command%
+    }%
+  \fi%
+  \ignorespaces%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Starting new table rows}
+%
+% We take a break from careful mouthery at last, and start playing with
+% newlines.  The standard one allows pagebreaks in unboxed tables, which
+% isn't really too desirable.
+%
+% Anyway, we'll try to make this macro rather more reusable than the standard
+% one.  Here goes.
+%
+% \begin{macro}{\@arraycr}
+%
+% We pass lots of information to a main parser macro, and expect it to cope.
+%
+%    \begin{macrocode}
+\def\@arraycr{\tab@arraycr{}}
+\def\tab@arraycr#1{\tab@cr{\tab@tabcr{#1}}{}{}}
+%    \end{macrocode}
+%
+% Now to actually do the work.  |\tab@cr| passes us the skip size, and the
+% appropriate one of the two arguments given above (both of which are empty)
+% depending on the presence of the $*$.
+%
+%    \begin{macrocode}
+\def\tab@tabcr#1#2{%
+%    \end{macrocode}
+%
+% If the total height I need to add between rows (from the optional argument
+% and the `extrasep' parameter) is greater than zero, I'll handle this by
+% extending the strut slightly.  I'm not actually sure whether this is the
+% right thing to do, to be honest, although it's easier than trying to
+% to an automatic |\vgap|, because I need to know which columns to skip.
+% If the space is less than zero, I'll just insert the vertical space with
+% in a |\noalign|.
+%
+% First, to calculate how much space needs adding.
+%
+%    \begin{macrocode}
+  \setlength\dimen@{#2}%
+  \advance\dimen@\tab@extrasep%
+%    \end{macrocode}
+%
+% If the height is greater than zero, I need to play with the strut.  I must
+% bear in mind that the current table cell (which I'm still in, remember)
+% may be in vertical mode, and I may or may not be in a paragraph.
+%
+% If I am in vertical mode, I'll backpedal to the previous box and put the
+% strut in an hbox superimposed on the previous baseline.  Otherwise, I can
+% just put the strut at the end of the text.  (This works in either LR
+% or paragraph mode as long as I'm not between paragraphs.)  Again, Rowland's
+% empty cell bug strikes.  (See |\tab@epar| for details.)
+%
+%    \begin{macrocode}
+  \ifdim\dimen@>\z@%
+    \ifvmode%
+      \unskip\ifdim\prevdepth>-\@m\p@\kern-\prevdepth\fi%
+      \nointerlineskip\expandafter\hbox%
+    \else%
+      \@maybe@unskip\expandafter\@firstofone%
+    \fi%
+    {\advance\dimen@\dp\@arstrutbox\vrule\@depth\dimen@\@width\z@}%
+  \fi%
+%    \end{macrocode}
+%
+% This table cell works as a group (which is annoying here).  I'll copy the
+% interrow gap into a global register so that I can use it in the |\noalign|.
+%
+%    \begin{macrocode}
+  \global\dimen\@ne\dimen@%
+  \cr%
+  \noalign{%
+    #1%
+    \ifdim\dimen\@ne<\z@\vskip\dimen\@ne\relax\fi%
+  }%
+  \@gobble%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@setcr}
+%
+% To set the |\\| command correctly in each table cell, we make it a part of
+% the preamble (in |\tab@midtext|) to call this routine.  It's easy -- just
+% saves the preamble from being huge.
+%
+%    \begin{macrocode}
+\def\tab@setcr{\let\\\tabularnewline}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tab@cr}
+%
+% Now we do the parsing work.  This is fun.  Note the revenge of the funny
+% braces here.  Nothing to worry about, honest.  The tricky bit is to keep
+% track of which arguments are which.  (Thanks to David Carlisle for pointing
+% out that I'd missed out the |\relax| here.)
+%
+%    \begin{macrocode}
+\def\tab@cr#1#2#3{%
+  \relax%
+  \iffalse{\fi\ifnum0=`}\fi%
+  \@ifstar{\tab@cr@i{#1}{#3}}{\tab@cr@i{#1}{#2}}%
+}
+\def\tab@cr@i#1#2{%
+  \@ifnextchar[{\tab@cr@ii{#1}{#2}}{\tab@cr@ii{#1}{#2}[\z@]}%
+}
+\def\tab@cr@ii#1#2[#3]{%
+  \ifnum0=`{}\fi%
+  #1{#3}{#2}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Gratuitous grotesquery}
+%
+% So far we've had an easy-ish ride (or should that be \emph{queasy}?).  Now
+% for something unexplainably evil.  We convince \LaTeX\ that it's loaded the
+% \package{array} package, so that packages which need it think they've got
+% it.
+%
+% The bogus date is the same as the date for the \package{array} package I've
+% got here -- this will raise a warning if Frank updates his package which
+% should filter back to me telling me that there's something I need to
+% know about.
+%
+% The messing with |\xdef| and the funny parsing ought to insert the current
+% \package{mdwtab} version and date into the fake \package{array} version
+% string, giving a visible clue to the user that this isn't the real
+% \package{array} package.
+%
+%    \begin{macrocode}
+\begingroup
+\catcode`.=11
+\def\@tempa#1 #2 #3\@@{#1 #2}
+\xdef\ver@array.sty
+  {1995/11/19 [mdwtab.sty \expandafter\@tempa\ver@mdwtab.sty\@@]}
+\endgroup
+%    \end{macrocode}
+%
+%
+% \subsection{Error messages}
+%
+% I've put all the error messages together, where I can find them, translate
+% them or whatever.
+%
+% First, some token-space saving (which also saves my fingers):
+%
+%    \begin{macrocode}
+\def\tab@error{\PackageError{mdwtab}}
+%    \end{macrocode}
+%
+% Now do the error messages.
+%
+%    \begin{macrocode}
+\def\tab@err@misscol{%
+  \tab@error{Missing column type}{%
+    I'm lost.  I was expecting something describing^^J%
+    the type of the current column, but you seem to^^J%
+    have missed it out.  I've inserted a type `l'^^J%
+    column here in the hope that this makes sense.%
+  }%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\tab@err@oddgroup{%
+  \tab@error{Misplaced group in table preamble}{%
+    I've found an open brace character in your preamble^^J%
+    when I was expecting a specifier character.  I'm^^J%
+    going to gobble the whole group and carry on as if^^J%
+    I'd never seen it.%
+  }%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\tab@err@undef#1{%
+  \tab@error{Unknown `\tab@colset' preamble character `\string#1'}{%
+    I don't understand what you meant by typing this^^J%
+    character.  Anyway, I'll ignore it this time around.^^J%
+    Just don't you do it again.%
+  }%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\tab@err@unbrh{%
+  \tab@error{Can't use unboxed tabular in LR mode}{%
+    You've asked for a tabular or array environment with^^J%
+    `L', `C' or `R' as the position specifier, but you're^^J%
+    in LR (restricted horizontal) mode, so it won't work.^^J%
+    I'll assume you really meant `c' and soldier on.%
+  }%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\tab@err@unbmm{%
+  \tab@error{Can't use unboxed tabular in maths mode}{%
+    You've asked for a tabular or array environment with^^J%
+    `L', `C' or `R' as the position specifier, but you're^^J%
+    in maths mode, so it won't work.  I'll pretend that^^J%
+    you really typed `c', and that this is all a bad dream.%
+  }%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\tab@err@unbext{%
+  \tab@error{Can't extend unboxed tabulars}{%
+    You're trying to use kludgy extensions (e.g.,^^J%
+    `delarray') on an array or tabular with `L', `C'^^J%
+    or `R' as the position specifier.  I'll assume you^^J%
+    subconsciously wanted a `c' type all along.%
+  }%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\tab@err@multi{%
+  \tab@error{More than one column in a \protect\multicolumn}{%
+    You've put more than one column into a \string\multicolumn^^J%
+    descriptor.  It won't work.  I have no idea what^^J%
+    will happen, although it won't be pleasant.  Hold^^J%
+    on tight now...%
+  }%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\tab@err@range{%
+  \tab@error{Expected `,' or `<end>' in range list}{%
+    I was expecting either the end of the range list,^^J%
+    or a comma, followed by another range.  I've^^J%
+    inserted a comma to try and get me back on track.^^J%
+    Good luck.%
+  }%
+}
+%    \end{macrocode}
+%
+% That's it.  No more.  Move along please.
+%
+%    \begin{macrocode}
+%</mdwtab>
+%    \end{macrocode}
+%
+%
+%^^A-------------------------------------------------------------------------
+% \section{Implementation of \package{mathenv}}
+%
+%
+% This is in a separate package, mainly to avoid wasting people's memory.
+%
+%    \begin{macrocode}
+%<*mathenv>
+%    \end{macrocode}
+%
+%
+% \subsection{Options handling}
+%
+% We need to be able to cope with \textsf{fleqn} and \textsf{leqno} options.
+% This will adjust our magic modified \env{eqnarray} environment
+% appropriately.
+%
+%    \begin{macrocode}
+\newif\if@fleqn
+\newif\if@leqno
+\DeclareOption{fleqn}{\@fleqntrue}
+\DeclareOption{leqno}{\@leqnotrue}
+\ProcessOptions
+%    \end{macrocode}
+%
+% We use the \package{mdwtab} package for all its nice table handling things.
+% (Oh, and to inflict it on users who want to do nice equations and don't
+% care about our tables.)
+%
+%    \begin{macrocode}
+\RequirePackage{mdwtab}
+%    \end{macrocode}
+%
+%
+% \subsection{Some useful registers}
+%
+% The old \LaTeX\ version puts the equation numbers in by keeping a count of
+% where it is in the alignment.  Since I don't know how may columns there are
+% going to be, I'll just use a switch in the preamble to tell me to stop
+% tabbing.
+%
+%    \begin{macrocode}
+\newif\if@eqalast
+%    \end{macrocode}
+%
+% Now define some useful length parameters.  First allocate them:
+%
+%    \begin{macrocode}
+\newskip\eqaopenskip
+\newskip\eqacloseskip
+\newskip\eqacolskip
+\newskip\eqainskip
+\newskip\splitleft
+\newskip\splitright
+%    \end{macrocode}
+%
+% Now assign some default values.  Users can play with these if they really
+% want although I can't see the point myself.
+%
+%    \begin{macrocode}
+\AtBeginDocument{%
+  \eqacloseskip\@centering%
+  \eqacolskip1.5em\@plus\@m\p@
+  \eqainskip\z@%
+  \if@fleqn%
+    \eqaopenskip\mathindent%
+    \splitleft\mathindent\relax%
+    \splitright\mathindent\@minus\mathindent\relax%  
+  \else%
+    \eqaopenskip\@centering%
+    \splitleft2.5em\@minus2.5em%
+    \splitright\splitleft%
+  \fi%
+  \relax%
+}
+%    \end{macrocode}
+%
+%
+% \subsection{A little display handling}
+%
+% I'm probably going a little far here, and invading territory already
+% claimed by the \package{amsmath} stuff (and done a good deal better than
+% I can be bothered to do), but just for completeness, this is how we handle
+% attempts to put displays inside other displays without screwing up the
+% spacing.
+%
+% \begin{macro}{\dsp@startouter}
+%
+% This is how we start an outermost display.  It's fairly easy really.  We
+% make |\dsp@start| start an inner display, and make |\dsp@end| close the
+% outer display.
+%
+%    \begin{macrocode}
+\def\dsp@startouter{%
+  \let\dsp@end\dsp@endouter%
+  $$%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\dsp@endouter}
+%
+% Ending the outer display is utterly trivial.
+%
+%    \begin{macrocode}
+\def\dsp@endouter{$$}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\dsp@startinner}
+%
+% Starting inner displays is done in a vbox (actually I choose |\vbox| or
+% |\vtop| depending on the setting of \textsf{leqno} to put the equation
+% number the right way round).
+%
+%    \begin{macrocode}
+\def\dsp@startinner{%
+  \let\dsp@end\dsp@endinner%
+  \if@fleqn\kern-\mathindent\fi%
+  \if@leqno\vtop\else\vtop\fi\bgroup%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\dsp@endinner}
+%
+% Ending an inner display is also really easy.
+%
+%    \begin{macrocode}
+\def\dsp@endinner{\egroup}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\dsp@start}
+%
+% This is what other bits of code uses to start displays.  It's one of the
+% start macros up above, and outer by default.
+%
+%    \begin{macrocode}
+\def\dsp@start{%
+  \ifmmode%
+    %\ifinner\mth@err@mdsp\fi%
+    \expandafter\dsp@startinner%
+  \else%
+    \ifhmode\ifinner\mth@err@hdsp\fi\fi%
+    \expandafter\dsp@startouter%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\dsp@tabpause}
+%
+% This sets up the correct pre- and postambles for the |\tabpause| macro in
+% maths displays.  This is fairly simple stuff.
+%
+%    \begin{macrocode}
+\def\dsp@tabpause{%
+  \def\tab@startpause%
+    {\penalty\postdisplaypenalty\vskip\belowdisplayskip}%
+  \def\tab@endpause%
+    {\penalty\predisplaypenalty\vskip\abovedisplayskip}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{The \env{eqnarray} environment}
+%
+% We allow the user to play with the style if this is really wanted.  I dunno
+% why, really.  Maybe someone wants very small alignments.
+%
+%    \begin{macrocode}
+\let\eqastyle\displaystyle
+%    \end{macrocode}
+%
+% \subsubsection{The main environments}
+%
+% \begin{environment}{eqnarray}
+% \begin{environment}{eqnarray*}
+%
+% We define the toplevel commands here.  They just add in default arguments
+% and then call |\@eqnarray| with a preamble string.  We handle equation
+% numbers by setting up a default (|\eqa@defnumber|) which is put into
+% the final column.  At the beginning of each row, we globally |\let|
+% |\eqa@number| equal to |\eqa@defnumber|.  The |\eqnumber| macro just
+% changes |\eqa@number| as required.  Since |\eqa@number| is changed globally
+% we must save it in this environment.
+%
+% First, we must sort out the optional arguments and things.  This is really
+% easy.  The only difference between the starred and non-starred environments
+% is the default definition of |\eqa@defnumber|.
+%
+%    \begin{macrocode}
+\def\eqnarray{%
+  \eqnarray@i\eqa@eqcount%
+}
+\@namedef{eqnarray*}{\eqnarray@i{}}
+\def\eqnarray@i#1{\@ifnextchar[{\eqnarray@ii{#1}}{\eqnarray@ii{#1}[rcl]}}
+%    \end{macrocode}
+%
+% Right.  Now for the real work.  The first argument is the default numbering
+% tokens; the second is the preamble string.
+%
+%    \begin{macrocode}
+\def\eqnarray@ii#1[#2]{%
+%    \end{macrocode}
+%
+% Set up the equation counter and labels correctly.
+%
+% \medskip\par\noindent|\begin{rant}|\par
+% The hacking with |\@currentlabel| is here because (in the author's opinion)
+% \LaTeX's |\refstepcounter| macro is broken.  It's currently defined as
+% \begin{listing}
+%\def\refstepcounter#1{%
+%  \stepcounter{#1}%
+%  \protected@edef\@currentlabel%
+%    {\csname p@#1\endcsname\csname the#1\endcsname}%
+%}
+% \end{listing}
+% which means that the current label gets `frozen' as soon as you do the
+% counter step.  By redefining the macro as
+% \begin{listing}
+%\def\refstepcounter#1{%
+%  \stepcounter{#1}%
+%  \edef\@currentlabel{%
+%    \expandafter\noexpand\csname p@#1\endcsname%
+%    \expandafter\noexpand\csname the#1\endcsname%
+%  }%
+%}
+% \end{listing}
+% these sorts of problems would be avoided, without any loss of functionality
+% or compatibility that I can see.
+% \par\noindent|\end{rant}|\par
+%
+%    \begin{macrocode}
+  \stepcounter{equation}%
+  \def\@currentlabel{\p@equation\theequation}%
+%    \end{macrocode}
+%
+% The next step is to set up the numbering.  I must save the old numbering
+% so I can restore it later (once in the alignment, I must assign these
+% things globally).
+%
+%    \begin{macrocode}
+  \let\eqa@oldnumber\eqa@number%
+  \def\eqa@defnumber{#1}%
+  \global\let\eqa@number\eqa@defnumber%
+%    \end{macrocode}
+%
+% The |\if@eqalastfalse| switch is false everywhere except when we're in the
+% final column.
+%
+%    \begin{macrocode}
+  \@eqalastfalse%
+%    \end{macrocode}
+%
+% Remove the |\mathsurround| kerning, since it will look very odd inside
+% the display.  We have our own spacing parameters for configuring these
+% things, so |\mathsurround| is unnecessary.
+%
+%    \begin{macrocode}
+  \m@th%
+%    \end{macrocode}
+%
+% Time to parse the preamble string now.  I must choose the correct column
+% set, initialise the preamble parser and set up the various macros.  The%
+% extra `|@{\tabskip\eqacloseskip}|' item sets up the tabskip glue to centre
+% the alignment properly.
+%
+%    \begin{macrocode}
+  \colset{eqnarray}%
+  \tab@initread%
+  \def\tab@tabtext{&\tabskip\z@skip}%
+  \tab@preamble{\tabskip\z@skip}%
+  \tab@readpreamble{#2@{\tabskip\eqacloseskip}}%
+  \dsp@tabpause%
+%    \end{macrocode}
+%
+% Now for some final setting up.  The column separation is set from the
+% user's parameter, the |\everycr| tokens are cleared, and I set up the
+% newline command appropriately.
+%
+%    \begin{macrocode}
+  \col@sep.5\eqainskip%
+  \everycr{}%
+  \let\\\@eqncr%
+%    \end{macrocode}
+%
+% Now start a maths display and do the alignment.  Set up the left hand
+% tabskip glue to centre the alignment, and do the actual alignment.
+% The preamble used is mainly that generated from the user's string, although
+% the stuff at the end is how we set up the equation number -- it repeats
+% appropriately so we can always find it.
+%
+%    \begin{macrocode}
+  \dsp@start%
+  \tabskip\eqaopenskip%
+  \halign to\displaywidth\expandafter\bgroup%
+    \the\tab@preamble%
+    &&\eqa@lastcol\hb@xt@\z@{\hss##}\tabskip\z@\cr%
+}
+%    \end{macrocode}
+%
+% Now for the end of the environment.  This is really easy.  Set the final
+% equation number, close the |\halign|, tidy up the equation counter (it's
+% been stepped once too many times) and close the display.
+%
+%    \begin{macrocode}
+\def\endeqnarray{%
+  \eqa@eqnum%
+  \egroup%
+  \dsp@end%
+  \global\let\eqa@number\eqa@oldnumber%
+  \global\@ignoretrue%
+  \global\advance\c@equation\m@ne%
+}
+\expandafter\let\csname endeqnarray*\endcsname\endeqnarray
+%    \end{macrocode}
+%
+% \end{environment}
+% \end{environment}
+%
+% Now we can define the column types. 
+%
+%    \begin{macrocode}
+\colpush{eqnarray}
+%    \end{macrocode}
+%
+% Note the positioning of ord atoms in the stuff below.  This will space out
+% relations and binops correctly when they occur at the edges of columns, and
+% won't affect ord atoms at the edges, because ords pack closely.
+%
+% First the easy ones.  Just stick |\hfil| in the right places and
+% everything will be all right.
+%
+%    \begin{macrocode}
+\coldef r{\tabcoltype{\hfil$\eqastyle}{{}$}}
+\coldef c{\tabcoltype{\hfil$\eqastyle{}}{{}$\hfil}}
+\coldef l{\tabcoltype{$\eqastyle{}}{$\hfil}}
+\coldef x{\tabcoltype{\if@fleqn\else\hfil\fi$\eqastyle}{$\hfil}}
+%    \end{macrocode}
+%
+% Now for the textual ones.  This is also fairly easy.
+%
+%    \begin{macrocode}
+\collet T [tabular]T
+%    \end{macrocode}
+%
+% Sort of split types of equations.  I mustn't use |\rlap| here, or
+% everything goes wrong -- |\\| doesn't get noticed by \TeX\ in the same way
+% as |\cr| does.
+%
+%    \begin{macrocode}
+\coldef L{\tabcoltype{\hb@xt@2em\bgroup$\eqastyle}{$\hss\egroup}}
+%    \end{macrocode}
+%
+% The \lit{:} column type is fairly simple.
+%
+%    \begin{macrocode}
+\coldef :{\tabspctype{\tabskip\eqacolskip}}
+\coldef q{\tabspctype{\quad}}
+%    \end{macrocode}
+%
+% The other column types just insert given text in an appropriate way.
+%
+%    \begin{macrocode}
+\collet > [tabular]>
+\collet < [tabular]<
+\collet * [tabular]*
+\collet @ [tabular]@
+%    \end{macrocode}
+%
+% Finally, the magical `|\magic|' column type, which sets the equation
+% number.  We set up the |\tabskip| glue properly, tab on, and set the flag
+% which marks the final column.  The |\eqa@lastcol| command is there to
+% raise an error if the user tabs over to this column.  I'll temporarily
+% redefine it to |\@eqalasttrue| when I enter this column legitimately.
+% The extra magical bits here will make the final column repeat, so that we
+% can find it if necessary.  Well is this column type named.
+%
+% That's it.  We can return to normal now.
+%
+%    \begin{macrocode}
+\colpop
+%    \end{macrocode}
+%
+% \subsubsection{Newline codes}
+%
+% Newline sequences (|\\|) get turned into calls of |\@eqncr|.  The job is
+% fairly simple, really.
+%
+%    \begin{macrocode}
+\def\@eqncr{\tab@cr\eqacr@i\interdisplaylinepenalty\@M}%
+\def\eqacr@i#1#2{%
+  \eqa@eqnum%
+  \noalign{\penalty#2\vskip\jot\vskip#1}%
+}
+%    \end{macrocode}
+%
+% \subsubsection{Setting equation numbers}
+%
+% \begin{macro}{\eqa@eqpos}
+%
+% Before we start, we need to generalise the flush-left number handling bits.
+% The macro |\eqa@eqpos| will put its argument in the right place.
+%
+%    \begin{macrocode}
+\if@leqno
+  \def\eqa@eqpos#1{%
+    \hb@xt@.01\p@{}\rlap{\normalfont\normalcolor\hskip-\displaywidth#1}%
+  }
+\else
+  \def\eqa@eqpos#1{\normalfont\normalcolor#1}
+\fi
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\eqa@eqnum}
+%
+% Here we typeset an equation number in roughly the right place.  First I'll
+% redefine |\eqa@lastcol| so that it tells me I'm in the right place, and
+% start a loop to find that place.
+%
+%    \begin{macrocode}
+\def\eqa@eqnum{%
+  \global\let\eqa@lastcol\@eqalasttrue%
+  \eqa@eqnum@i%
+}
+%    \end{macrocode}
+%
+% Now for the loop.  The |\relax| here is absolutely vital -- it starts the
+% table column, inserting useful tokens like `|\eqa@lastcol|' which tell
+% me where I am in the alignment.  Then, if I've reached the end, I can
+% typeset the equation number; otherwise I go off into another macro and
+% step on to the next column.
+%
+%    \begin{macrocode}
+\def\eqa@eqnum@i{%
+  \relax%
+  \if@eqalast%
+    \expandafter\eqa@eqnum@ii%
+  \else%
+    \expandafter\eqa@eqnum@iii%
+  \fi%
+}
+\def\eqa@eqnum@ii{%
+  \eqa@eqpos\eqa@number%
+  \global\let\eqa@number\eqa@defnumber%
+  \global\let\eqa@lastcol\eqa@@lastcol%
+  \cr%
+}
+\def\eqa@eqnum@iii{&\eqa@eqnum@i}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\eqa@lastcol}
+%
+% This is used as a marker for the final column in an \env{eqnarray}
+% environment.  By default it informs the user that they've been very
+% silly and swallows the contents of the column.  I'll redefine it to
+% something more useful at appropriate times, and then turn it back again.
+%
+%    \begin{macrocode}
+\def\eqa@@lastcol{\mth@err@number\setbox\z@}
+\let\eqa@lastcol\eqa@@lastcol
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Numbering control}
+%
+% \begin{macro}{\eqnumber}
+%
+% The |\eqnumber| command sets the equation number on the current equation.
+% This is really easy, actually.
+%
+%    \begin{macrocode}
+\newcommand\eqnumber[1][\eqa@eqcount]{\gdef\eqa@number{#1}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\eqa@eqcount}
+%
+% This is how a standard equation number is set, stepping the counter and
+% all.  It's really easy and obvious.
+%
+%    \begin{macrocode}
+\def\eqa@eqcount{(\theequation)\global\advance\c@equation\@ne}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\nonumber}
+%
+% The \LaTeX\ |\nonumber| command could be defined by saying
+% \begin{listing}
+%\renewcommand{\nonumber}{\eqnumber[]}
+% \end{listing}
+% but I'll be slightly more efficient and redefine |\eqa@number| directly.
+%
+%    \begin{macrocode}
+\def\nonumber{\global\let\eqa@number\@empty}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{The \env{eqnalign} environment}
+%
+% As a sort of companion to \env{eqnarray}, here's an environment which does
+% similar things inside a box, rather than taking up the whole display width.
+% It uses the same column types that we've already created, so there should
+% be no problems.
+%
+% \begin{environment}{eqnalign}
+%
+% First, sort out some simple things like optional arguments.
+%
+%    \begin{macrocode}
+\def\eqnalign{\@ifnextchar[\eqnalign@i{\eqnalign@i[rcl]}}
+\def\eqnalign@i[#1]{%
+  \@ifnextchar[{\eqnalign@ii{#1}}{\eqnalign@ii{#1}[c]}%
+}
+%    \end{macrocode}
+%
+% Now we actually do the environment.  This is fairly easy, actually.
+%
+%    \begin{macrocode}
+\def\eqnalign@ii#1[#2]{%
+  \let\\\eqn@cr%
+  \colset{eqnarray}%
+  \tab@initread%
+  \def\tab@tabtext{&\tabskip\z@skip}%
+  \tabskip\z@skip%
+  \col@sep.5\eqainskip%
+  \tab@readpreamble{#1}%
+  \everycr{}%
+  \if#2t\vtop\else%
+    \if#2b\vbox\else%
+      \vcenter%
+    \fi%
+  \fi%
+  \bgroup%
+  \halign\expandafter\bgroup\the\tab@preamble\cr%
+}
+%    \end{macrocode}
+%
+% Finishing the environment is even simpler.
+%
+%    \begin{macrocode}
+\def\endeqnalign{%
+  \crcr%
+  \egroup%
+  \egroup%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{macro}{\eqn@cr}
+%
+% Newlines are really easy here.
+%
+%    \begin{macrocode}
+\def\eqn@cr{\tab@cr\eqn@cr@i{}{}}
+\def\eqn@cr@i#1{\cr\noalign{\vskip\jot\vskip#1}\@gobble}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Simple multiline equations}
+%
+% As a sort of example and abbreviation, here's a multiline display
+% environment which just centres everything.
+%
+% \begin{environment}{eqlines}
+%
+% We just get |\eqnarray| to do everything for us.  This is really easy.
+%
+%    \begin{macrocode}
+\def\eqlines{\eqnarray[x]}
+\let\endeqlines\endeqnarray
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{environment}{eqlines*}
+%
+% There's a $*$ version which omits numbers.  This is easy too.  Lots of
+% hacking with expansion here to try and reduce the number of tokens being
+% used.  Is it worth it?
+%
+%    \begin{macrocode}
+\expandafter\edef\csname eqlines*\endcsname{%
+  \expandafter\noexpand\csname eqnarray*\endcsname[x]%
+}
+\expandafter\let\csname endeqlines*\expandafter\endcsname
+                \csname endeqnarray*\endcsname
+%    \end{macrocode}
+%
+% \end{environment}
+%
+%
+% \subsection{Split equations}
+%
+% Based on an idea from \textit{The \TeX book}, we provide some simple
+% environments for doing split equations.  There's plenty of scope for
+% improvement here, though.
+%
+% \begin{environment}{spliteqn}
+% \begin{environment}{spliteqn*}
+%
+% The only difference between these two is that the $*$-version doesn't put
+% in an equation number by default (although this behaviour can be
+% changed by |\eqnumber|).
+%
+% The fun here mainly concerns putting in the equation number at the right
+% place -- for |leqno| users, we need to put the number on the first line;
+% otherwise we put it on the last line.
+%
+% The way we handle this is to have two macros, |\\| (which clearly does
+% all the user line breaks) and |\seq@lastcr| which is used at the end of
+% the environment to wrap everything up.  The |\seq@eqnocr| macro puts an
+% equation number on the current line and then does a normal |\\|.  It also
+% resets |\\| and |\seq@lastcr| so that they don't try to put another
+% equation number in.  This must be done globally, although anyone who tries
+% to nest maths displays will get what they deserve.
+%
+% For the non-$*$ environment, then, we need to step the equation counter,
+% and set |\\| to |\seq@cr| or |\seq@eqnocr| as appropriate for the setting
+% of the |leqno| flag -- |\seq@lastcr| always gets set to put an equation
+% number in (because it will be reset if the number actually gets done
+% earlier -- this catches stupid users trying to put a single row into
+% a split environment).
+%
+%    \begin{macrocode}
+\def\spliteqn{%
+  \let\eqa@oldnumber\eqa@number%
+  \global\let\eqa@number\eqa@eqcount%
+  \spliteqn@i%
+}
+%    \end{macrocode}
+%
+% For the $*$ variant, we don't need to bother with equation numbering, so
+% this is really easy.
+%
+%    \begin{macrocode}
+\@namedef{spliteqn*}{%
+  \let\eqa@oldnumber\eqa@number%
+  \gdef\eqa@number{}%
+  \spliteqn@i%
+}
+%    \end{macrocode}
+%
+% Ending the environments is easy.  Most of the stuff here will be described
+% later.
+%
+%    \begin{macrocode}
+\def\endspliteqn{%
+  \hfilneg\seq@lastcr%
+  \egroup%
+  \dsp@end%
+  \global\let\eqa@number\eqa@oldnumber%
+  \global\advance\c@equation\m@ne%
+}
+\expandafter\let\csname endspliteqn*\endcsname\endspliteqn
+%    \end{macrocode}
+%
+% \end{environment}
+% \end{environment}
+%
+% \begin{macro}{\spliteqn@i}
+%
+% Here we handle the full display splits.  Start a maths display, and make
+% each row of the alignment take up the full display width.
+%
+% The macro |\seq@dosplit| does most of the real work for us -- setting up
+% the alignment and so forth.  The template column is interesting.  There
+% are two items glue on both sides of the actual text:
+%
+% \begin{itemize}
+%
+% \item Some glue which can shrink.  This keeps the display from the edges
+%       of the page unless we get a really wide item.
+%
+% \item An |\hfil| to do the alignment.  By default, this centres the
+%       equations.  On the first line, however, we put a leading |\hfilneg|
+%       which cancels the first |\hfil|, making the first row left aligned.
+%       Similarly, at the end, we put an |\hfilneg| after the last equation
+%       to right align the last line.
+%
+% \end{itemize}
+%
+% We pass this information on as an argument.  It's easy really.
+%
+%    \begin{macrocode}
+\def\spliteqn@i{%
+%    \end{macrocode}
+%
+% First, set up equation numbering properly.  See my rant about
+% |\refstepcounter| above.
+%
+%    \begin{macrocode}
+  \stepcounter{equation}%
+  \def\@currentlabel{\p@equation\theequation}%
+%    \end{macrocode}
+%
+% Right; now to sort out the numbering and newline handling.  If the number's
+% meant to be on the first line (for \textsf{leqno} users), then it gets
+% typeset on the first like; otherwise we just do a normal newline on
+% all lines except the first.  Once |\seq@eqnocr| has done its stuff, it
+% redefines all the newline handling not to insert another number.
+%
+%    \begin{macrocode}
+  \if@leqno%
+    \global\let\seq@docr\seq@eqnocr%
+  \else%
+    \global\let\seq@docr\seq@cr%
+  \fi%
+  \global\let\seq@lastcr\seq@eqnocr%
+%    \end{macrocode}
+%
+% For my next trick, I'll do some display handling -- start a (possibly
+% nested) maths display, set up the |\tabpause| macro appropriately, and
+% set the newline command to do the right thing.
+%
+%    \begin{macrocode}
+  \dsp@start%
+  \dsp@tabpause%
+  \def\\{\seq@docr}%
+%    \end{macrocode}
+%
+% Finally, call another macro to do the remaining bits of setting up.
+%
+%    \begin{macrocode}
+  \seq@dosplit%
+    {\hb@xt@\displaywidth{%
+      \hskip\splitleft\hfil$\displaystyle##$%
+      \hfil\hskip\splitright}}%
+    {\hfilneg}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{subsplit}
+%
+% For doing splits in the middle of equations, we provide a similar
+% environment.  Here, we make |\\| just start a new line.  We also use
+% a |\vcenter| rather than a full maths display.  The glue items are also
+% a bit different: we use plain double-quads on each side of the item, and
+% we need to remove them by hand at the extremities of the environment.
+%
+%    \begin{macrocode}
+\def\subsplit{%
+  \let\\\seq@cr%
+  \vcenter\bgroup%
+  \seq@dosplit{\hfil\qquad$##$\qquad\hfil}{\hfilneg\hskip-2em}%
+}
+%    \end{macrocode}
+%
+% Ending the environment is fairly easy.  We remove the final glue item,
+% and close the alignment and the vbox.
+%
+%    \begin{macrocode}
+\def\endsubsplit{%
+  \hfilneg\hskip-2em\cr%
+  \egroup\egroup%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{macro}{\seq@dosplit}
+%
+% Here we do most of the real work.  Actually, since the preamble is passed
+% in as an argument, most of the work is already done.  The only thing to
+% really note is the template for subsequent columns.  To stop users putting
+% in extra columns (which is where we put the equation number) we raise an
+% error and discard the input in a scratch box register.  This template is
+% repeated infinitely so as to allow us to put the equation number in nicely.
+% However, the final negative glue item won't work properly, so the equation
+% will look awful.
+%
+%    \begin{macrocode}
+\def\seq@dosplit#1#2{%
+  \halign\bgroup%
+    #1&&\mth@err@number\setbox\z@\hbox{##}\cr%
+  #2\relax%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\seq@eqnocr}
+%
+% Here's how we set equation numbers.  Since the column provided raises
+% errors as soon as a token finds its way into it, we start with a |&\omit|.
+% Then we just put the equation number in a zero-width box.  Finally, we
+% reset the newline commands to avoid putting in more than one equation
+% number, and do normal newline things.
+%
+%    \begin{macrocode}
+\def\seq@eqnocr{%
+  &\omit%
+  \hb@xt@\z@{\hss\eqa@eqpos\eqa@number}%
+  \global\let\seq@docr\seq@cr%
+  \global\let\seq@lastcr\seq@cr%
+  \seq@cr%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\seq@cr}
+%
+% Newlines are very easy.  We add a |\jot| of extra space, since this is
+% a nice thing to do.
+%
+%    \begin{macrocode}
+\def\seq@cr{\tab@cr\seq@cr@i\interdisplaylinepenalty\@M}
+\def\seq@cr@i#1#2{\cr\noalign{\penalty#2\vskip\jot\vskip#1}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Matrix handling}
+%
+% There's been a complete and total overhaul of the spacing calculations
+% for matrices here.  The vertical spacing now bears an uncanny similarity
+% to the rules \TeX\ uses to space out |\atop|-like fractions, the difference
+% being that you can have more than one column in a matrix.  This has the
+% interesting side-effect that we get an \package{amsmath}-style
+% sub/superscript environment almost free of charge with the matrix handling
+% (it just ends up being a script-size single-column matrix).
+%
+% What is rather gratifying is that our \env{matrix} environment looks
+% rather nicer than \package{amsmath}'s (which is based directly on
+% \env{array}, giving it nasty restrictions on the numbers of columns and
+% so on); in particular, the version here gives the `correct' result for
+% Knuth's exercise~18.42 (which states categorically that a |\smallskip|
+% should be placed between the rows of the big matrix).
+%
+% The reason the interrow space doesn't come out in the AMS version is
+% that \env{array} inserts extra vertical space by extending the depth of
+% the final row using a strut: the big matrix already extends deeper than
+% this, so the strut doesn't make any difference.  If the space was added
+% by |\hlx{s[\smallskipamount]}| instead of the |\\| command, things would
+% be different.
+%
+% \begin{figure}
+%
+% ^^A This is essentially what amsmath (version 1.2b) does.  The real
+% ^^A implementation requires a counter MaxMatrixCols, and has fewer braces:
+% ^^A that's all the difference.  Oh, and I turn off \arrayextrasep here,
+% ^^A since amsmath doesn't expect it to be there (accurate emulation, see?)
+% ^^A and I've used \hspace instead of \hskip since everything else is
+% ^^A `proper' LaTeX stuff.
+%
+% \newenvironment{ams-pmatrix}{^^A
+%   \setlength{\arrayextrasep}{0pt}^^A
+%   \left(^^A
+%   \hspace{-\arraycolsep}^^A
+%   \begin{array}{*{10}{c}}^^A
+% }{^^A
+%  \end{array}^^A
+%  \hspace{-\arraycolsep}^^A
+%  \right)^^A
+% }
+%
+% \begin{demo}{Exercise 18.42 from \emph{The \TeX book}}
+%\newcommand{\domatrix}[1]{
+%  \def\mat##1
+%    {\begin{#1}##1\end{#1}}
+%  \[ \begin{#1}
+%     \mat{a & b \\ c & d} &
+%     \mat{e & f \\ g & h}
+%     \\[\smallskipamount]
+%     0 &
+%     \mat{i & j \\ k & l}
+%     \end{#1}
+%  \]
+%}
+%\domatrix{pmatrix}
+%\domatrix{ams-pmatrix}
+% \end{demo}
+%
+% \end{figure}
+%
+% \begin{environment}{genmatrix}
+%
+% The first job is to store my maths style and font away, because I'll be
+% needing it lots later.
+%
+%    \begin{macrocode}
+\def\genmatrix#1#2#3#4#5{%
+  \let\mat@style#1%
+  \ifx#2\scriptstyle%
+    \let\mat@font\scriptfont%
+  \else\ifx#2\scriptscriptstyle%
+    \let\mat@font\scriptscriptfont%
+  \else%
+    \let\mat@font\textfont%
+  \fi\fi%
+%    \end{macrocode}
+%
+% Now to cope with inserted text.  This is easy.
+%
+%    \begin{macrocode}
+  \ifx\mat@style\scriptstyle%
+    \let\mat@textsize\scriptsize%
+  \else\ifx\mat@style\scriptscriptstyle%
+    \let\mat@textsize\scriptscriptsize%
+  \else%
+    \let\mat@textsize\relax%
+  \fi\fi%
+%    \end{macrocode}
+%
+% Now for some fun.  I'll remember how to start and end the matrix in a
+% couple of macros |\mat@left| and |\mat@right|.  I haven't yet worked out
+% exactly what needs to be in |\mat@right| yet, though, so I'll build that
+% up in a scratch token list while I'm making my mind up.
+%
+% Initially, I want to open a group (to trap the style changes), set the
+% maths style (to get the right spacing), insert the left delimiter, insert
+% some spacing around the matrix, and start a centred box.  The ending just
+% closes all the groups and delimiters I opened.
+%
+%    \begin{macrocode}
+  \def\mat@left{\bgroup\mat@style\left#4#3\vcenter\bgroup}%
+  \toks@{\egroup#3\right#5\egroup}%
+%    \end{macrocode}
+%
+% Now comes a slightly trickier bit.  If the maths style is script or
+% scriptscript, then I need to raise the box by a little bit to make it look
+% really good.  The right amount is somewhere around \smallf 3/4\,pt, I
+% think, so that's what I'll use.
+%
+%    \begin{macrocode}
+  \@tempswatrue%
+  \ifx\mat@style\displaystyle\else\ifx\mat@style\textstyle\else%
+    \@tempswafalse%
+    \setbox\z@\hbox\bgroup$%
+    \toks@\expandafter{\the\toks@$\m@th\egroup\raise.75\p@\box\z@}%
+  \fi\fi%
+%    \end{macrocode}
+%
+% If I'm not in maths mode right now, then I should enter maths mode, and
+% remember to leave it later.
+%
+%    \begin{macrocode}
+  \if@tempswa\ifmmode\else%
+    $\m@th%
+    \toks@\expandafter{\the\toks@$}%
+  \fi\fi%
+%    \end{macrocode}
+%
+% Now I've sorted out how to end the environment properly, so I can set up
+% the macro, using |\edef|.
+%
+%    \begin{macrocode}
+  \edef\mat@right{\the\toks@}%
+%    \end{macrocode}
+%
+% Now see if there's an optional argument.  If not, create lots of centred
+% columns.
+%
+%    \begin{macrocode}
+  \@ifnextchar[\genmatrix@i{\genmatrix@i[[c]}%
+}
+%    \end{macrocode}
+%
+% Now to sort out everything else.
+%
+%    \begin{macrocode}
+\def\genmatrix@i[#1]{%
+%    \end{macrocode}
+%
+% Some initial setting up: choose the correct column set, and set up some
+% variables for reading the preamble.
+%
+%    \begin{macrocode}
+  \colset{matrix}%
+  \tab@initread%
+%    \end{macrocode}
+%
+% Now comes some of the tricky stuff.  The space between columns should be
+% 12\,mu (by trial and error).  We put the space in a box so we can measure
+% it in the correct mathstyle.
+%
+%    \begin{macrocode}
+  \setbox\z@\hbox{$\mat@style\mskip12mu$}%
+  \edef\tab@tabtext{&\kern\the\wd\z@}%
+  \tab@readpreamble{#1}%
+%    \end{macrocode}
+%
+% Now we need to decide how to space out the rows.  The code here is based
+% on the information in appendix~G of \emph{The \TeX book}: I think it'd be
+% nice if my matrices were spaced out in the same way as normal fractions
+% (particularly |\choose|y things).  The standard |\baselineskip| and
+% |\lineskip| parameters come in really handy here.
+%
+% The parameters vary according to the size of the text, so I need to see
+% if we have scriptsize or less, or not.  The tricky |\if| sorts this out.
+%
+%    \begin{macrocode}
+  \if1\ifx\mat@style\scriptstyle1\else%
+      \ifx\mat@style\scriptscriptstyle1\else0\fi\fi%
+    \baselineskip\fontdimen10\mat@font\tw@%
+    \advance\baselineskip\fontdimen12\mat@font\tw@%
+    \lineskip\thr@@\fontdimen8\mat@font\thr@@%
+  \else%
+    \baselineskip\fontdimen8\mat@font\tw@%
+    \advance\baselineskip\fontdimen11\mat@font\tw@%
+    \lineskip7\fontdimen8\mat@font\thr@@%
+  \fi%
+  \lineskiplimit\lineskip%
+%    \end{macrocode}
+%
+% Now actually set up for the alignment.  Assign |\\| to the correct value.
+% Set up the |\tabskip|.  Do the appropriate |\mat@left| thing set up above.
+% And then start the alignment.
+%
+%    \begin{macrocode}
+  \let\\\mat@cr%
+  \tabskip\z@skip%
+  \col@sep\z@%
+  \mat@left%
+  \halign\expandafter\bgroup\the\tab@preamble\tabskip\z@skip\cr%
+%    \end{macrocode}
+%
+% Now for a little hack to make the spacing consistent between matrices of
+% the same height.  This comes directly from \PlainTeX.  This appears to
+% make the spacing \emph{exactly} the same as the \TeX\ primitives, oddly
+% enough.
+%
+%    \begin{macrocode}
+  \ifx\mat@font\textfont%
+    \omit$\mat@style\mathstrut$\cr\noalign{\kern-\baselineskip}%
+  \fi%
+}
+%    \end{macrocode}
+%
+% Finishing the environment is really easy.  We do the spacing hack again
+% at the bottom, close the alignment and then tidy whatever we started in
+% |\mat@left|.
+%
+%    \begin{macrocode}
+\def\endgenmatrix{%
+  \crcr%
+  \ifx\mat@font\textfont%
+    \omit$\mat@style\mathstrut$\cr\noalign{\kern-\baselineskip}%
+  \fi%
+  \egroup%
+  \mat@right%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{macro}{\mat@cr}
+%
+% Newlines are really easy.  The $*$-form means nothing here, so we ignore
+% it.
+%
+%    \begin{macrocode}
+\def\mat@cr{\tab@cr\mat@cr@i{}{}}
+\def\mat@cr@i#1{\cr\noalign{\vskip#1}\@gobble}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\newmatrix}
+%
+% This is how we define new matrix environments.  It's simple fun with
+% |\csname| and |\expandafter|.
+%
+%    \begin{macrocode}
+\def\newmatrix#1#2{%
+  \@namedef{#1}{\genmatrix#2}%
+  \expandafter\let\csname end#1\endcsname\endgenmatrix%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{matrix}
+% \begin{environment}{pmatrix}
+% \begin{environment}{dmatrix}
+% \begin{environment}{smatrix}
+% \begin{environment}{spmatrix}
+% \begin{environment}{sdmatrix}
+% \begin{environment}{smatrix*}
+% \begin{environment}{spmatrix*}
+% \begin{environment}{sdmatrix*}
+%
+% Now we define all the other environments we promised.  This is easy.
+%
+%    \begin{macrocode}
+\newmatrix{matrix}{{\textstyle}{\textstyle}{\,}{.}{.}}
+\newmatrix{pmatrix}{{\textstyle}{\textstyle}{\,}{(}{)}}
+\newmatrix{dmatrix}{{\textstyle}{\textstyle}{\,}}
+\newmatrix{smatrix}{{\scriptstyle}{\scriptstyle}{}{.}{.}}
+\newmatrix{spmatrix}{{\scriptstyle}{\scriptstyle}{}{(}{)}}
+\newmatrix{sdmatrix}{{\scriptstyle}{\scriptstyle}{}}
+\newmatrix{smatrix*}{{\scriptstyle}{\textstyle}{}{.}{.}}
+\newmatrix{spmatrix*}{{\scriptstyle}{\textstyle}{}{(}{)}}
+\newmatrix{sdmatrix*}{{\scriptstyle}{\textstyle}{}}
+%    \end{macrocode}
+%
+% \end{environment}
+% \end{environment}
+% \end{environment}
+% \end{environment}
+% \end{environment}
+% \end{environment}
+% \end{environment}
+% \end{environment}
+% \end{environment}
+%
+% \begin{environment}{script}
+%
+% Now for superscripts and subscripts.  This is fairly easy, because I
+% took so much care over the matrix handling.
+%
+%    \begin{macrocode}
+\def\script{%
+  \let\mat@style\scriptstyle%
+  \def\mat@left{\vcenter\bgroup}%
+  \def\mat@right{\egroup}%
+  \let\mat@font\scriptfont%
+  \let\mat@textsize\scriptsize%
+  \@ifnextchar[\genmatrix@i{\genmatrix@i[c]}%
+}
+\let\endscript\endgenmatrix
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% Now define the column types.
+%
+%    \begin{macrocode}
+\colpush{matrix}
+\coldef l{\tabcoltype{\kern\z@$\mat@style}{\m@th$\hfil}}
+\coldef c{\tabcoltype{\hfil$\mat@style}{\m@th$\hfil}}
+\coldef r{\tabcoltype{\hfil$\mat@style}{\m@th$}}
+\coldef T#1{\tab@aligncol{#1}{\begingroup\mat@textsize}{\endgroup}}
+\collet > [tabular]>
+\collet < [tabular]<
+\collet * [tabular]*
+\collet @ [tabular]@
+%    \end{macrocode}
+%
+% The repeating type is more awkward.  Things will go wrong if this is
+% given before the first column, so we must do a whole repeat by hand.  We
+% can tell if we haven't contributed a column yet, since |\tab@column| will
+% be zero.  Otherwise, we fiddle the parser state to start a new column, and
+% insert the |&| character to make \TeX\ repeat the preamble.
+%
+%    \begin{macrocode}
+\coldef {[}{%
+  \@firstoftwo{%
+    \ifnum\tab@columns=\z@%
+      \def\@tempa##1\q@delim{%
+        \tab@mkpreamble##1[##1\q@delim%
+      }%
+      \expandafter\@tempa%
+    \else%
+      \tab@setstate\tab@prestate%
+      \tab@append\tab@preamble{&}%
+      \expandafter\tab@mkpreamble%
+    \fi%
+  }%
+}
+%    \end{macrocode}
+%
+% We're done defining columns now.
+%
+%    \begin{macrocode}
+\colpop
+%    \end{macrocode}
+%
+%
+% \subsection{Dots\dots}
+%
+% Nothing whatsoever to do with alignments, although vertical and diagonal
+% dots in small matrices look really silly.  The following hacky definitions
+% work rather better.
+%
+% \begin{macro}{\mdw@dots}
+%
+% First of all, here's some definitions common to both of the dots macros.
+% The macro takes as an argument the actual code to draw the dots, passing
+% it the scaled size of a point in the scratch register |\dimen@|; the
+% register |\box 0| is set to contain a dot of the appropriate size.
+%
+%    \begin{macrocode}
+\def\mdw@dots#1{\ensuremath{\mathpalette\mdw@dots@i{#1}}}
+\def\mdw@dots@i#1#2{%
+  \setbox\z@\hbox{$#1\mskip1.8mu$}%
+  \dimen@\wd\z@%
+  \setbox\z@\hbox{$#1.$}%
+  #2%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\vdots}
+%
+% I'll start with the easy one.  This is a simple translation of the original
+% implementation.
+%
+%    \begin{macrocode}
+\def\vdots{%
+  \mdw@dots{\vbox{%
+    \baselineskip4\dimen@%
+    \lineskiplimit\z@%
+    \kern6\dimen@%
+    \copy\z@\copy\z@\box\z@%
+  }}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\ddots}
+%
+% And I'll end with the other easy one\dots
+%
+%    \begin{macrocode}
+\def\ddots{%
+  \mdw@dots{\mathinner{%
+    \mkern1mu%
+    \raise7\dimen@\vbox{\kern7\dimen@\copy\z@}%
+    \mkern2mu%
+    \raise4\dimen@\copy\z@%
+    \mkern2mu%
+    \raise\dimen@\box\z@%
+    \mkern1mu%
+  }}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Lucky dip}
+%
+% Time to round off with some trivial environments, just to show how easy
+% this stuff is.
+%
+% \begin{environment}{cases}
+% \begin{environment}{smcases}
+%
+% These are totally and utterly trivial.
+%
+%    \begin{macrocode}
+\def\cases{\left\{\,\array{@{}lTl@{}}}
+\def\endcases{\endarray\,\right.}
+\def\smcases{\left\{\smarray{@{}lTl@{}}}
+\def\endsmcases{\endsmarray\,\right.}
+%    \end{macrocode}
+%
+% \end{environment}
+% \end{environment}
+%
+% \subsection{Error messages}
+%
+% Some token saving:
+%
+%    \begin{macrocode}
+\def\mth@error{\PackageError{mathenv}}
+%    \end{macrocode}
+%
+% Now for the error messages.
+%
+%    \begin{macrocode}
+\def\mth@err@number{%
+  \mth@error{Too many `&' characters found}{%
+    You've put too many `&' characters in an alignment^^J%
+    environment (like `eqnarray' or `spliteqn') and wandered^^J%
+    into trouble.  I've gobbled the contents of that column^^J%
+    and hopefully I can recover fairly easily.%
+  }%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\mth@err@mdsp{%
+  \mth@error{Can't do displays in nondisplay maths mode}{%
+    You're trying to start a display environment, but you're^^J%
+    in nondisplay maths mode.  The display will appear but^^J%
+    don't blame me when it looks horrible.%
+  }%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\mth@err@hdsp{%
+  \mth@error{Can't do displays in LR mode}{%
+    You're trying to start a display environment, but you're^^J%
+    in LR (restricted horizontal) mode.  Everything will go^^J%
+    totally wrong, so your best bet is to type `X', fix the^^J%
+    mistake and start again.%
+  }%
+}
+%    \end{macrocode}
+%
+% \vskip\parskip\vbox{ ^^A The best way I could find of keeping this lot
+%                      ^^A together, I'm afraid.
+% That's all there is.  Byebye.
+%
+%    \begin{macrocode}
+%</mathenv>
+%    \end{macrocode}
+% \nopagebreak
+%
+% \hfill Mark Wooding, \today
+% }
+%
+% \Finale
+%
+\endinput
diff --git a/mdwthm.dtx b/mdwthm.dtx
new file mode 100644
index 0000000..f4a17d2
--- /dev/null
+++ b/mdwthm.dtx
@@ -0,0 +1,303 @@
+% \begin{meta-comment}
+%
+% $Id: mdwthm.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
+%
+% Standard theorem typesetting
+%
+% (c) 2001 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: mdwthm.dtx,v $
+% Revision 1.1  2002/02/03 20:49:03  mdw
+% Checkin for new build system.
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% mdwthm package -- standard theorem stuff
+%% Copyright (c) 2001 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%% 
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%% 
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software Foundation,
+%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preambles>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{mdwthm}
+%<+package>                [2001/09/16 1.0 theorem typesetting]
+%<+thmstyle>\ProvidesFile{mdwmargin.thm}
+%<+thmstyle>             [2001/09/16 1.0 numbers-in-the-margin theorem style]
+% \end{meta-comment}
+%
+% \CheckSum{140}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{mdwthm}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+%^^A-------------------------------------------------------------------------
+% \section{User guide}
+%
+% \subsection{Environments provided}
+%
+% \DescribeEnv{theorem}
+% \DescribeEnv{lemma}
+% \DescribeEnv{proposition}
+% \DescribeEnv{corollary}
+% \DescribeEnv{definition}
+% \DescribeEnv{example}
+% \DescribeEnv{fact}
+% \DescribeEnv{remark}
+% \DescribeEnv{note}
+% The package defines a collection of theorem environments, declared in the
+% usual way.  All of them except \env{claim} share the same counter.  If the
+% document class has a |\chapter| command, then they are numbered within the
+% chapter; otherwise there is a single numbering system throughout the
+% document.
+%
+% Every environment has a $*$-version, which doesn't print a number.  This
+% might be useful every now and then.
+%
+% The environments \env{theorem}, \env{lemma}, \env{proposition},
+% \env{claim}and \env{corollary} are set using the `plain' style, with the
+% body text in \textit{italics}.  The environments \env{definition} and
+% \env{example} are set in the `definition' style, with body text in roman.
+% The remaining environments, \env{fact}, \env{remark}, and \env{note} are
+% set in the `remark' style.
+%
+% \DescribeEnv{claim}
+% \DescribeEnv{proof}
+% The \env{claim} environment has its own counter, which is reset at the
+% beginning of the \env{proof} environment.
+%
+% \subsection{The \package{mdwmargin} style}
+%
+% This package also provides a pretty `number-hanging-in-the-margin' theorem
+% style collection, available under the name \env{mdwmargin}.
+%
+% \implementation
+%
+%
+%^^A-------------------------------------------------------------------------
+% \section{Implementation of the environments}
+%
+%    \begin{macrocode}
+%<*package>
+\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{amsthm}}
+\ProcessOptions\relax
+\RequirePackage{amsthm}
+%    \end{macrocode}
+%
+% \subsection{The simple bits}
+%
+% \begin{environment}{theorem}
+%
+% Do the right thing with the numbering rules.
+%
+%    \begin{macrocode}
+\toks@{\newtheorem{theorem}{Theorem}}
+\@tempswatrue%
+\ifx\if@article\iftrue\@tempswafalse\fi
+\ifx\chapter\@@undefined\@tempswafalse\fi
+\if@tempswa\toks@\expandafter{\the\toks@[chapter]}\fi
+\the\toks@
+\newtheorem*{theorem*}{Theorem}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{environment}{lemma}
+% \begin{environment}{proposition}
+% \begin{environment}{corollary}
+% \begin{environment}{claim}
+% \begin{environment}{definition}
+% \begin{environment}{example}
+% \begin{environment}{fact}
+% \begin{environment}{remark}
+%
+% Most of this is very easy.
+%
+%    \begin{macrocode}
+\theoremstyle{plain}
+\newtheorem{lemma}[theorem]{Lemma}
+\newtheorem*{lemma*}{Lemma}
+\newtheorem{proposition}[theorem]{Proposition}
+\newtheorem*{proposition*}{Proposition}
+\newtheorem{corollary}[theorem]{Corollary}
+\newtheorem*{corollary*}{Corollary}
+\newtheorem{fact}[theorem]{Fact}
+\newtheorem*{fact*}{Fact}
+\newtheorem{claim}{Claim}
+\newtheorem*{claim*}{Claim}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\theoremstyle{definition}
+\newtheorem{definition}[theorem]{Definition}
+\newtheorem*{definition*}{Definition}
+\newtheorem{example}[theorem]{Example}
+\newtheorem*{example*}{Example}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\theoremstyle{remark}
+\newtheorem{remark}[theorem]{Remark}
+\newtheorem*{remark*}{Remark}
+%    \end{macrocode}
+%
+% \end{environment}
+% \end{environment}
+% \end{environment}
+% \end{environment}
+% \end{environment}
+% \end{environment}
+% \end{environment}
+% \end{environment}
+%
+% \begin{environment}{note}
+%
+% Someone else might also have a \env{note} environment.  Be careful.
+%
+%    \begin{macrocode}
+\ifx\note\@@undefined
+  \newtheorem{note}[theorem]{Note}
+  \newtheorem*{note*}{Note}
+\fi
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{environment}{proof}
+%
+% Now to hack the proof environment.
+%
+%    \begin{macrocode}
+\renewenvironment{proof}[1][\proofname]{%
+  \setcounter{claim}{0}%
+  \par\normalfont%
+  \trivlist\advance\itemindent\labelsep\let\makelabel\textit%
+  \advance\@topsep-\parskip%
+  \advance\@topsepadd-\parskip%
+  \item[#1\@proofdot]%
+}{%
+  \qed\endtrivlist%
+}
+\def\@proofdot{.}
+%    \end{macrocode}
+% \end{environment}
+%
+% Done.
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+%^^A-------------------------------------------------------------------------
+% \section{Implementation of the theorem style}
+%
+%    \begin{macrocode}
+%<*thmstyle>
+%    \end{macrocode}
+%
+% \begin{macro}{\thmhead@margin}
+%
+% Firstly, a macro to typeset the theorem environment header, with the number
+% in the margin.
+%
+%    \begin{macrocode}
+\def\thmhead@margin#1#2#3{%
+  \thmnumber{\llap{#2{\normalsize\quad}}}%
+  \thmname{#1}%
+  \thmnote{ \the\thm@notefont(#3)}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\thm@headfont@margin}
+%
+% Now to decide on the header font.  Definitely we want boldface; if the
+% documentclass (or \package{mdwfonts}) has decided on a different font
+% family for the headings, then we use that.
+%
+%    \begin{macrocode}
+\def\thm@headfont@margin{%
+  \fontseries{b}%
+  \ifx\headdefault\@@undfined\else\fontfamily\headdefault\fi%
+  \selectfont%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\qedsymbol}
+%
+% Use the nice symbol if available.
+%
+%    \begin{macrocode}
+\AtBeginDocument{\ifx\square\@@undefined\else\def\qedsymbol{$\square$}\fi}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hack@thm}
+%
+% Now we hack the standard theorem styles to do what we want.  This is a
+% tedious enough game with |\expandafter|.
+%
+%    \begin{macrocode}
+\def\hack@thm#1#2{%
+  \expandafter\def\expandafter#1\expandafter{#1%
+    \let\thmhead\thmhead@margin%
+    \thm@headfont{\thm@headfont@margin}%
+    \thm@headpunct{}%
+    \advance\thm@postskip-\parskip%
+    \def\after@thm{#2}%
+  }
+}
+\def\@endtheorem{\after@thm\endtrivlist\@endpefalse}
+\let\@proofdot\relax
+\hack@thm\th@plain{}
+\hack@thm\th@definition{\qed}
+\hack@thm\th@remark{\qed}
+%</thmstyle>
+%    \end{macrocode}
+% \end{macro}
+%
+% \hfill Mark Wooding, \today
+% \Finale
+%
+\endinput
diff --git a/mdwtools.ins b/mdwtools.ins
new file mode 100644
index 0000000..79530fd
--- /dev/null
+++ b/mdwtools.ins
@@ -0,0 +1,87 @@
+%
+% $Id: mdwtools.ins,v 1.1 2002/02/03 20:49:03 mdw Exp $
+%
+% Installer for the mdwtools packages
+%
+% (c) 1996 Mark Wooding
+%
+
+%----- Revision history -----------------------------------------------------
+%
+% $Log: mdwtools.ins,v $
+% Revision 1.1  2002/02/03 20:49:03  mdw
+% Checkin for new build system.
+%
+% Revision 1.3  1996/11/19 20:57:26  mdw
+% Entered into RCS
+%
+
+% --- Licence note ---
+%
+% mdwtools installer
+% Copyright (c) 1996 Mark Wooding
+%
+% This program is free software; you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation; either version 2 of the License, or
+% (at your option) any later version.
+%
+% This program is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+% --- Sort out how to do all this ---
+
+\def\batchfile{mdwtools.ins}
+\input docstrip
+\keepsilent
+
+\preamble
+
+IMPORTANT NOTICE
+\endpreamble
+
+{ % --- This is a group so that docstrip \reads it all in one go ---
+
+  \ifx\generate\mdwxxnotdef
+    \gdef\mdwgen#1{#1}
+    \gdef\mdwf#1#2{\generateFile{#1}{n}{#2}}
+    \gdef\needed#1{}
+  \else
+    \global\let\mdwgen\generate
+    \global\def\mdwf{\file}
+    \global\askforoverwritefalse
+  \fi
+
+}
+
+\mdwgen{\mdwf {at.sty}		{\from {at.dtx}	      {package}}
+	\mdwf {mdwlist.sty}	{\from {mdwlist.dtx}  {package}}
+	\mdwf {mdwtab.sty}	{\from {mdwtab.dtx}   {mdwtab}
+				 \needed{syntax.dtx}
+				 \from {footnote.dtx} {macro}
+				 \from {doafter.dtx}  {macro}}
+	\mdwf {syntax.sty}	{\from {syntax.dtx}   {package}
+				 \from {doafter.dtx}  {macro}}
+	\mdwf {mathenv.sty}	{\from {mdwtab.dtx}   {mathenv}}
+	\mdwf {mdwmath.sty}	{\from {mdwmath.dtx}  {package}}
+	\mdwf {sverb.sty}	{\from {sverb.dtx}    {package}}
+	\mdwf {footnote.sty}	{\from {footnote.dtx} {package}}
+	\mdwf {doafter.sty}	{\from {doafter.dtx}  {package,latex2e}}
+	\mdwf {doafter.tex}	{\from {doafter.dtx}  {package,plain}}
+	\mdwf {cmtt.sty}	{\from {cmtt.dtx}     {sty}}
+	\mdwf {mTTenc.def}	{\from {cmtt.dtx}     {def}}
+	\mdwf {mTTcmtt.fd}	{\from {cmtt.dtx}     {fd}}
+	\mdwf {crypto.sty}	{\from {crypto.dtx}   {package}}
+	\mdwf {mdwthm.sty}	{\from {mdwthm.dtx}   {package}}
+	\mdwf {exercise.sty}	{\from {exercise.dtx} {package}}
+	\mdwf {mdwmargin.thm}	{\from {mdwthm.dtx}   {thmstyle}}
+	\mdwf {poetry.sty}	{\from {poetry.dtx}   {package}}
+}
+
+\Msg{Done!}
diff --git a/mdwtools.tex b/mdwtools.tex
new file mode 100644
index 0000000..cdc22f0
--- /dev/null
+++ b/mdwtools.tex
@@ -0,0 +1,1215 @@
+% \begin{meta-comment}
+%
+% $Id: mdwtools.tex,v 1.1 2002/02/03 20:49:03 mdw Exp $
+%
+% Common declarations for mdwtools.dtx files
+%
+% (c) 1996 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: mdwtools.tex,v $
+% Revision 1.1  2002/02/03 20:49:03  mdw
+% Checkin for new build system.
+%
+% Revision 1.4  1996/11/19 20:55:55  mdw
+% Entered into RCS
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% mdwtools common declarations
+%% Copyright (c) 1996 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <file preamble>
+%<*mdwtools>
+\ProvidesFile{mdwtools.tex}
+             [1996/05/10 1.4 Shared definitions for mdwtools .dtx files]
+%</mdwtools>
+% \end{meta-comment}
+%
+% \CheckSum{668}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \section{Introduction and user guide}
+%
+% This file is really rather strange; it gets |\input| by other package
+% documentation files to set up most of the environmental gubbins for them.
+% It handles almost everything, like loading a document class, finding any
+% packages, and building and formatting the title.
+%
+% It also offers an opportunity for users to customise my nice documentation,
+% by using a |mdwtools.cfg| file (not included).
+%
+%
+% \subsection{Declarations}
+%
+% A typical documentation file contains something like
+% \begin{listinglist} \listingsize \obeylines
+% |\input{mdwtools}|
+% \<declarations>
+% |\mdwdoc|
+% \end{listinglist}
+% The initial |\input| reads in this file and sets up the various commands
+% which may be needed.  The final |\mdwdoc| actually starts the document,
+% inserting a title (which is automatically generated), a table of
+% contents etc., and reads the documentation file in (using the |\DocInput|
+% command from the \package{doc} package.
+%
+% \subsubsection{Describing packages}
+%
+% \DescribeMacro{\describespackage}
+% \DescribeMacro{\describesclass}
+% \DescribeMacro{\describesfile}
+% \DescribeMacro{\describesfile*}
+% The most important declarations are those which declare what the
+% documentation describes.  Saying \syntax{"\\describespackage{<package>}"}
+% loads the \<package> (if necessary) and adds it to the auto-generated
+% title, along with a footnote containing version information.  Similarly,
+% |\describesclass| adds a document class name to the title (without loading
+% it -- the document itself must do this, with the |\documentclass| command).
+% For files which aren't packages or classes, use the |\describesfile| or
+% |\describesfile*| command (the $*$-version won't |\input| the file, which
+% is handy for files like |mdwtools.tex|, which are already input).
+%
+% \DescribeMacro{\author}
+% \DescribeMacro{\date}
+% \DescribeMacro{\title}
+% The |\author|, |\date| and |\title| declarations work slightly differently
+% to normal -- they ensure that only the \emph{first} declaration has an
+% effect.  (Don't you play with |\author|, please, unless you're using this
+% program to document your own packages.)  Using |\title| suppresses the
+% automatic title generation.
+%
+% \DescribeMacro{\docdate}
+% The default date is worked out from the version string of the package or
+% document class whose name is the same as that of the documentation file.
+% You can choose a different `main' file by saying
+% \syntax{"\\docdate{"<file>"}"}.
+%
+% \subsubsection{Contents handling}
+%
+% \DescribeMacro{\addcontents}
+% A documentation file always has a table of contents.  Other
+% contents-like lists can be added by saying
+% \syntax{"\\addcontents{"<extension>"}{"<command>"}"}.  The \<extension>
+% is the file extension of the contents file (e.g., \lit{lot} for the
+% list of tables); the \<command> is the command to actually typeset the
+% contents file (e.g., |\listoftables|).
+%
+% \subsubsection{Other declarations}
+%
+% \DescribeMacro{\implementation}
+% The \package{doc} package wants you to say
+% \syntax{"\\StopEventually{"<stuff>"}"}' before describing the package
+% implementation.  Using |mdwtools.tex|, you just say |\implementation|, and
+% everything works.  It will automatically read in the licence text (from
+% |gpl.tex|, and wraps some other things up.
+%
+% 
+% \subsection{Other commands}
+%
+% The |mdwtools.tex| file includes the \package{syntax} and \package{sverb}
+% packages so that they can be used in documentation files.  It also defines
+% some trivial commands of its own.
+%
+% \DescribeMacro{\<}
+% Saying \syntax{"\\<"<text>">" is the same as "\\synt{"<text>"}"}; this
+% is a simple abbreviation.
+%
+% \DescribeMacro{\smallf}
+% Saying \syntax{"\\smallf" <number>"/"<number>} typesets a little fraction,
+% like this: \smallf 3/4.  It's useful when you want to say that the default
+% value of a length is 2 \smallf 1/2\,pt, or something like that.
+%
+%
+% \subsection{Customisation}
+%
+% You can customise the way that the package documentation looks by writing
+% a file called |mdwtools.cfg|.  You can redefine various commands (before
+% they're defined here, even; |mdwtools.tex| checks most of the commands that
+% it defines to make sure they haven't been defined already.
+%
+% \DescribeMacro{\indexing}
+% If you don't want the prompt about whether to generate index files, you
+% can define the |\indexing| command to either \lit{y} or \lit{n}.  I'd
+% recommend that you use |\providecommand| for this, to allow further
+% customisation from the command line.
+%
+% \DescribeMacro{\mdwdateformat}
+% If you don't like my date format (maybe you're American or something),
+% you can redefine the |\mdwdateformat| command.  It takes three arguments:
+% the year, month and date, as numbers; it should expand to something which
+% typesets the date nicely.  The default format gives something like
+% `10 May 1996'.  You can produce something rather more exotic, like
+% `10\textsuperscript{th} May \textsc{\romannumeral 1996}' by saying
+%\begin{listing}
+%\newcommand{\mdwdateformat}[3]{%
+%  \number#3\textsuperscript{\numsuffix{#3}}\ %
+%  \monthname{#2}\ %
+%  \textsc{\romannumeral #1}%
+%}
+%\end{listing}
+% \DescribeMacro{\monthname}
+% \DescribeMacro{\numsuffix}
+% Saying \syntax{"\\monthname{"<number>"}"} expands to the name of the
+% numbered month (which can be useful when doing date formats).  Saying
+% \syntax{"\\numsuffix{"<number>"}"} will expand to the appropriate suffix
+% (`th' or `rd' or whatever) for the \<number>.  You'll have to superscript
+% it yourself, if this is what you want to do.  Putting the year number
+% in roman numerals is just pretentious |;-)|.
+%
+% \DescribeMacro{\mdwhook}
+% After all the declarations in |mdwtools.tex|, the command |\mdwhook| is
+% executed, if it exists.  This can be set up by the configuration file
+% to do whatever you want.
+%
+% There are lots of other things you can play with; you should look at the
+% implementation section to see what's possible.
+%
+% \implementation
+%
+% \section{Implementation}
+%
+%    \begin{macrocode}
+%<*mdwtools>
+%    \end{macrocode}
+%
+% The first thing is that I'm not a \LaTeX\ package or anything official
+% like that, so I must enable `|@|' as a letter by hand.
+%
+%    \begin{macrocode}
+\makeatletter
+%    \end{macrocode}
+%
+% Now input the user's configuration file, if it exists.  This is fairly
+% simple stuff.
+%
+%    \begin{macrocode}
+\@input{mdwtools.cfg}
+%    \end{macrocode}
+%
+% Well, that's the easy bit done.
+%
+%
+% \subsection{Initialisation}
+%
+% Obviously the first thing to do is to obtain a document class.  Obviously,
+% it would be silly to do this if a document class has already been loaded,
+% either by the package documentation or by the configuration file.
+%
+% The only way I can think of for finding out if a document class is already
+% loaded is by seeing if the |\documentclass| command has been redefined
+% to raise an error.  This isn't too hard, really.
+%
+%    \begin{macrocode}
+\ifx\documentclass\@twoclasseserror\else
+  \documentclass[a4paper]{ltxdoc}
+  \ifx\doneclasses\mdw@undefined\else\doneclasses\fi
+\fi
+%    \end{macrocode}
+%
+% As part of my standard environment, I'll load some of my more useful
+% packages.  If they're already loaded (possibly with different options),
+% I'll not try to load them again.
+%
+%    \begin{macrocode}
+\@ifpackageloaded{doc}{}{\usepackage{doc}}
+\@ifpackageloaded{syntax}{}{\usepackage[rounded]{syntax}}
+\@ifpackageloaded{sverb}{}{\usepackage{sverb}}
+%    \end{macrocode}
+%
+%
+% \subsection{Some macros for interaction}
+%
+% I like the \LaTeX\ star-boxes, although it's a pain having to cope with
+% \TeX's space-handling rules.  I'll define a new typing-out macro which
+% makes spaces more significant, and has a $*$-version which doesn't put
+% a newline on the end, and interacts prettily with |\read|.
+%
+% First of all, I need to make spaces active, so I can define things about
+% active spaces.
+%
+%    \begin{macrocode}
+\begingroup\obeyspaces
+%    \end{macrocode}
+%
+% Now to define the main macro.  This is easy stuff.  Spaces must be
+% carefully rationed here, though.
+%
+% I'll start a group, make spaces active, and make spaces expand to ordinary
+% space-like spaces.  Then I'll look for a star, and pass either |\message|
+% (which doesn't start a newline, and interacts with |\read| well) or
+% |\immediate\write 16| which does a normal write well.
+%
+%    \begin{macrocode}
+\gdef\mdwtype{%
+\begingroup\catcode`\ \active\let \space%
+\@ifstar{\mdwtype@i{\message}}{\mdwtype@i{\immediate\write\sixt@@n}}%
+}
+\endgroup
+%    \end{macrocode}
+%
+% Now for the easy bit.  I have the thing to do, and the thing to do it to,
+% so do that and end the group.
+%
+%    \begin{macrocode}
+\def\mdwtype@i#1#2{#1{#2}\endgroup}
+%    \end{macrocode}
+%
+%
+% \subsection{Decide on indexing}
+%
+% A configuration file can decide on indexing by defining the |\indexing|
+% macro to either \lit{y} or \lit{n}.  If it's not set, then I'll prompt
+% the user.
+%
+% First of all, I want a switch to say whether I'm indexing.
+%
+%    \begin{macrocode}
+\newif\ifcreateindex
+%    \end{macrocode}
+%
+% Right: now I need to decide how to make progress.  If the macro's not set,
+% then I want to set it, and start a row of stars.
+%
+%    \begin{macrocode}
+\ifx\indexing\@@undefined
+  \mdwtype{*****************************}
+  \def\indexing{?}
+\fi
+%    \end{macrocode}
+%
+% Now enter a loop, asking the user whether to do indexing, until I get
+% a sensible answer.
+%
+%    \begin{macrocode}
+\loop
+  \@tempswafalse
+  \if y\indexing\@tempswatrue\createindextrue\fi
+  \if Y\indexing\@tempswatrue\createindextrue\fi
+  \if n\indexing\@tempswatrue\createindexfalse\fi
+  \if N\indexing\@tempswatrue\createindexfalse\fi
+  \if@tempswa\else
+  \mdwtype*{* Create index files? (y/n) *}
+  \read\sixt@@n to\indexing%
+\repeat
+%    \end{macrocode}
+%
+% Now, based on the results of that, display a message about the indexing.
+%
+%    \begin{macrocode}
+\mdwtype{*****************************}
+\ifcreateindex
+  \mdwtype{* Creating index files      *}
+  \mdwtype{* This may take some time   *}
+\else
+  \mdwtype{* Not creating index files  *}
+\fi
+\mdwtype{*****************************}
+%    \end{macrocode}
+%
+% Now I can play with the indexing commands of the \package{doc} package
+% to do whatever it is that the user wants.
+%
+%    \begin{macrocode}
+\ifcreateindex
+  \CodelineIndex
+  \EnableCrossrefs
+\else
+  \CodelineNumbered
+  \DisableCrossrefs
+\fi
+%    \end{macrocode}
+%
+% And register lots of plain \TeX\ things which shouldn't be indexed.
+% This contains lots of |\if|\dots\ things which don't fit nicely in
+% conditionals, which is a shame.  Still, it doesn't matter that much,
+% really.
+%
+%    \begin{macrocode}
+\DoNotIndex{\def,\long,\edef,\xdef,\gdef,\let,\global}
+\DoNotIndex{\if,\ifnum,\ifdim,\ifcat,\ifmmode,\ifvmode,\ifhmode,%
+            \iftrue,\iffalse,\ifvoid,\ifx,\ifeof,\ifcase,\else,\or,\fi}
+\DoNotIndex{\box,\copy,\setbox,\unvbox,\unhbox,\hbox,%
+            \vbox,\vtop,\vcenter}
+\DoNotIndex{\@empty,\immediate,\write}
+\DoNotIndex{\egroup,\bgroup,\expandafter,\begingroup,\endgroup}
+\DoNotIndex{\divide,\advance,\multiply,\count,\dimen}
+\DoNotIndex{\relax,\space,\string}
+\DoNotIndex{\csname,\endcsname,\@spaces,\openin,\openout,%
+            \closein,\closeout}
+\DoNotIndex{\catcode,\endinput}
+\DoNotIndex{\jobname,\message,\read,\the,\m@ne,\noexpand}
+\DoNotIndex{\hsize,\vsize,\hskip,\vskip,\kern,\hfil,\hfill,\hss}
+\DoNotIndex{\m@ne,\z@,\z@skip,\@ne,\tw@,\p@}
+\DoNotIndex{\dp,\wd,\ht,\vss,\unskip}
+%    \end{macrocode}
+%
+% Last bit of indexing stuff, for now: I'll typeset the index in two columns
+% (the default is three, which makes them too narrow for my tastes).
+%
+%    \begin{macrocode}
+\setcounter{IndexColumns}{2}
+%    \end{macrocode}
+%
+%
+% \subsection{Selectively defining things}
+%
+% I don't want to tread on anyone's toes if they redefine any of these
+% commands and things in a configuration file.  The following definitions
+% are fairly evil, but should do the job OK.
+%
+% \begin{macro}{\@gobbledef}
+%
+% This macro eats the following |\def|inition, leaving not a trace behind.
+%
+%    \begin{macrocode}
+\def\@gobbledef#1#{\@gobble}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\tdef}
+% \begin{macro}{\tlet}
+%
+% The |\tdef| command is a sort of `tentative' definition -- it's like
+% |\def| if the control sequence named doesn't already have a definition.
+% |\tlet| does the same thing with |\let|.
+%
+%    \begin{macrocode}
+\def\tdef#1{
+  \ifx#1\@@undefined%
+    \expandafter\def\expandafter#1%
+  \else%
+    \expandafter\@gobbledef%
+  \fi%
+}
+\def\tlet#1#2{\ifx#1\@@undefined\let#1=#2\fi}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsection{General markup things}
+%
+% Now for some really simple things.  I'll define how to typeset package
+% names and environment names (both in the sans serif font, for now).
+%
+%    \begin{macrocode}
+\tlet\package\textsf
+\tlet\env\textsf
+%    \end{macrocode}
+%
+% I'll define the |\<|\dots|>| shortcut for syntax items suggested in the
+% \package{syntax} package.
+%
+%    \begin{macrocode}
+\tdef\<#1>{\synt{#1}}
+%    \end{macrocode}
+%
+% And because it's used in a few places (mainly for typesetting lengths),
+% here's a command for typesetting fractions in text.
+%
+%    \begin{macrocode}
+\tdef\smallf#1/#2{\ensuremath{^{#1}\!/\!_{#2}}}
+%    \end{macrocode}
+%
+%
+% \subsection{A table environment}
+%
+% \begin{environment}{tab}
+%
+% Most of the packages don't use the (obviously perfect) \package{mdwtab}
+% package, because it's big, and takes a while to load.  Here's an
+% environment for typesetting centred tables.  The first (optional) argument
+% is some declarations to perform.  The mandatory argument is the table
+% preamble (obviously).
+%
+%    \begin{macrocode}
+\@ifundefined{tab}{%
+  \newenvironment{tab}[2][\relax]{%
+    \par\vskip2ex%
+    \centering%
+    #1%
+    \begin{tabular}{#2}%
+  }{%
+    \end{tabular}%
+    \par\vskip2ex%
+  }
+}{}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+%
+% \subsection{Commenting out of stuff}
+%
+% \begin{environment}{meta-comment}
+%
+% Using |\iffalse|\dots|\fi| isn't much fun.  I'll define a gobbling
+% environment using the \package{sverb} stuff.
+%
+%    \begin{macrocode}
+\ignoreenv{meta-comment}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+%
+% \subsection{Float handling}
+%
+% This gubbins will try to avoid float pages as much as possible, and (with
+% any luck) encourage floats to be put on the same pages as text.
+%
+%    \begin{macrocode}
+\def\textfraction{0.1}
+\def\topfraction{0.9}
+\def\bottomfraction{0.9}
+\def\floatpagefraction{0.7}
+%    \end{macrocode}
+%
+% Now redefine the default float-placement parameters to allow `here' floats.
+%
+%    \begin{macrocode}
+\def\fps@figure{htbp}
+\def\fps@table{htbp}
+%    \end{macrocode}
+%
+%
+% \subsection{Other bits of parameter tweaking}
+%
+% Make \env{grammar} environments look pretty, by indenting the left hand
+% sides by a large amount.
+%
+%    \begin{macrocode}
+\grammarindent1in
+%    \end{macrocode}
+%
+% I don't like being told by \TeX\ that my paragraphs are hard to linebreak:
+% I know this already.  This lot should shut \TeX\ up about most problems.
+%
+%    \begin{macrocode}
+\sloppy
+\hbadness\@M
+\hfuzz10\p@
+%    \end{macrocode}
+%
+% Also make \TeX\ shut up in the index.  The \package{multicol} package
+% irritatingly plays with |\hbadness|.  This is the best hook I could find
+% for playing with this setting.
+%
+%    \begin{macrocode}
+\expandafter\def\expandafter\IndexParms\expandafter{%
+  \IndexParms%
+  \hbadness\@M%
+}
+%    \end{macrocode}
+%
+% The other thing I really don't like is `Marginpar moved' warnings.  This
+% will get rid of them, and lots of other \LaTeX\ warnings at the same time.
+%
+%    \begin{macrocode}
+\let\@latex@warning@no@line\@gobble
+%    \end{macrocode}
+%
+% Put some extra space between table rows, please.
+%
+%    \begin{macrocode}
+\def\arraystretch{1.2}
+%    \end{macrocode}
+%
+% Most of the code is at guard level one, so typeset that in upright text.
+%
+%    \begin{macrocode}
+\setcounter{StandardModuleDepth}{1}
+%    \end{macrocode}
+%
+%
+% \subsection{Contents handling}
+%
+% I use at least one contents file (the main table of contents) although
+% I may want more.  I'll keep a list of contents files which I need to
+% handle.
+%
+% There are two things I need to do to contents files here:
+% \begin{itemize}
+% \item I must typeset the table of contents at the beginning of the
+%       document; and
+% \item I want to typeset tables of contents in two columns (using the
+%       \package{multicol} package).
+% \end{itemize}
+%
+% The list consists of items of the form
+% \syntax{"\\do{"<extension>"}{"<command>"}"}, where \<extension> is the
+% file extension of the contents file, and \<command> is the command to
+% typeset it.
+%
+% \begin{macro}{\docontents}
+%
+% This is where I keep the list of contents files.  I'll initialise it to
+% just do the standard contents table.
+%
+%    \begin{macrocode}
+\def\docontents{\do{toc}{\tableofcontents}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\addcontents}
+%
+% By saying \syntax{"\\addcontents{"<extension>"}{"<command>"}"}, a document
+% can register a new table of contents which gets given the two-column
+% treatment properly.  This is really easy to implement.
+%
+%    \begin{macrocode}
+\def\addcontents#1#2{%
+  \toks@\expandafter{\docontents\do{#1}{#2}}%
+  \edef\docontents{\the\toks@}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Finishing it all off}
+%
+% \begin{macro}{\finalstuff}
+%
+% The |\finalstuff| macro is a hook for doing things at the end of the
+% document.  Currently, it inputs the licence agreement as an appendix.
+%
+%    \begin{macrocode}
+\tdef\finalstuff{\appendix\part*{Appendix}\input{gpl}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\implementation}
+%
+% The |\implementation| macro starts typesetting the implementation of
+% the package(s).  If we're not doing the implementation, it just does
+% this lot and ends the input file.
+%
+% I define a macro with arguments inside the |\StopEventually|, which causes
+% problems, since the code gets put through an extra level of |\def|fing
+% depending on whether the implementation stuff gets typeset or not.  I'll
+% store the code I want to do in a separate macro.
+%
+%    \begin{macrocode}
+\def\implementation{\StopEventually{\attheend}}
+%    \end{macrocode}
+%
+% Now for the actual activity.  First, I'll do the |\finalstuff|.  Then, if
+% \package{doc}'s managed to find the \package{multicol} package, I'll add
+% the end of the environment to the end of each contents file in the list.
+% Finally, I'll read the index in from its formatted |.ind| file.
+%
+%    \begin{macrocode}
+\tdef\attheend{%
+  \finalstuff%
+  \ifhave@multicol%
+    \def\do##1##2{\addtocontents{##1}{\protect\end{multicols}}}%
+    \docontents%
+  \fi%
+  \PrintIndex%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{File version information}
+%
+% \begin{macro}{\mdwpkginfo}
+%
+% For setting up the automatic titles, I'll need to be able to work out
+% file versions and things.  This macro will, given a file name, extract
+% from \LaTeX\ the version information and format it into a sensible string.
+%
+% First of all, I'll put the original string (direct from the
+% |\Provides|\dots\ command).  Then I'll pass it to another macro which can
+% parse up the string into its various bits, along with the original
+% filename.
+%
+%    \begin{macrocode}
+\def\mdwpkginfo#1{%
+  \edef\@tempa{\csname ver@#1\endcsname}%
+  \expandafter\mdwpkginfo@i\@tempa\@@#1\@@%
+}
+%    \end{macrocode}
+%
+% Now for the real business.  I'll store the string I build in macros called
+% \syntax{"\\"<filename>"date", "\\"<filename>"version" and
+% "\\"<filename>"info"}, which store the file's date, version and
+% `information string' respectively.  (Note that the file extension isn't
+% included in the name.)
+%
+% This is mainly just tedious playing with |\expandafter|.  The date format
+% is defined by a separate macro, which can be modified from the
+% configuration file.
+%
+%    \begin{macrocode}
+\def\mdwpkginfo@i#1/#2/#3 #4 #5\@@#6.#7\@@{%
+  \expandafter\def\csname #6date\endcsname%
+    {\protect\mdwdateformat{#1}{#2}{#3}}%
+  \expandafter\def\csname #6version\endcsname{#4}%
+  \expandafter\def\csname #6info\endcsname{#5}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\mdwdateformat}
+%
+% Given three arguments, a year, a month and a date (all numeric), build a
+% pretty date string.  This is fairly simple really.
+%
+%    \begin{macrocode}
+\tdef\mdwdateformat#1#2#3{\number#3\ \monthname{#2}\ \number#1}
+\def\monthname#1{%
+  \ifcase#1\or%
+     January\or February\or March\or April\or May\or June\or%
+     July\or August\or September\or October\or November\or December%
+  \fi%
+}
+\def\numsuffix#1{%
+  \ifnum#1=1 st\else%
+  \ifnum#1=2 nd\else%
+  \ifnum#1=3 rd\else%
+  \ifnum#1=21 st\else%
+  \ifnum#1=22 nd\else%
+  \ifnum#1=23 rd\else%
+  \ifnum#1=31 st\else%
+  th%
+  \fi\fi\fi\fi\fi\fi\fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\mdwfileinfo}
+%
+% Saying \syntax{"\\mdwfileinfo{"<file-name>"}{"<info>"}"} extracts the
+% wanted item of \<info> from the version information for file \<file-name>.
+%
+%    \begin{macrocode}
+\def\mdwfileinfo#1#2{\mdwfileinfo@i{#2}#1.\@@}
+\def\mdwfileinfo@i#1#2.#3\@@{\csname#2#1\endcsname}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{List handling}
+%
+% There are several other lists I need to build.  These macros will do
+% the necessary stuff.
+%
+% \begin{macro}{\mdw@ifitem}
+%
+% The macro \syntax{"\\mdw@ifitem"<item>"\\in"<list>"{"<true-text>"}"^^A
+% "{"<false-text>"}"} does \<true-text> if the \<item> matches any item in
+% the \<list>; otherwise it does \<false-text>.
+%
+%    \begin{macrocode}
+\def\mdw@ifitem#1\in#2{%
+  \@tempswafalse%
+  \def\@tempa{#1}%
+  \def\do##1{\def\@tempb{##1}\ifx\@tempa\@tempb\@tempswatrue\fi}%
+  #2%
+  \if@tempswa\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\mdw@append}
+%
+% Saying \syntax{"\\mdw@append"<item>"\\to"<list>} adds the given \<item>
+% to the end of the given \<list>.
+%
+%    \begin{macrocode}
+\def\mdw@append#1\to#2{%
+  \toks@{\do{#1}}%
+  \toks\tw@\expandafter{#2}%
+  \edef#2{\the\toks\tw@\the\toks@}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\mdw@prepend}
+%
+% Saying \syntax{"\\mdw@prepend"<item>"\\to"<list>} adds the \<item> to the
+% beginning of the \<list>.
+%
+%    \begin{macrocode}
+\def\mdw@prepend#1\to#2{%
+  \toks@{\do{#1}}%
+  \toks\tw@\expandafter{#2}%
+  \edef#2{\the\toks@\the\toks\tw@}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\mdw@add}
+%
+% Finally, saying \syntax{"\\mdw@add"<item>"\\to"<list>} adds the \<item>
+% to the list only if it isn't there already.
+%
+%    \begin{macrocode}
+\def\mdw@add#1\to#2{\mdw@ifitem#1\in#2{}{\mdw@append#1\to#2}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Described file handling}
+%
+% I'l maintain lists of packages, document classes, and other files
+% described by the current documentation file.
+%
+% First of all, I'll declare the various list macros.
+%
+%    \begin{macrocode}
+\def\dopackages{}
+\def\doclasses{}
+\def\dootherfiles{}
+%    \end{macrocode}
+%
+% \begin{macro}{\describespackage}
+%
+% A document file can declare that it describes a package by saying
+% \syntax{"\\describespackage{"<package-name>"}"}.  I add the package to
+% my list, read the package into memory (so that the documentation can
+% offer demonstrations of it) and read the version information.
+%
+%    \begin{macrocode}
+\def\describespackage#1{%
+  \mdw@ifitem#1\in\dopackages{}{%
+    \mdw@append#1\to\dopackages%
+    \usepackage{#1}%
+    \mdwpkginfo{#1.sty}%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\describesclass}
+%
+% By saying \syntax{"\\describesclass{"<class-name>"}"}, a document file
+% can declare that it describes a document class.  I'll assume that the
+% document class is already loaded, because it's much too late to load
+% it now.
+%
+%    \begin{macrocode}
+\def\describesclass#1{\mdw@add#1\to\doclasses\mdwpkginfo{#1.cls}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\describesfile}
+%
+% Finally, other `random' files, which don't have the status of real \LaTeX\
+% packages or document classes, can be described by saying \syntax{^^A
+% "\\describesfile{"<file-name>"}" or "\\describesfile*{"<file-name>"}"}.
+% The difference is that the starred version will not |\input| the file.
+%
+%    \begin{macrocode}
+\def\describesfile{%
+  \@ifstar{\describesfile@i\@gobble}{\describesfile@i\input}%
+}
+\def\describesfile@i#1#2{%
+  \mdw@ifitem#2\in\dootherfiles{}{%
+    \mdw@add#2\to\dootherfiles%
+    #1{#2}%
+    \mdwpkginfo{#2}%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Author and title handling}
+%
+% I'll redefine the |\author| and |\title| commands so that I get told
+% whether I need to do it myself.
+%
+% \begin{macro}{\author}
+%
+% This is easy: I'll save the old meaning, and then redefine |\author| to
+% do the old thing and redefine itself to then do nothing.
+%
+%    \begin{macrocode}
+\let\mdw@author\author
+\def\author{\let\author\@gobble\mdw@author}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\title}
+%
+% And oddly enough, I'll do exactly the same thing for the title, except
+% that I'll also disable the |\mdw@buildtitle| command, which constructs
+% the title automatically.
+%
+%    \begin{macrocode}
+\let\mdw@title\title
+\def\title{\let\title\@gobble\let\mdw@buildtitle\relax\mdw@title}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\date}
+%
+% This works in a very similar sort of way.
+%
+%    \begin{macrocode}
+\def\date#1{\let\date\@gobble\def\today{#1}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\datefrom}
+%
+% Saying \syntax{"\\datefrom{"<file-name>"}"} sets the document date from
+% the given filename.
+%
+%    \begin{macrocode}
+\def\datefrom#1{%
+  \protected@edef\@tempa{\noexpand\date{\csname #1date\endcsname}}%
+  \@tempa%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\docfile}
+%
+% Saying \syntax{"\\docfile{"<file-name>"}"} sets up the file name from which
+% documentation will be read.
+%
+%    \begin{macrocode}
+\def\docfile#1{%
+  \def\@tempa##1.##2\@@{\def\@basefile{##1.##2}\def\@basename{##1}}%
+  \edef\@tempb{\noexpand\@tempa#1\noexpand\@@}%
+  \@tempb%
+}
+%    \end{macrocode}
+%
+% I'll set up a default value as well.
+%
+%    \begin{macrocode}
+\docfile{\jobname.dtx}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Building title strings}
+%
+% This is rather tricky.  For each list, I need to build a legible looking
+% string.
+%
+% \begin{macro}{\mdw@addtotitle}
+%
+% By saying
+%\syntax{"\\mdw@addtotitle{"<list>"}{"<command>"}{"<singular>"}{"<plural>"}"}
+% I can add the contents of a list to the current title string in the
+% |\mdw@title| macro.
+%
+%    \begin{macrocode}
+\tdef\mdw@addtotitle#1#2#3#4{%
+%    \end{macrocode}
+%
+% Now to get to work.  I need to keep one `lookahead' list item, and a count
+% of the number of items read so far.  I'll keep the lookahead item in
+% |\@nextitem| and the counter in |\count@|.
+%
+%    \begin{macrocode}
+  \count@\z@%
+%    \end{macrocode}
+%
+% Now I'll define what to do for each list item.  The |\protect| command is
+% already set up appropriately for playing with |\edef| commands.
+%
+%    \begin{macrocode}
+  \def\do##1{%
+%    \end{macrocode}
+%
+% The first job is to add the previous item to the title string.  If this
+% is the first item, though, I'll just add the appropriate \lit{The } or
+% \lit{ and the } string to the title (this is stored in the |\@prefix|
+% macro).
+%
+%    \begin{macrocode}
+    \edef\mdw@title{%
+      \mdw@title%
+      \ifcase\count@\@prefix%
+      \or\@nextitem%
+      \else, \@nextitem%
+      \fi%
+    }%
+%    \end{macrocode}
+%
+% That was rather easy.  Now I'll set up the |\@nextitem| macro for the
+% next time around the loop.
+%
+%    \begin{macrocode}
+    \edef\@nextitem{%
+      \protect#2{##1}%
+      \protect\footnote{%
+        The \protect#2{##1} #3 is currently at version %
+        \mdwfileinfo{##1}{version}, dated \mdwfileinfo{##1}{date}.%
+      }\space%
+    }%
+%    \end{macrocode}
+%
+% Finally, I need to increment the counter.
+%
+%    \begin{macrocode}
+    \advance\count@\@ne%
+  }%
+%    \end{macrocode}
+%
+% Now execute the list.
+%
+%    \begin{macrocode}
+  #1%
+%    \end{macrocode}
+%
+% I still have one item left over, unless the list was empty.  I'll add
+% that now.
+%
+%    \begin{macrocode}
+  \edef\mdw@title{%
+    \mdw@title%
+    \ifcase\count@%
+    \or\@nextitem\space#3%
+    \or\ and \@nextitem\space#4%
+    \fi%
+  }%
+%    \end{macrocode}
+%
+% Finally, if $|\count@| \ne 0$, I must set |\@prefix| to \lit{ and the }.
+%
+%    \begin{macrocode}
+  \ifnum\count@>\z@\def\@prefix{ and the }\fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\mdw@buildtitle}
+%
+% This macro will actually do the job of building the title string.
+%
+%    \begin{macrocode}
+\tdef\mdw@buildtitle{%
+%    \end{macrocode}
+%
+% First of all, I'll open a group to avoid polluting the namespace with
+% my gubbins (although the code is now much tidier than it has been in
+% earlier releases).
+%
+%    \begin{macrocode}
+  \begingroup%
+%    \end{macrocode}
+%
+% The title building stuff makes extensive use of |\edef|.  I'll set
+% |\protect| appropriately.  (For those not in the know,
+% |\@unexpandable@protect| expands to `|\noexpand\protect\noexpand|',
+% which prevents expansion of the following macro, and inserts a |\protect|
+% in front of it ready for the next |\edef|.)
+%
+%    \begin{macrocode}
+  \let\@@protect\protect\let\protect\@unexpandable@protect%
+%    \end{macrocode}
+%
+% Set up some simple macros ready for the main code.
+%
+%    \begin{macrocode}
+  \def\mdw@title{}%
+  \def\@prefix{The }%
+%    \end{macrocode}
+%
+% Now build the title.  This is fun.
+%
+%    \begin{macrocode}
+  \mdw@addtotitle\dopackages\package{package}{packages}%
+  \mdw@addtotitle\doclasses\package{document class}{document classes}%
+  \mdw@addtotitle\dootherfiles\texttt{file}{files}%
+%    \end{macrocode}
+%
+% Now I want to end the group and set the title from my string.  The
+% following hacking will do this.
+%
+%    \begin{macrocode}
+  \edef\next{\endgroup\noexpand\title{\mdw@title}}%
+  \next%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Starting the main document}
+%
+% \begin{macro}{\mdwdoc}
+%
+% Once the document preamble has done all of its stuff, it calls the
+% |\mdwdoc| command, which takes over and really starts the documentation
+% going.
+%
+%    \begin{macrocode}
+\def\mdwdoc{%
+%    \end{macrocode}
+%
+% First, I'll construct the title string.
+%
+%    \begin{macrocode}
+  \mdw@buildtitle%
+  \author{Mark Wooding}%
+%    \end{macrocode}
+%
+% Set up the date string based on the date of the package which shares
+% the same name as the current file.
+%
+%    \begin{macrocode}
+  \datefrom\@basename%
+%    \end{macrocode}
+%
+% Set up verbatim characters after all the packages have started.
+%
+%    \begin{macrocode}
+  \shortverb\|%
+  \shortverb\"%
+%    \end{macrocode}
+%
+% Start the document, and put the title in.
+%
+%    \begin{macrocode}
+  \begin{document}
+  \maketitle%
+%    \end{macrocode}
+%
+% This is nasty.  It makes maths displays work properly in demo environments.
+% \emph{The \LaTeX\ Companion} exhibits the bug which this hack fixes.  So
+% ner.
+%
+%    \begin{macrocode}
+  \abovedisplayskip\z@%
+%    \end{macrocode}
+%
+% Now start the contents tables.  After starting each one, I'll make it
+% be multicolumnar.
+%
+%    \begin{macrocode}
+  \def\do##1##2{%
+    ##2%
+    \ifhave@multicol\addtocontents{##1}{%
+      \protect\begin{multicols}{2}%
+      \hbadness\@M%
+    }\fi%
+  }%
+  \docontents%
+%    \end{macrocode}
+%
+% Input the main file now.
+%
+%    \begin{macrocode}
+  \DocInput{\@basefile}%
+%    \end{macrocode}
+%
+% That's it.  I'm done.
+%
+%    \begin{macrocode}
+  \end{document}
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{And finally\dots}
+%
+% Right at the end I'll put a hook for the configuration file.
+%
+%    \begin{macrocode}
+\ifx\mdwhook\@@undefined\else\expandafter\mdwhook\fi
+%    \end{macrocode}
+%
+% That's all the code done now.  I'll change back to `user' mode, where
+% all the magic control sequences aren't allowed any more.
+%
+%    \begin{macrocode}
+\makeatother
+%</mdwtools>
+%    \end{macrocode}
+%
+% Oh, wait!  What if I want to typeset this documentation?  Aha.  I'll cope
+% with that by comparing |\jobname| with my filename |mdwtools|.  However,
+% there's some fun here, because |\jobname| contains category-12 letters,
+% while my letters are category-11.  Time to play with |\string| in a messy
+% way.
+%
+%    \begin{macrocode}
+%<*driver>
+\makeatletter
+\edef\@tempa{\expandafter\@gobble\string\mdwtools}
+\edef\@tempb{\jobname}
+\ifx\@tempa\@tempb
+  \describesfile*{mdwtools.tex}
+  \docfile{mdwtools.tex}
+  \makeatother
+  \expandafter\mdwdoc
+\fi
+\makeatother
+%</driver>
+%    \end{macrocode}
+%
+% That's it.  Done!
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
diff --git a/poetry.dtx b/poetry.dtx
new file mode 100644
index 0000000..cfd0282
--- /dev/null
+++ b/poetry.dtx
@@ -0,0 +1,1242 @@
+% \begin{meta-comment}
+%
+% poetry.dtx
+%
+% Sophisticated typesetting of poetry
+%
+% (c) 1996 Mark Wooding
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% poetry package -- sophisticated typesetting of poetry
+%% Copyright (c) 1996 Mark Wooding
+%%
+%% This package is not finished, let alone properly tested.  It is being
+%% released in the hope that others can contribute ideas and suggestions
+%% that the author (who is not an expert on poetry) may have missed.
+%%
+%% I hope that someone finds this package useful.  However, if it goes
+%% wrong, that's your problem.  I may try and fix it, although the author
+%% does not guarantee that this is the case.
+%%
+%% This pre-release version may be distributed under the terms of the GNU
+%% General Public Licence, as published by the Free Software Foundation;
+%% either version 2 of the Licence, or (at your option) any later version.
+%% However, since this is not finished, and I'd like others to benefit
+%% from the finished version, the author BEGS and PLEADS you not to spread
+%% this pre-release too much.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preambles>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{poetry}
+%<+package>                [1996/05/28 1.00 Poetry typesetting]
+% \end{meta-comment}
+%
+% ^^A \CheckSum{579}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{poetry}
+\def\todo#1{%
+  \par\bigskip\noindent%
+  \fbox{\dimen0\hsize\advance\dimen0-2\fboxsep%
+        \parbox{\dimen0}%
+               {\vskip5pt\centerline{\bfseries TO DO}\vskip 12pt#1}}%
+  \par\bigskip}%
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+% \section{User guide}
+%
+% The \package{poem} package is designed to provide appropriate typesetting
+% for all manner of `sensible' poems, by which I mean not to exclude the
+% works of such great poets as Spike Milligan, but more those who lay out
+% their words to form pretty patterns: such works must be dealt with on
+% an individual basis, I'm afraid.
+%
+% An overview of the features provided wouldn't go amiss, I think.
+% \begin{itemize}
+%
+% \item Poems are normally centred on the page based on the length of
+%       the longest line.  This package handles this requirement, but
+%       allows poems to be left or right aligned if desired.
+%
+% \item Lines of poems are numbered, and may be labelled and referenced
+%       using the normal |\label| and |\ref| commands of \LaTeX.  Numbers
+%       are by default printed every 5 lines, on the right hand side, but
+%       this is fully configurable, as is the style of the numbers.
+%
+% \item Stanzas can be numbered, titled, either, neither or both.  Stanza
+%       numbers can be labelled and referenced.
+%
+% \end{itemize}
+%
+%
+% \subsection{Typesetting simple poems}
+%
+% \DescribeEnv{poem}
+% You can typeset a poem using the \env{poem} environment.  The lines of
+% the poem are separated by |\\| commands as usual.  Use the |\stanza*|
+% command to start new stanzas.  Something like this would do the job:
+%
+% \todo{There should be a demo here}
+%
+% Lines of a poem will be broken if they get too long.  However, a
+% `logical' line of a poem will never be broken between pages.\footnote{
+%   This is an artifact of the way I've implemented the poems.  I don't
+%   think it's a terribly nasty restriction.}
+% Continued lines are indented from the left margin by a fair distance,
+% so that they don't get confused with the starts of new lines.
+%
+% \DescribeMacro{\poemline}
+% You've probably noticed that the poem lines are numbered down the right
+% hand side.  This happens automatically, although you can turn it off if
+% it's inappropriate.  All the line numbers are generated by the command
+% |\poemline|, which you can define however you like.  Saying
+% \begin{listing}
+%\renewcommand{\poemline}{}
+% \end{listing}
+% will cause nothing to be printed for the line numbers, turning them off.
+%
+% \todo{A command to disable numbering?}
+%
+% \DescribeMacro{\title}
+% You can use the |\title| command to typeset a title for your poem.  The
+% title is inserted right there and then, so watch out.  It's conventional
+% to put the title at the top of the poem, although this is art we're talking
+% about, so who knows?  Just say \syntax{"\title{"<title>"}"}.
+%
+% \DescribeMacro{\author}
+% Similarly, the author of a poem can be credited with the |\author| command.
+% Just put the author's name in the argument.  Authors usually go at the
+% bottom of poems.
+%
+% \DescribeMacro{\poemtitle} \DescribeMacro{\poemauthor}
+% The |\title| and |\author| commands are implemented internally by the
+% commands |\poemtitle| and |\poemauthor|, which you can redefine if you
+% like.  You should probably have a look at the default definitions before
+% you do this: they use some little features which haven't been described
+% yet.  Don't be intimidated, though: I'll get to them later!
+%
+%
+% \subsection{Playing with stanzas}
+%
+% \DescribeMacro{\stanza}
+% The |\stanza| command is actually fairly complicated.  It always starts
+% a new stanza, leaving a gap if necessary after the previous line.
+% Also, the stanza will be numbered, unless you use the |\stanza*| command.
+% You can also give the stanza a title by saying
+% \syntax{"\\stanza["<title>"]"} (or |\stanza*|\dots\ if you don't want the
+% number).  The title and number are printed above the new stanza.
+%
+% \DescribeMacro{\labelstanza}
+% The stanza numbers are typeset by the command |\labelstanza| which you
+% can define however you like.  To disable them entirely, say
+% \begin{listing}
+%\renewcommand{\labelstanza}{}
+% \end{listing}
+%
+% There are a collection of other style parameters for stanza titles.  These
+% are described below (if you're not interested in this sort of thing, skip
+% to the next section).
+%
+% \begin{description} \def\makelabel#1{\hskip\labelsep\cmd{#1}\hfil}
+% \item [stanza] is a \LaTeX\ counter which contains the current stanza
+%       number.
+% \item [\thestanza] typesets the value of the |stanza| counter in normal
+%       text.
+% \item [\labelstanza] typesets the value of the |stanza| counter specially
+%       for use as a stanza title.  (The default style uses small caps here,
+%       which is generally inappropriate in running text.)
+% \item [\stanzaname] is a command with one argument which typesets a stanza
+%       title string, as passed to the |\stanza| command (not including the
+%       number).
+% \item [\stanzacombine] is given two arguments: a title (built by
+%       |\labelstanza|) and a title (formatted by |\stanzaname|).  It
+%       should format and space these two arguments.  It \emph{can't}
+%       change the font of this text -- it's too late for that now.
+%       This command is only used when both a number and a stanza title
+%       are given.
+% \item [\stanzaspace] is called with no arguments.  It should somehow
+%       separate the previous stanza (if any) from the new one.  Look at the
+%	counter value to find out whether this is the first stanza, if it
+%	matters (e.g., you're drawing little rows of stars or something).
+% \item [\stanzatitle] is given one argument: a `combined' title.  It should
+%       typeset the title as a line in LR mode.  Again, it's too late to
+%       play with fonts now.
+% \end{description}
+%
+% All of the commands described above are given fairly simple definitions
+% by default: you should be able to customise these without difficulty.
+%
+%
+% \subsection{Starting new lines}
+%
+% \DescribeMacro{\\}
+% New lines within a stanza are started with the |\\| command.  This always
+% starts a new line.  The |\\*| command (which forbids a following page
+% break) and the optional argument (which adds vertical space) are
+% fully supported.
+%
+% \DescribeMacro{\nl}
+% However, there's also a command |\nl| which works like |\\| (it has a
+% $*$-version and so on) except that it won't start a new line unless
+% there's something already on the current one.  This is useful in commands
+% like |\poemauthor| which want to typeset their text on a new line without
+% possibly leaving an ugly looking gap.
+%
+% For example, the definition of |\poemauthor| is:
+% \begin{listing}
+%\providecommand{\poemauthor}[1]{%
+%  \nl*[\smallskipamount]%
+%  \nonumber%
+%  \hfill\normalfont\itshape#1%
+%  \\%
+%}
+% \end{listing}
+% The important part to us is that |\nl*[\smallskipamount]| at the
+% beginning.  This starts a new line, making sure that there's no page
+% break between it and the previous line, and adds a little extra space
+% before the author's name.  The |\nonumber| command just prevents this line
+% from being numbered, since it's not actually part of the poem itself:
+% numbering is dealt with in detail in the next section.
+%
+%
+% \subsection{Line numbering}
+%
+% \DescribeMacro{\poemline}
+% I skimmed over line numbering earlier, because it's a bit complex.  I'll
+% start with the default definition of the |\poemline| command, which will
+% give me something specific to talk about.  The command is used to generate
+% the line number for the line which has \emph{just finished}.
+%
+% \begin{listing}
+%\providecommand{\poemline}{%
+%  \ifmultipleof{5}{\value{poemline}}%
+%    {\poemlineposition[r]{\scriptsize\thepoemline}}%
+%    {}%
+%  \refstepcounter{poemline}%
+%}
+% \end{listing}
+%
+% \DescribeMacro{\ifmultipleof}
+% The |\ifmultipleof{5}{\value{poemline}}|\dots\ construction restricts the
+% printed numbers to every fifth line (|\value{poemline}| is the value of
+% the |poemline| counter).  Saying
+% \syntax{"\\ifmultipleof{"$n$"}{"$x$"}{"<true>"}{"<false>"}"} will do
+% \<true> if~$x$ is a multiple of~$n$; otherwise it does \<false>.
+%
+% \DescribeMacro{\poemlineposition}
+% The |\poemlineposition| command positions its text to the right or
+% left of the poem, according to whether its optional argument is \lit{l}
+% or \lit{r}.
+%
+% So, the code up there just prints the poem line in small numbers on the
+% right hand side of every fifth line of the poem.  (Phew!)  It then steps
+% the counter so it'll be all right for cross-references in the next line
+% down.  Got that?
+%
+% \DescribeMacro{\nonumber}
+% Something a little simpler now: saying |\nonumber| in a line of poetry will
+% suppress the line number on that line.  The counter won't be stepped, and
+% no number is printed.  This is mainly useful in titles and other
+% adornments in poems.
+%
+%
+% \subsection{Other little extras}
+%
+% \DescribeEnv{xpoem}
+% The \env{poem} environment doesn't actually do a lot by itself.  If you
+% look at its definition, you'll see that it just starts a standard \LaTeX\
+% \env{verse} environment and then calls the \env{xpoem} environment to
+% do the actual work.  The idea is that you can then redefine \env{poem}
+% to do whatever setting up you want and then use \env{xpoem} to do
+% its typesetting magic.  For example, the definitions
+% \begin{listing}
+%\newcommand{\poemend}{}
+%\renewenvironment{poem}[2]{%
+%  \begin{verse}%
+%  \renewcommand{\poemend}{\author{#2}}%
+%  \begin{xpoem}%
+%  \title{#1}%
+%}{%
+%  \poemend%
+%  \end{xpoem}%
+%  \end{verse}%
+%}
+% \end{listing}
+% modifies the environment so that it takes two arguments, the title and
+% the author, and sets them at the beginning and end of the poem
+% respectively.
+%
+% \TeX\ hackers who know about such things could make a \env{poem}
+% environment which `obeys' line breaks in the input file by making active
+% newlines do an |\nl| command.  The possibilities are endless.
+%
+% \DescribeMacro{\splitline}
+% The |\splitline| command should be used at the start of a new line (it
+% starts a new line all by itself otherwise).  It shunts all the text of
+% the line to the right so that it starts where the previous line finished.
+%
+% \todo{Come up with an example for this}
+%
+%
+% \implementation
+%
+% \section{Implementation}
+%
+% \subsection{Various allocations}
+%
+% I need a shocking number of allocations for this package to work.  I'll
+% start with the counters, because they're probably the most reasonable.
+%
+% |poem@count| keeps track of which poem this is, so I can look up the
+% width in my magic list (I'll describe width handling later in detail).
+% |poemline| is a user-level counter which keeps track of the current line
+% number.  |stanza| keeps track of the current stanza number.
+%
+% The |\poemchunksize| counter (which is also faked as a \LaTeX\ counter)
+% tells me how big a chunk should be.  The final counter, |\poem@linesleft|
+% tells me how many more lines I can do in this chunk.
+%
+% All the counters are assigned globally, or at least they should be.
+%
+%    \begin{macrocode}
+\newcounter{poem@count}
+\newcounter{poemline}
+\newcount\poemchunksize
+\let\c@poemchunksize\poemchunksize
+\newcount\poem@linesleft
+\poemchunksize=30
+%    \end{macrocode}
+%
+% Now for some length registers.  |\poem@width| contains the width of the
+% poem as read from the |.aux| file; |\poem@thiswidth| contains the width
+% of the longest line read so far.  Both of these are updated as I go through
+% the poem.  The final value of |\poem@thiswidth| is written back to the
+% list when all's finished.
+%
+% |\poem@lastwidth| contains the width of the last line -- it's used in
+% handling |\splitline|s.  |\poem@prevdepth| is used to fiddle |\prevdepth|
+% when handling long lines.
+%
+% All of these length parameters should be modified globally at all times.
+%
+%    \begin{macrocode}
+\newdimen\poem@width
+\newdimen\poem@thiswidth
+\newdimen\poem@lastwidth
+\newdimen\poem@prevdepth
+%    \end{macrocode}
+%
+% The switch |\ifpoem@long| is used to decide whether we need to save the
+% poem width in the aux file.
+%
+%    \begin{macrocode}
+\newif\ifpoem@long
+%    \end{macrocode}
+%
+% Lastly, a skip register.  This is the glue on the left hand side of a 
+% poem.  It should be |\@centering| to center the poem horizontally, or
+% something rigid and nonzero to left-align.
+%
+%    \begin{macrocode}
+\newskip\poemleftskip
+\poemleftskip\@centering
+%    \end{macrocode}
+%
+%
+% \subsection{Handling poem widths}
+%
+% Poems are horizontally centred, based on the width of their longest line.
+% This can be done without too many problems using an |\halign|.  However,
+% this would require \TeX\ to read in the whole poem before being able to lay
+% out the first line; this is clearly impractical for something like
+% \emph{The Rime of the Ancient Mariner}.
+%
+% The solution is fairly similar to that used by the \package{longtable}
+% package.  I'll divide a poem up into chunks, centring each chunk
+% horizontally.  I'll also keep track of the longest line so far, and make
+% sure that it affects each chunk, so as to prevent the chunks looking odd.
+% When all's finished, I'll write a list containing the widths of all the
+% poems to the |.aux| file so that next time everything will look nice.
+%
+% The list is held in just one macro, which contains entries of the form
+% \syntax{"["<poem-number>"]{"<width>"}"}.  I build the new updated
+% list in another macro as I go -- this version will be written to the
+% |.aux| file at the very end, to ensure that inserted or removed poems
+% don't mess anything up permanently.  It also avoids problems to do with
+% poem widths decreasing, which gives \package{longtable} a bit of a
+% headache.
+%
+% These two macros are always assigned globally.
+%
+%    \begin{macrocode}
+\def\poem@widths{}
+\def\poem@savedwidths{}
+%    \end{macrocode}
+%
+% \begin{macro}{\poem@getwidth}
+%
+% The width of the current poem can be read using this macro.  It assigns
+% the width to the |\poem@width| register; it gets the value 0\,pt if no
+% value for this poem actually exists.
+%
+%    \begin{macrocode}
+\def\poem@getwidth#1{%
+  \def\@tempa##1[#1]##2##3\@@{##2}%
+  \global\poem@width\expandafter\@tempa\poem@savedwidths[#1]\z@\@@%
+  \relax%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\poem@setwidth}
+%
+% I can also write the width of the current poem using this macro.  It
+% updates the new improved list with the value of |\poem@thiswidth|.
+%
+%    \begin{macrocode}
+\def\poem@setwidth#1{%
+  \def\@tempb##1[#1]\z@{##1}%
+  \def\@tempa##1[#1]##2##3\@@{%
+    \xdef\poem@widths{%
+      ##1%
+      [#1]{\the\poem@thiswidth}%
+      \ifdim##2=\z@\else\expandafter\@tempb\fi##3%
+    }%
+  }%
+  \expandafter\@tempa\poem@widths[#1]\z@\@@%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% At the very end of the document, I want to write the poem widths to the
+% |.aux| file.  The following code will do the job nicely.
+%
+%    \begin{macrocode}
+\AtEndDocument{%
+  \if@filesw%
+    \immediate\write\@auxout%
+      {\gdef\noexpand\poem@savedwidths{\poem@widths}}%
+  \fi%
+}
+%    \end{macrocode}
+%
+%
+% \subsection{Some little details}
+%
+% \begin{macro}{\@maybe@unskip}
+%
+% This macro solves a little problem.  In an alignment (and in other places)
+% it's desirable to suppress trailing space.  The usual method, to say
+% |\unskip|, is a little hamfisted, because it removes perfectly reasonable
+% aligning spaces like |\hfil|s.  While as a package writer I can deal with
+% this sort of thing by saying |\kern\z@| in appropriate places, it can
+% annoy users who are trying to use |\hfill| to override alignment in funny
+% places.
+%
+% My current solution seems to be acceptable.  I'll remove the natural width
+% of the last glue item, so that it can still stretch and shrink if
+% necessary.  The implementation makes use of the fact that multiplying
+% a \<skip> by a \<number> kills off the stretch.
+%
+%    \begin{macrocode}
+\def\@maybe@unskip{\hskip-\@ne\lastskip\relax}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Line numbering}
+%
+% Poem lines are numbered in a fairly sensible and normal way.  However, it's
+% not normal to number every single line.  The macro |\poemline| below will
+% decide whether and how to number a line.
+%
+% \begin{macro}{\ifmultipleof}
+%
+% This macro is called as
+% \syntax{"\\ifmultipleof{"$n$"}{"$x$"}{"<true>"}{"<false>"}"}.  If the
+% number~$x$ is a multiple of~$n$, then the whole lot expands to \<true>;
+% otherwise it expands to \<false>.  The test here relies on \TeX\ doing
+% integer division (which it does).
+%
+%    \begin{macrocode}
+\def\ifmultipleof#1#2{%
+  \count@#2%
+  \divide\count@#1%
+  \multiply\count@#1%
+  \relax%
+  \ifnum#2=\count@%
+    \expandafter\@firstoftwo%
+  \else%
+    \expandafter\@secondoftwo%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\poemlineposition}
+%
+% This macro typesets its argument relative to the poem in some neat way.
+% It's called as \syntax{"\\poemlineposition["<posn>"]{"<text>"}"}.  The
+% \<posn> may be \lit{l} or \lit{r}, where `l' and `r' mean left and right
+% respectively.
+%
+% This command only produces at all sensible results when typesetting poem
+% line numbers.
+%
+%    \begin{macrocode}
+\def\poemlineposition{\@ifnextchar[\poem@lp@i{\poem@lp@i[l]}}
+%    \end{macrocode}
+%
+% Now there's some sorting out to do.  If the number is to go on the
+% right, then there's no problem: it can just be typeset as it is.
+% Positioning on the left isn't too hard either -- I just need to shift the
+% number to the left by |\linewidth| plus a bit for niceness.
+%
+%    \begin{macrocode}
+\def\poem@lp@i[#1]#2{%
+  \if#1r%
+    \hfil\kern8\p@#2%
+  \else\if#1l%
+    \llap{#2\kern8\p@\kern\linewidth}%
+  \fi\fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\poemline}
+%
+% The default definition of |\poemline| will put a line number in script
+% size (so as not to appear too obvious) on every fifth line.
+%
+%    \begin{macrocode}
+\providecommand{\poemline}{%
+  \ifmultipleof{5}{\value{poemline}}%
+    {\poemlineposition[r]{\scriptsize\thepoemline}}%
+    {}%
+  \refstepcounter{poemline}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{The main environment}
+%
+% \begin{environment}{xpoem}
+%
+% The \env{xpoem} environment is where the nastiness really starts. 
+% Actually, the early bit is simple enough.
+%
+% This environment has a funny name, so that users and style designers can
+% define a usable `poem' environment the way they want.  Typically this
+% will involve playing with some parameters, maybe setting up some active
+% characters in a funny way, and probably adding a list environment to
+% provide appropriate indentation on the left and right sides.
+%
+%    \begin{macrocode}
+\def\xpoem{%
+%    \end{macrocode}
+%
+% The first thing to do is to reset the line number counter.
+%
+%    \begin{macrocode}
+  \global\c@poemline\z@%
+%    \end{macrocode}
+%
+% Now for some hookery -- the internal |\poem@printline| command will do
+% the job of deciding whether to print a line number or not on the current
+% line.  Unless otherwise disabled, this will be equal to |\poemline|.
+%
+%    \begin{macrocode}
+  \global\let\poem@printline\poemline%
+%    \end{macrocode}
+%
+% The |\nonumber| command, which is also used by \env{eqnarray},\footnote{^^A
+%   Just a plug: check out the improved \env{eqnarray} environment in the
+%   \package{mathenv} package!}
+% suppresses numbering of the current line by changing |\poem@printline|.
+% It will be reset by the next line end, so it only applies to a single line.
+%
+%    \begin{macrocode}
+  \def\nonumber{\global\let\poem@printline\@empty}%
+%    \end{macrocode}
+%
+% The |\title| and |\author| commands need redefining.  I'll set these
+% equal to some user-configurable commands below.
+%
+%    \begin{macrocode}
+  \let\title\poemtitle%
+  \let\author\poemauthor%
+%    \end{macrocode}
+%
+% Do some nasty things to make lists work properly.
+%
+%    \begin{macrocode}
+  \global\@inlabelfalse%
+  \global\@newlistfalse%
+%    \end{macrocode}
+%
+% Now it's time to start the alignment.  I'll clear the |\everycr| tokens,
+% and set up the |\\| command.  I'll make |\par| expand to nothing exciting,
+% so that blank lines in poems won't mess anything up, and set up the
+% `outside' meaning of |\nl|.
+%
+%    \begin{macrocode}
+  \everycr{}%
+  \let\\\poem@cr%
+  \def\nl{\poem@nl}%
+  \global\let\poem@nl\poem@donl%
+  \let\par\@empty%
+%    \end{macrocode}
+%
+% Now to set the widths of the poem.  |\poem@width| is read from the |.aux|
+% file from the \emph{last} time the poem was typeset, and is used to set
+% the width \emph{this} time, while |\poem@thiswidth| is initially zero,
+% and is set up as we go through \emph{this} time, and will be used to
+% set the actual poem width \emph{next} time.  Is that clear?  No?  Oh, well.
+%
+%    \begin{macrocode}
+  \expandafter\poem@getwidth\expandafter{\the\c@poem@count}%
+  \global\poem@thiswidth\z@%
+  \global\poem@longfalse
+%    \end{macrocode}
+%
+% Now some hacking to position the poem horizontally.  I need to inspect the
+% current list margins, so as to make it look right.  I'll set |\dimen@| to
+% be the size of the right hand margin.
+%
+%    \begin{macrocode}
+  \dimen@\hsize%
+  \advance\dimen@-\@totalleftmargin%
+  \advance\dimen@-\linewidth%
+%    \end{macrocode}
+%
+% Now for some silly little things before I really get going.  Leave some
+% vertical space, and step the counter ready for the first line.
+%
+%    \begin{macrocode}
+  \bigskip%
+  \stepcounter{poemline}%
+  \def\@currentlabel{\p@poemline\thepoemline}%
+%    \end{macrocode}
+%
+% Other things may want to add their declarations here.  I'll provide a hook.
+%
+%    \begin{macrocode}
+  \poem@hook%
+%    \end{macrocode}
+%
+% Now start the first poem chunk and give control to the user.
+%
+%    \begin{macrocode}
+  \poem@startchunk%
+}
+%    \end{macrocode}
+%
+% That's the start of the environment done; what happens at the end?  Well,
+% some fairly simple things, actually.
+%
+%    \begin{macrocode}
+\def\endxpoem{%
+%    \end{macrocode}
+%
+% First of all, I forcibly truncate this chunk of poem.
+%
+%    \begin{macrocode}
+  \nl%
+  \poem@endchunk%
+%    \end{macrocode}
+%
+% Now, if the poem is longer than the chunk size, I'll add it to the new
+% width list.  If it's shorter than the chunk size, there's no need to do
+% this, since \TeX\ will always work out the correct width `in time'.
+%
+%    \begin{macrocode}
+  \ifnum\c@poemline>\poemchunksize\poem@longtrue\fi%
+  \ifpoem@long%
+    \expandafter\poem@setwidth\expandafter{\the\c@poem@count}%
+  \fi%
+%    \end{macrocode}
+%
+% Now I'll step the poem counter, leave a little gap, and end the
+% environment.
+%
+%    \begin{macrocode}
+  \global\advance\c@poem@count\@ne%
+  \bigskip%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{macro}{\poem@hook}
+%
+% The hook used above in |\poem| starts off empty.  Macro packages can add
+% to it later.
+%
+%    \begin{macrocode}
+\def\poem@hook{}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\poem@addtohook}
+%
+% Packages add to that hook by saying
+% \syntax{"\\poem@addtohook{"<declarations>"}"}.  This is truly trivial.
+%
+%    \begin{macrocode}
+\def\poem@addtohook#1{%
+  \expandafter\def\expandafter\poem@hook\expandafter{\poem@hook#1}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% I'll take a break from the deep hacking for a while, and implement some
+% style things.  These commands should be redefined to alter the style of
+% the poems.  (I've tried hard to make them as simple as possible.)
+%
+% \begin{macro}{\poemtitle}
+%
+% Poem titles are large, bold, and centred.  The |\nl| command starts a new
+% row if necessary.  I want to avoid a page break after the title, for
+% obvious reasons.
+%
+%    \begin{macrocode}
+\providecommand{\poemtitle}[1]{%
+  \nl%
+  \nonumber%
+  \hfill\normalfont\large\bfseries#1\hfill%
+  \\*[\bigskipamount]%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\poemauthor}
+%
+% Authors are typeset in italics, right aligned.
+%
+%    \begin{macrocode}
+\providecommand{\poemauthor}[1]{%
+  \nl*[\smallskipamount]%
+  \nonumber%
+  \hfill\normalfont\itshape#1%
+  \\%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Poem chunk handling}
+%
+% Poems are divided into chunks to save \TeX's memory.  Chunks are started
+% like this:
+%
+% \begin{macro}{\poem@startchunk}
+%
+%    \begin{macrocode}
+\def\poem@startchunk{%
+%    \end{macrocode}
+%
+% Reset the `lines left' counter.  When this hits zero, I end the chunk and
+% start another one.
+%
+%    \begin{macrocode}
+  \global\poem@linesleft\poemchunksize%
+%    \end{macrocode}
+%
+% Now for the alignment itself.  The poem is centred by tabskip glue around
+% its first column.  There are an infinite number of zero-width columns off
+% to the right, in which the line numbers are typeset (this avoids problems
+% if users accidentally tab over to the next column).
+%
+% The `main' column is a bit odd.  It reads the text into a box, which is
+% global to preserve save stack space, and then calls a macro |\poem@doline|
+% to typeset the text in the box correctly.
+%
+%    \begin{macrocode}
+  \skip@\@totalleftmargin%
+  \advance\skip@\poemleftskip%
+  \tabskip\skip@%
+  \halign to\hsize\bgroup%
+    \global\let\poem@nl\poem@cr%
+    \global\setbox\@ne\hbox{{\ignorespaces##\@maybe@unskip}}\poem@doline%
+    \tabskip\@centering&&%
+    \poem@rightcolumn\hbox{{##}}\tabskip\dimen@\cr%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\poem@endchunk}
+%
+% This is really easy.  I end the line, in case it hasn't been ended already
+% (although it should have been), and end the alignment.
+%
+%    \begin{macrocode}
+\def\poem@endchunk{%
+  \crcr%
+  \noalign{\global\dimen@i\prevdepth\nointerlineskip}%
+  \omit\hb@xt@\poem@width{}\cr%
+  \egroup%
+  \prevdepth\dimen@i%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Typesetting poem lines}
+%
+% \begin{macro}{\poem@doline}
+%
+% This is where most of the real mess lies.  Given a line of doggerel in
+% box~1, I must typeset it beautifully.
+%
+%    \begin{macrocode}
+\def\poem@doline{%
+%    \end{macrocode}
+%
+% In order to know whether I need to split the line, I must know how wide
+% the line number is.  (Judging from the books I've seen, lines are allowed
+% to encroach on the space allocated to line numbers, as long as there isn't
+% a number on this line.  Maybe as a future extension, I could decide whether
+% it might be better to suppress this line, and maybe force a number for
+% the next one since it won't fit here.)
+%
+% Anyway, I'll do this the easy way.  I'll work out the width of the line
+% number, and subtract it from the basic line width.
+%
+%    \begin{macrocode}
+  \dimen@\linewidth%
+  \global\setbox\@labels\hbox{\poem@printline}%
+  \advance\dimen@-\wd\@labels%
+%    \end{macrocode}
+%
+% If the width of the doggerel is wider than |\dimen@|, I must split the
+% text over more than one line, or at least I must try to.  (\TeX\ may
+% be able to squeeze the text onto one line by shrinking the glue, so I've
+% got to watch out for this possibility.)
+%
+%    \begin{macrocode}
+  \ifdim\wd\@ne>\dimen@%
+%    \end{macrocode}
+%
+% I'll now put the text in a vbox, so I can play with it.  The parshape
+% is set up so that the first line misses the line number (if there is
+% one), while subsequent lines are indented, but take up the full available
+% width of the page.  The text is not indented (just to make sure).
+%
+% The messing with |\leftskip| and the initial kern provides the indentation,
+% and saves a little arithmetic.  There is a more plausible historical reason
+% for it too.
+%
+%    \begin{macrocode}
+    \global\setbox\@ne\vtop{%
+      \parshape\tw@ \z@\dimen@ \z@\linewidth%
+      \leftskip3em%
+      \noindent%
+      \kern-3em%
+      \unhbox\@ne%
+      \@@par%
+    }%
+%    \end{macrocode}
+%
+% Since table cells are set in LR mode, the baselineskip glue will be set
+% all wrong underneath this line.  I also need to set |\poem@lastwidth|
+% correctly.  I'll copy the box to another box, and pick off the bottom line
+% so I can peek inside.
+%
+% I'll set |\poem@prevdepth| from the depth of the box (this will be set
+% properly at the end of the line).  I'll also rip that box apart, remove
+% the |\parfillskip| glue, and rebox it in an attempt to calculate
+% |\poem@lastwidth|.  This isn't perfect, since the line might actually be
+% shrinking instead of stretching.  This is unlikely, though.
+%
+%    \begin{macrocode}
+    \global\setbox\thr@@\vbox{%
+      \unvcopy\@ne%
+      \global\setbox\thr@@\lastbox%
+      \global\poem@prevdepth\dp\thr@@%
+      \global\setbox\thr@@\hbox{\unhbox\thr@@\unskip}%
+      \global\poem@lastwidth\wd\thr@@%
+    }%
+%    \end{macrocode}
+%
+% Now that's done, I can output the box.  I'll clear box~3, which I
+% vandalised above.  I also know that the line was too long, so I can
+% set the poem widths to |\linewidth| with impunity.
+%
+%    \begin{macrocode}
+    \box\@ne%
+    \global\setbox\thr@@\box\voidb@x%
+    \global\poem@width\linewidth%
+    \global\poem@thiswidth\linewidth%
+  \else%
+%    \end{macrocode}
+%
+% If it fits, I can update the widths if necessary, set |\poem@lastwidth|,
+% and spew out the text.  Finally, I'll set |\poem@prevdepth| to a sentinel
+% value meaning `don't change'.
+%
+%    \begin{macrocode}
+    \ifdim\wd\@ne>\poem@width\global\poem@width\wd\@ne\fi%
+    \ifdim\wd\@ne>\poem@thiswidth\global\poem@thiswidth\wd\@ne\fi%
+    \global\poem@lastwidth\wd\@ne%
+    \unhbox\@ne\hfil%
+    \global\poem@prevdepth\maxdimen%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Starting a new line}
+%
+% There are two different routes to starting new lines.  The |\\| command
+% always starts a new line.  The command |\nl| will work out if
+% the current line hasn't been started yet, and behaves appropriately.
+%
+% \begin{macro}{\poem@cr}
+%
+% The |\poem@cr| macro implements the |\\| command and the |\nl|
+% command once a new line has been started.
+%
+% First, I need to pick out the optional arguments.  All the standard hacking
+% for doing newlines in alignments appears here.  If you want detailed
+% commentary, look somewhere else -- this is humdrum stuff now.
+%
+%    \begin{macrocode}
+\def\poem@cr{%
+  \relax%
+  \global\let\poem@nl\poem@donl%
+  \iffalse{\fi\ifnum0=`}\fi%
+  \@ifstar{\poem@cr@i\@M}{\poem@cr@i\z@}%
+}
+\def\poem@cr@i#1{\@ifnextchar[{\poem@cr@ii{#1}}{\poem@cr@ii{#1}[\z@]}}
+%    \end{macrocode}
+%
+% That's the standard hacking over.  Here's the tricky bit.
+%
+%    \begin{macrocode}
+\def\poem@cr@ii#1[#2]{%
+  \ifnum0=`{}\fi%
+%    \end{macrocode}
+%
+% First of all, I must clear the command which raises an error in the right
+% hand column.  Then I'll enter the column and insert the line number (which
+% was stored in |\@labels| for safekeeping).
+%
+%    \begin{macrocode}
+  \global\let\poem@rightcolumn\relax%
+  &\relax%
+  \llap{\unhbox\@labels}%
+%    \end{macrocode}
+%
+% Now I'll reset the various hooks and things ready for the next like.
+%
+%    \begin{macrocode}
+  \global\let\poem@printline\poemline%
+  \global\let\poem@rightcolumn\poem@@rightcolumn%
+%    \end{macrocode}
+%
+% Now to decide whether to start a new chunk.  I'll decrement the counter,
+% and if it reaches zero, I'll end that chunk and start a new one.
+%
+%    \begin{macrocode}
+  \global\advance\poem@linesleft\m@ne%
+  \ifnum\poem@linesleft=\z@%
+    \poem@endchunk%
+    \expandafter\poem@startchunk%
+  \else%
+    \expandafter\cr%
+  \fi%
+%    \end{macrocode}
+%
+% Finally, if I had a split line, I must change the |\prevdepth| setting to
+% keep everyone happy.
+%
+%    \begin{macrocode}
+  \noalign{%
+    \addpenalty{#1}%
+    \vskip#2%
+    \ifdim\poem@prevdepth=\maxdimen\else\prevdepth\poem@prevdepth\fi%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\poem@donl}
+%
+% The |\poem@nl| macro implements |\nl| during those `in-between' times
+% outside of a line of doggerel.  This is actually spectacularly easy.
+%
+%    \begin{macrocode}
+\def\poem@donl{%
+  \noalign{\ifnum0=`}\fi%
+  \@ifstar{\poem@donl@i{\addpenalty\@M}}{\poem@donl@i{}}%
+}
+\def\poem@donl@i#1{%
+  \@ifnextchar[{\poem@donl@ii{#1}}{\poem@donl@ii{#1}[\z@]}%
+}
+\def\poem@donl@ii#1[#2]{%
+  #1%
+  \addvspace{#2}%
+  \ifnum0=`{\fi}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsection{Other things}
+%
+% Well, that's all that I actually need to supply; everything else can be
+% added over the top.
+%
+% \begin{macro}{\splitline}
+%
+% Some books appear to split lines, starting the second where the first
+% ends.  This is easy to handle with the |\splitline| command.
+%
+%    \begin{macrocode}
+\def\splitline{\nl\nonumber\kern\poem@lastwidth\ }
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\stanza}
+%
+% New stanzas are started using the |\stanza| command, oddly enough.  There's
+% a problem, though: to number, or not to number?  Following the example of
+% \LaTeX's sectioning commands, I'll not number if there's a following $*$.
+% I don't really think that this is the right thing to do, since unnumbered
+% stanzas are much more common than numbered ones.  This is actually a real
+% pain.
+%
+% Anyway, if I'm going to handle numbered stanzas, I'll need a counter.
+%
+%    \begin{macrocode}
+\newcounter{stanza}
+%    \end{macrocode}
+%
+% Whatever happens, I'll start by adding in some vertical space above the
+% stanza.  Then I'll see if there's a following $*$.  If so, step the counter
+% and typeset the number; otherwise do nothing.  However, there's a snaglet
+% here: |\@ifstar| will do assignments and things, and start the next row of
+% the alignment prematurely.  I'll do the work in a |\noalign| to avoid
+% problems.  (Yuk.)
+%
+%    \begin{macrocode}
+\def\stanza{%
+  \nl%
+  \noalign{\ifnum0=`}\fi%
+  \@ifstar{%
+    \stanza@i{}%
+  }{%
+    \stanza@i{\global\advance\c@stanza\@ne\labelstanza}%
+  }%
+}
+%    \end{macrocode}
+%
+% OK\@.  Now I have to see if there's an optional argument.  I'm still safely
+% inside that |\noalign|, remember.
+%
+%    \begin{macrocode}
+\def\stanza@i#1{\@ifnextchar[{\stanza@ii{#1}}{\stanza@ii{#1}[]}}
+%    \end{macrocode}
+%
+% I can now read the argument, and decide what actually needs to be done.
+%
+%    \begin{macrocode}
+\def\stanza@ii#1[#2]{%
+%    \end{macrocode}
+%
+% I want to be able to allow |\label|s inside the optional argument.
+% However, I also want to be able to see whether the number and/or title
+% is `empty', bearing in mind that the title may contain just a |\label|,
+% which shouldn't alter the spacing; which means really that I ought to put
+% them into boxes and measure them.  But this stops |\refstepcounter|'s
+% setting of |\@currentlabel| (in the `number' box) being noticed by the
+% possible |\label| command in the other box.  I \emph{could} say something
+% like
+% \begin{listing}
+%\refstepcounter{stanza}
+%\addtocounter{stanza}{-1}
+% \end{listing}
+% which will do what I want, but defining |\@currentlabel| by hand is
+% considerably easier, and more efficient.
+%
+%    \begin{macrocode}
+  \def\@currentlabel{\p@stanza\thestanza}%
+  \sbox\z@{#1}%
+  \sbox\tw@{\stanzaname{#2}}%
+%    \end{macrocode}
+%
+% There are essentially four possibilities:
+% \begin{itemize}
+% \item There's nothing to typeset at all.  This is easy: don't typeset
+%       anything.
+% \item There's a number, but no title.
+% \item There's a title, but no number.
+% \item There's both a title \emph{and} a number.
+% \end{itemize}
+% The tricky bit is the last possibility, since I don't know how the two
+% will be separated.  Oh, well: I'll just have to use a load of user macros.
+%
+% As a first attempt, I'll put the thing to typeset into box~0.  This is
+% fairly simple.  If there's a title, then I check if there's a number too:
+% if so, I'll combine them both into box~0; otherwise I can just copy the
+% box over.  If there's anything to typeset at this point, it'll be in
+% box~0.  However, I'm currently in a |\noalign|, and that introduces a
+% level of grouping.  So I'll then move the box into box~1, which is global.
+%
+%    \begin{macrocode}
+  \ifdim\wd\tw@>\z@%
+    \ifdim\wd\z@>\z@%
+      \global\setbox\@ne\hbox{\stanzacombine{\unhbox\z@}{\unhbox\tw@}}%
+    \else%
+      \global\setbox\@ne\box\tw@%
+    \fi%
+  \else%
+    \global\setbox\@ne\hbox{\unhbox\z@\unhbox\tw@}%
+  \fi%
+%    \end{macrocode}
+%
+% That's all the messy processing done.  Now I can just typeset the
+% title.
+%
+%    \begin{macrocode}
+  \ifnum0=`{\fi}%
+  \stanzaspace%
+  \ifdim\wd\@ne>\z@%
+    \nonumber%
+    \stanzatitle{\unhbox\@ne}%
+  \else
+  \fi%
+%    \end{macrocode}
+%
+% That's it!  I'm done.
+%
+%    \begin{macrocode}
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% The |stanza| counter must be reset at the beginning of the poem.
+%
+%    \begin{macrocode}
+\poem@addtohook{\global\c@stanza\z@}
+%    \end{macrocode}
+%
+% Now for some formatting defaults.  This is easy stuff.
+%
+%
+% \begin{macro}{\thestanza}
+%
+% Obviously, this is the default way to typeset a stanza number.
+%
+%    \begin{macrocode}
+\renewcommand{\thestanza}{\Roman{stanza}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\labelstanza}
+%
+% This macro is responsible for giving the stanza number to be typeset in
+% the title line.
+%
+%    \begin{macrocode}
+\providecommand{\labelstanza}{\textsc{\roman{stanza}}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\stanzaname}
+%
+% This is responsible for typesetting the stanza's name.  This is easy.
+%
+%    \begin{macrocode}
+\providecommand{\stanzaname}[1]{\textsc{#1}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\stanzacombine}
+%
+% This is how to combine stanza numbers and names.  I'll just leave a space.
+%
+%    \begin{macrocode}
+\providecommand{\stanzacombine}[2]{#1\quad#2}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\stanzaspace}
+%
+% Separate the previous stanza from a new one.  This isn't done in
+% |\stanzatitle| because there may not be a title.
+%
+%    \begin{macrocode}
+\providecommand{\stanzaspace}{\nl[\medskipamount]}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\stanzatitle}
+%
+% Finally, this is the typesetting of the stanza title in its entirety.
+%
+%    \begin{macrocode}
+\providecommand{\stanzatitle}[1]{%
+  \hfill#1\hfill\\%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
diff --git a/sverb.dtx b/sverb.dtx
new file mode 100644
index 0000000..8e55ce0
--- /dev/null
+++ b/sverb.dtx
@@ -0,0 +1,1189 @@
+% \begin{meta-comment}
+%
+% $Id: sverb.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
+%
+% Verbatim typesetting done properly (ahem)
+%
+% (c) 1996 Mark Wooding
+%
+%----- Revision history -----------------------------------------------------
+%
+% $Log: sverb.dtx,v $
+% Revision 1.1  2002/02/03 20:49:03  mdw
+% Checkin for new build system.
+%
+% Revision 1.3  1996/11/19 21:01:18  mdw
+% Entered into RCS
+%
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% sverb package -- handling of verbatim text
+%% Copyright (c) 1996 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preamble>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{sverb}
+%<+package>                [1996/05/08 1.3 Verbatim typesetting]
+% \end{meta-comment}
+%
+% \CheckSum{651}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment}
+%
+%<*driver>
+\input{mdwtools}
+\describespackage{sverb}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+% \section{User guide}
+%
+% The \package{sverb} package provides some useful commands and environments
+% for doing things with verbatim text.  I prefer this code to the standard
+% \package{verbatim} package (by Rainer Sch\"opf et al.)\ although I'm
+% biased.
+%
+% The package was written to fulfil a particular purpose: I wanted to be able
+% to typeset ARM assembler code, 77~columns wide, on A5~paper, with the
+% fields separated by \textit{tab} characters.  It's grown up fairly
+% organically from that, and I've tidied it when I've seen the code get too
+% ugly.
+%
+% The current features are:
+%
+% \begin{itemize}
+%
+% \item A `listing' environment which typesets verbatim text nicely.
+%
+% \item A command to read verbatim text from an external file.
+%
+% \item Support for arbitrary-sized chunks of text without overflowing \TeX's
+%       memory.
+%
+% \item Support for \textit{tab} characters in the verbatim text.
+%
+% \item An environment for typesetting demonstrations of \LaTeX\ markup.
+%
+% \item It all works correctly with the \package{doc} system for documenting
+%       \LaTeX\ packages.
+%
+% \item A fairly hairy but quite powerful programmer interface to the yukky
+%       bits of the package.
+%
+% \end{itemize}
+%
+% The interface is described in its own section, so that more timid readers
+% can avoid it.  That said, some of the stuff in this section gets rather
+% technical.
+%
+% Note that this package doesn't even try to do anything with short bits of
+% verbatim text (as handled by the |\verb:...:| command).  I have a separate
+% package (\package{syntax}) which does all sorts of horrible things along
+% those lines.
+%
+% \subsection{The \env{listing} environment}
+%
+% \DescribeEnv{listing}
+% The main method for typesetting verbatim text is the \env{listing}
+% environment.  This works pretty much the same as the standard
+% \env{verbatim} environment, with some exceptions, which are described
+% below.
+%
+% So that you know exactly what you're getting, here are the rules by which
+% \package{sverb} decides what the verbatim text actually is:
+%
+% \begin{itemize}
+%
+% \item If there's any text, other than spaces, on the same line as the
+%       `|\begin{listing}|', then the contents of the environment begins
+%       immediately after the closing brace (with all leading spaces
+%       preserved).  Otherwise, the text begins on the following line.
+%
+% \item If there is any text, other than spaces, before the
+%       `|\end{listing}|', but on the same line, this is considered to be the
+%       last line of the text; otherwise the text is presumed to have ended
+%       at the end of the previous line.
+%
+% \item Any text following the |\end{listing}| on the same line is thrown
+%       away.  There are good reasons for this, but they're technical.
+%       Essentially there's nothing I can do about it.
+%
+% \end{itemize}
+%
+% \begin{figure}
+% \begin{demo}[w]{The \env{listing} environment}
+%\dots in the following code:
+%
+%\begin{listing}
+%init            MOV     R0,#200         ;Version 2.00 please
+%                LDR     R1,=&4B534154   ;Magic number (`TASK')
+%                ADR     R2,appName      ;Find application name
+%                SWI     Wimp_Initialise ;Register as a WIMP task
+%\end{listing}
+%
+%The next step is to \dots
+% \end{demo}
+% \end{figure}
+%
+% Tab characters are supported within the environment: tab stops are set
+% every eighth column, although this can be modified.
+%
+% \subsubsection{Configuring the \env{listing} environment}
+%
+% The text size used in the \env{listing} environment is set by the
+% |\listingsize| command.  By default, this is set to |\small|, although you
+% can redefine it in the document preamble, or it can be set in the document
+% class.
+%
+% The amount by which the listing text is indented is controlled by the
+% |\listingindent| length parameter.  This is a fixed length, whose default
+% value is 1\,em.
+%
+% \subsubsection{Choosing a different end-text}
+%
+% \DescribeEnv{listing*}
+% The \env{listing} environment is terminated by the exact character sequence
+% `|\end{listing}|'.  This isn't too much of a problem, unless you want to
+% include this string in the text.  This is achieved by the \env{listing$*$}
+% environment, which allows you to specify the end-text to find as an
+% argument.
+%
+% For example:
+%
+% \begin{demo}{The \env{listing$*$} environment}
+%Type a listing as follows:
+%
+%\begin{listing*}{<end-listing*>}
+%\begin{listing}
+%This is a listing.  Yes.
+%\end{listing}
+%<end-listing*>
+%\end{demo}
+%
+% Don't include `special' characters in your chosen end-text unless you know
+% what you're doing.
+%
+% \subsection{Writing text to a file}
+%
+% \DescribeEnv{verbwrite}
+% You can write verbatim text to a file using the \env{verbwrite}
+% environment.  The syntax is fairly straightforward:
+%
+% \begin{quote}
+% \syntax{"\\begin{verbwrite}{"<file-name>"}" \dots "\\end{verbwrite}"}
+% \end{quote}
+%
+% The text of the environment is written to the named file.  The rules about
+% where the text actually starts and ends are the same as for the
+% \env{listing} environment.
+%
+% There is also a $*$-variant, like \env{listing$*$}, which allows you to
+% choose the end-text.  The end-text is the first argument, the filename
+% comes second.
+%
+% There is a restriction on the characters you can write to the file: they
+% must all be considered `printable' by \TeX; otherwise they will be read
+% back in as `\syntax{"^^"<chars>}' which isn't too good.  Unfortunately,
+% this includes tab characters, so you can't write them.\footnote{^^A
+%   Well, not without doing serious surgery on \TeX\ itself, anyway. }
+%
+% \iffalse [Example time...  Ho hum.  There is evilness here.] \fi
+%\begin{verbwrite*}{<end-write>}{wrdemo1.tmp}
+%\begin{verbwrite}{wrdemo.tmp}
+%This is some text written to
+%a file near the beginning of
+%the file.
+%\end{verbwrite}
+%<end-write>
+%
+% For example: \verbinput{wrdemo1.tmp}
+%
+% \input{wrdemo1.tmp} \iffalse [Now build the file ;-) ] \fi
+%
+% \subsection{The \cmd\verbinput\ command}
+%
+% \DescribeMacro{\verbinput}
+% You can input a pre-prepared text file exactly as it is in the input using
+% the |\verbinput| command.  The filename is given as an argument.  For
+% example:
+%
+% \begin{demo}{The \cmd\verbinput\ command}
+%\verbinput{wrdemo.tmp}
+% \end{demo}
+%
+% \subsection{The \env{demo} environment}
+%
+% Package authors need to document their packages, and it's common to want
+% to display examples showing the original text and the output side-by-side
+% (or, when space doesn't permit this, one above the other).  Both the
+% \LaTeX\ book and \textit{The \LaTeX\ Companion} contain such examples.
+%
+% The \env{demo} environment allows such displays to be created easily.  The
+% syntax of the environment is as follows:
+%
+% \begin{quote}
+% \syntax{"\\begin{demo}["<shape>"]{"<title>"}" \dots "\\end{demo}"}
+% \end{quote}
+%
+% The optional \synt{shape} argument can be either `|w|' (wide), or `|n|'
+% (narrow).  A `wide' shape places the input and output one above the other,
+% while the `narrow' shape puts them side-by-side.  The default shape is
+% `narrow'.  An attractive border is drawn around the display to finish it
+% off nicely.
+%
+% An example:
+%
+%\begin{demo*}{<end-demo>}[w]{The \env{demo} environment}
+%\begin{demo}{From the \textit{\TeX book}}
+%\[ \sum_{p\;\rm prime}
+%   f(p) = \int_{t>1}
+%      f(t)\,{\rm d}\pi(t) \]
+%\end{demo}
+%<end-demo>
+%
+% \DescribeEnv{demo*}
+% As with the other environments created by this package, there's a
+% $*$-variant which takes the end-text as an argument.
+%
+%
+% \section{Programmer interface}
+%
+% This section describes the publicly available routines provided by the
+% \package{sverb} package.  Routines not described here are libable to be
+% changed or even removed without warning, so don't use them.
+%
+% \subsection{Environment hooks}
+%
+% Each of the environments created here works in the same way.  For each
+% environment \env{foo}, there's a main command responsible for doing the
+% work, called |\sv@foo|.  This is given all the arguments of the normal
+% environment, and two more:
+%
+% \begin{itemize}
+%
+% \item The `end-text' to search for, which marks the end of the environment.
+%
+% \item Some actions to perform after the text has been read and processed.
+%       This allows the calling macro to do some extra actions, like closing
+%       boxes, etc.
+%
+% \end{itemize}
+%
+% All the environments do is call the main command with appropriate
+% arguments.
+%
+% \subsection{Reading the verbatim text}
+%
+% \DescribeMacro{\sv@read}
+% The main scanning routine is |\sv@read|.  It is called with three
+% arguments:
+%
+% \begin{itemize}
+%
+% \item The end-text marking the end of the environment.
+%
+% \item The name of a macro (which must be a single token) which is called
+%       with a line of text as its single argument.  This is given each
+%       line of text which is read from the environment in turn.
+%
+% \item A macro, or other sort of action, which is to be done when the text
+%       has been read and processed.
+%
+% \end{itemize}
+%
+% The macro |\sv@read| assumes that the caller has already made some
+% provision for removing the category codes of the following text, by either
+% calling |\@verbatim| or using the construction
+% \begin{listing}
+%\let\do=\@makeother
+%\dospecials
+% \end{listing}
+%
+% \DescribeMacro{\sv@safespc}
+% Note that any space characters you read using |\sv@read| will be catcoded
+% as |\active|.  Normally this is OK because |\obeyspaces| (or
+% |\@vobeyspaces|) will be in effect.  If you're doing something more exotic,
+% like writing text to a file or building a command string, you can call
+% |\sv@safespc| which defines the active-space character to be a normal
+% whitespace-space when expanded.
+%
+% \implementation
+%
+% \section{Implementation}
+%
+% This section defines several macros and environments which allow verbatim
+% typing, with a high degree of configurability.  OK, so this sort of
+% thing's been done so often before that it isn't true, but I don't really
+% care.
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+% \subsection{Simple things}
+%
+% To help us build funny macros which involve strange and different category
+% codes, I'll write some simple macros which I can use while building my
+% complicated and clever ones.
+%
+% \begin{macro}{\@cspecials}
+%
+% This macro is used to assist the definition of some of the environments.
+% It makes `|\|', `|{|' and `|}|' into `other' characters, and replaces them
+% with `\verb"|"', `|<|' and `|>|' respectively.  Note that `|[|' and `|]|'
+% aren't used, because they make defining commands which take optional
+% arguments awkward.  Note that we open a group here.  This should be closed
+% using \verb"|endgroup" at the end of the special section.
+%
+%    \begin{macrocode}
+\def\@cspecials{%
+  \begingroup%
+  \catcode`|0%
+  \catcode`<1%
+  \catcode`>2%
+  \catcode`\{12%
+  \catcode`\}12%
+  \catcode`\\12%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sv@startlisting}
+%
+% This macro sets everything up nicely for a \env{listing}-type verbatim
+% environment.
+%
+%    \begin{macrocode}
+\def\sv@startlisting{%
+  \def\par{\@@par\penalty\interlinepenalty}%
+  \@@par%
+  \leftskip\@totalleftmargin%
+  \obeylines%
+  \@noligs%
+  \let\do\@makeother\dospecials%
+  \verbatim@font%
+  \frenchspacing%
+  \@vobeyspaces%
+  \settabwidth%
+  \catcode9\active%
+  \lccode`\~9\lowercase{\let~\sv@vtab}%
+  \lccode`\~13\lowercase{\let~\vinput@cr}%
+  \interlinepenalty500%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{Tab character handling}
+%
+% One of the things we want to do here is handle tab characters properly.
+% (Here, `properly' means `moving to the next column which is a multiple of
+% eight', the way these things were always meant to.)
+%
+% \begin{macro}{\settabwidth}
+%
+% The tabs used by our tabbed verbatim environments are set up by this
+% routine.  It sets the tab width parameter |\svtab| to 8 times the width
+% of a |\tt| space.  If you really want, you can redefine this macro.
+%
+%    \begin{macrocode}
+\newdimen\svtab
+\def\settabwidth{\setbox\z@\hbox{\texttt{\space}}\svtab8\wd\z@}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sv@vtab}
+%
+% Here we handle tabs inside verbatim environments.  We expect each line to
+% be typeset as a box, using something like
+%
+% \begin{listing}
+%\setbox0\hbox{#1}
+%\leavevmode
+%\box0
+%\par
+% \end{listing}
+%
+% The idea is that you make tab active, and set it to this macro.  We stop
+% the current box, stretch it to the right width, and start another one
+% straight after, so nobody know the difference.  The code here is straight
+% from Appendix~D of \textit{The \TeX book}.
+%
+%    \begin{macrocode}
+\def\sv@vtab{%
+  \hfill\egroup%
+  \@tempdima\wd\z@%
+  \divide\@tempdima\svtab%
+  \multiply\@tempdima\svtab%
+  \advance\@tempdima\svtab%
+  \wd\z@\@tempdima%
+  \leavevmode\box\z@%
+  \setbox\z@\hbox\bgroup%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\verbinput}
+%
+% We allow input from a file, by the |\verbinput| command.  We display the
+% text pretty much the same as the \env{listing} environment below.
+%
+% We set tab and return active, and get them to do appropriate things.  This
+% isn't actually all that hard.
+%
+%    \begin{macrocode}
+\def\verbinput#1{%
+  \begin{listinglist}%
+  \listingsize%
+  \sv@startlisting%
+  \setbox\z@\hbox\bgroup%
+  \input{#1}%
+  \sv@stripspc%
+  \egroup%
+  \ifdim\wd\z@=\z@%
+    \ifhmode\par\fi%
+  \else%
+    \leavevmode\box\z@\par%
+  \fi%
+  \end{listinglist}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\vinput@cr}
+%
+% This macro handles return characters while inputting text in |\verbinput|.
+% We just output our current box, and start another.
+%
+%    \begin{macrocode}
+\def\vinput@cr{%
+  \egroup%
+  \leavevmode\box\z@%
+  \par%
+  \setbox\z@\hbox\bgroup%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{Reading verbatim text}
+%
+% The traditional way of reading verbatim text is to use a delimited
+% argument, as described in the \textit{\TeX book}.  This works well-ish if
+% the text isn't very long.  A better solution would be to pick out the text
+% line-by-line and process it like that.  So this is what we do.
+%
+% \begin{macro}{\matcher}
+%
+% For long verbatim environments, we need to be able to find the end text.
+% This is rather tricky.  The solution here is rather horrible.  The
+% environment picks out each line of the text at a time, as an argument, and
+% tests to see if it contains the text we're after.  We do the test in a
+% particularly yukky way: we add the actual target text to the end of the
+% line, and inspect the text following the match to see if the match is at
+% the end.
+%
+% The |\matcher| macro creates a `matcher' which will test strings to see if
+% they contain something interesting.
+%
+% To create a matcher, say
+% \syntax{"\\matcher{"<cmd-name>"}{"<target>"}{"<process-cmd>"}"}.  The
+% command \synt{cmd-name} accepts a line of text as an argument and calls
+% the \synt{process-cmd} with the text of the line before the match, or the
+% whole lot.  It also sets |\@ifmatched| appropriately.
+%
+% (Having spent ages coming up with this cruft myself, I found some very
+% similar, but slightly better, code in Appendix~D.  So I've changed mine to
+% match Donald's.  Anyway, credit where it's due: cheers Don.)
+%
+%    \begin{macrocode}
+\newif\if@matched
+\def\matcher#1#2#3{%
+  \expandafter\def\csname\string#1$match\endcsname##1#2##2##3\end{%
+    \ifx##2\relax%
+      \@matchedfalse%
+    \else%
+      \@matchedtrue%
+    \fi%
+    #3{##1}%
+  }%
+  \expandafter\def\expandafter#1\expandafter##\expandafter1\expandafter{%
+    \csname\string#1$match\endcsname##1#2\relax\end%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sv@stripspc}
+%
+% This macro strips any trailing glue in the current horizontal list.  This
+% is fairly simple, actually: we just loop while glue is the last item.  It's
+% slightly complicated by penalties which \TeX\ puts into the list between
+% the glue items, but we just remove them too.
+%
+%    \begin{macrocode}
+\def\sv@stripspc{%
+  \unpenalty%
+  \ifdim\lastskip=\z@\else%
+    \unskip\expandafter\sv@stripspc%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sv@percent}
+%
+% This macro strips a single leading percent character if there is one, and
+% if the \env{doc} package is loaded.  We store the possibly stripped text in
+% |\@tempa|.
+%
+%    \begin{macrocode}
+\begingroup
+\catcode`\%=12
+\gdef\sv@percent#1#2\relax
+    {\ifx\check@percent\@@undefined
+                     \ifx#1\relax\def\@tempa{}\else
+                         \def\@tempa{#1#2}\fi\else
+                     \ifx#1\relax\def\@tempa{}\else
+                         \ifx#1%\def\@tempa{#2}\else
+                             \def\@tempa{#1#2}\fi\fi\fi}
+\endgroup
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\@isspaces}
+%
+% We want to avoid writing the first and last lines of the environment to the
+% file if there's nothing in them.  To do this, we need to know whether a
+% piece of text contains only space characters.  This macro does this, in a
+% rather nasty way.  See the other macros below for details of how this
+% works.
+%
+% We define |\sv@safespc| at the same time: this makes space active and
+% expand to a space character which is not active.  Neat, huh?
+%
+%    \begin{macrocode}
+\lccode`\~32
+\lccode`\!32
+\lowercase{%
+  \def\@isspaces#1{%
+    \ifx#1\relax%
+      \def\@tempb{\@tempswafalse}%
+    \else\ifx#1~%
+      \let\@tempb\@isspaces%
+    \else%
+      \def\@tempb##1\relax{}%
+    \fi\fi%
+    \@tempb%
+  }
+  \def\sv@safespc{%
+    \catcode32\active%
+    \def~{ }%
+  }
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sv@read}
+%
+% This macro does the main job of reading a chunk of verbatim text.  You call
+% it like this:
+%
+% \begin{quote}
+% \syntax{"\\sv@read{"<end-text>"}{"<process-line-proc>"}{"<end-proc>"}"}
+% \end{quote}
+%
+% The \synt{end-text} is the text to find at the end of the `environment': we
+% stop when we find it.
+%
+% The \synt{process-line-proc} is a macro which is passed as an argument each
+% line which we read from the text.
+%
+% The \synt{end-proc} is a macro to call once we've finished reading all of
+% the text.  This can tidy up an environment or close a file or whatever.
+%
+% We read the text by picking out newlines using a delimited macro.  We have
+% to be a little clever, because newlines are active in verbatim text.
+%
+% We will also strip `|%|' signs off the beginning if the \package{doc}
+% package is here (\package{doc} tries to play with \LaTeX's verbatim stuff,
+% and doesn't understand the way we do things).
+%
+%    \begin{macrocode}
+\def\sv@read#1#2#3{%
+%    \end{macrocode}
+%
+% This code does all sorts of evil things, so I'll start by opening a group.
+%
+%    \begin{macrocode}
+  \begingroup%
+%    \end{macrocode}
+%
+% So that I can spot the end-text, I'll create a matcher macro.
+%
+%    \begin{macrocode}
+  \matcher\@match{#1}\sv@read@ii%
+%    \end{macrocode}
+%
+% So that I can identify line ends, I'll make them active.  I'll also make
+% spaces active so that they can expand to whatever they ought to expand
+% to (spaces in files, or funny \verb*" " characters or whatever.
+%
+%    \begin{macrocode}
+  \catcode13\active%
+  \catcode32\active%
+%    \end{macrocode}
+%
+% I'll use the |\if@tempswa| flag to tell me whether I ought to output the
+% current line.  This is a little messy, so I'll describe it later.  I'll
+% initialise it to false because this is the correct thing to do.
+%
+%    \begin{macrocode}
+  \@tempswafalse%
+%    \end{macrocode}
+%
+% Most of the job is done by two submacros.  I'll define them in terms of
+% my current arguments (to save lots of token munging).  The first just
+% extracts the next line (which ends at the next newline character) and
+% tries to match it.
+%
+%    \begin{macrocode}
+  \lccode`\~13\lowercase{%
+    \def\sv@read@i##1~{\@match{##1}}%
+  }%
+%    \end{macrocode}
+%
+% The results of the match get passed here, along with the text of the
+% line up to the matched text.
+%
+%    \begin{macrocode}
+  \def\sv@read@ii##1{%
+%    \end{macrocode}
+%
+% The first job to do is to maybe strip off percent signs from the beginning,
+% to keep \package{doc} happy.
+%
+%    \begin{macrocode}
+    \sv@percent##1\relax\relax%
+%    \end{macrocode}
+%
+% Now I need to decide whether I ought to output this line.  The method goes
+% like this: if this is the first line (|\if@tempswa| is false) or the last
+% (|\if@matched| is true), \emph{and} the text consists only of spaces, then
+% I'll ignore it.
+%
+% The first thing to do is to notice the last line -- if |\if@matched| is
+% true, then I'll make |\if@tempswa| false to make the first-line and
+% last-line cases work the same way.
+%
+%    \begin{macrocode}
+    \if@matched\@tempswafalse\fi%
+%    \end{macrocode}
+%
+% Now if this is the first or last line, I'll examine it for spaces.  This
+% is done in a separate macro.  It will set |\if@tempswa| false if the
+% text contains only spaces.
+%
+%    \begin{macrocode}
+    \if@tempswa\else\@tempswatrue\expandafter\@isspaces\@tempa\relax\fi%
+%    \end{macrocode}
+%
+% Now, if |\if@tempswa| is still true, perform the \<process-line-proc> on
+% the line of text.  I'll provide a group, so that it doesn't upset me
+% too much.
+%
+%    \begin{macrocode}
+    \if@tempswa%
+      \begingroup%
+      \expandafter#2\expandafter{\@tempa}%
+      \endgroup%
+    \fi%
+%    \end{macrocode}
+%
+% The next line won't be the first one, so I'll set the flag true in
+% readiness.
+%
+%    \begin{macrocode}
+    \@tempswatrue%
+%    \end{macrocode}
+%
+% Now, if that wasn't the last line, go round again; otherwise end the group
+% I started ages ago, and do the user's \<end-proc>.
+%
+%    \begin{macrocode}
+    \if@matched\def\@tempa{\endgroup#3}\else\let\@tempa\sv@read@i\fi%
+    \@tempa%
+  }%
+%    \end{macrocode}
+%
+% Now to start the thing up.  I'll read the first line.
+%
+%    \begin{macrocode}
+  \sv@read@i%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sv@readenv}
+%
+% This macro works out an appropriate end-text for the current environment.
+% If you say \syntax{"\\sv@readenv{"<macro-name>"}"}, it will expand do
+% \begin{listinglist} \listingsize \synshorts
+% <macro-name>"{\\"$_{12}$"end{"$_{12}$<current-env-name>"}"$_{12}$"}"^^A
+%		"{\\end{"<current-env-name>"}}"
+% \end{listinglist}
+% Easy, no?
+%
+% This is all done with mirrors.  No, err\dots\ it's done with
+% |\expandafter|.
+%
+%    \begin{macrocode}
+\begingroup
+\lccode`\<=`\{
+\lccode`\>=`\}
+\lccode`\|=`\\
+\lowercase{\endgroup
+\def\sv@readenv#1{%
+  \expandafter\expandafter\expandafter%
+    #1\expandafter\sv@readenv@i\@currenvir\@@%
+}
+\def\sv@readenv@i#1\@@{{|end<#1>}{\end{#1}}}
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sv@verbline}
+%
+% This macro typesets a line in a verbatim way, so you can construct a real
+% verbatim environment from it.  It's a bit tricky in the way that it catches
+% the last line.  Don't worry about this: it's easy really.  Note the
+% |\relax| after the |\par| -- this is because \package{doc} tries to do
+% clever things with |\par| to strip `|%|' signs out.
+%
+%    \begin{macrocode}
+\def\sv@verbline#1{%
+  \setbox\z@\hbox{#1\sv@stripspc}%
+  \ifdim\wd\z@=\z@%
+    \if@matched\ifhmode\par\relax\fi\else\leavevmode\par\relax\fi%
+  \else%
+    \leavevmode\box\z@\par\relax%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{Listing environments}
+%
+% The \env{listing} environment is our equivalent of the standard
+% \env{verbatim} environment.  We do some slightly cleverer things, though,
+% to make sure (for example) that even text which contains |\end{listing}|
+% can be typeset.
+%
+% \begin{macro}{\listinglist}
+% \begin{environment}{listinglist}
+%
+% This defines the layout for the \env{listing} environment.  It starts a
+% list with the appropriate shape.  It's also made into an environment, so
+% that the end-paragraph-environment bits work correctly.
+%
+% The |\listingindent| length parameter sets up the indentation of the
+% listings.  If there's a |\parindent| setting, I'll line listings up with
+% that; otherwise I'll just choose something which looks right.
+%
+%    \begin{macrocode}
+\newdimen\listingindent
+\AtBeginDocument{%
+  \ifdim\parindent=\z@\listingindent1em\else\listingindent\parindent\fi%
+}
+%    \end{macrocode}
+%
+% Now to define a size hook for the environment.  This is fairly simple
+% stuff.
+%
+%    \begin{macrocode}
+\ifx\listingsize\@@undefined
+  \let\listingsize\small
+\fi
+%    \end{macrocode}
+%
+% Now to define the environment itself.  Suppress the indentation if we're
+% first thing on a new list item, so that the listing lines up with
+% everything else.
+%
+%    \begin{macrocode}
+\def\listinglist{%
+  \list{}{%
+    \if@inlabel%
+      \leftmargin\z@%
+    \else%
+      \leftmargin\listingindent%
+    \fi%
+    \rightmargin\z@%
+    \labelwidth\z@%
+    \labelsep\z@%
+    \itemindent\z@%
+    \listparindent\z@%
+    \let\makelabel\relax%
+    \parsep\z@skip%
+  }%
+  \parfillskip\@flushglue%
+  \item\relax%
+}
+\let\endlistinglist\endlist
+%    \end{macrocode}
+%
+% \end{environment}
+% \end{macro}
+%
+% \begin{environment}{listing}
+%
+% The \env{listing} environment is the only real verbatim-like environment we
+% create will all this kit, although it does the job very nicely.
+%
+% The environment indents its contents slightly, unlike \env{verbatim}, and
+% uses a smaller typeface in an attempt to fit 77-column text on an A5~page.
+% There is also a $*$-variant, which allows you to specify the terminating
+% text.  This enables you to include absolutely any text in the environment,
+% including |\end{listing}|.
+%
+% First, we must define the |\listing| command.
+%
+%    \begin{macrocode}
+\def\listing{%
+  \listinglist%
+  \listingsize%
+  \sv@readenv\sv@listing%
+}
+%    \end{macrocode}
+%
+% Now we define the |\@listing| command, which does most of the work.  We
+% base the \env{listing} environment on a \env{list}.
+%
+%    \begin{macrocode}
+\def\sv@listing#1#2{%
+  \sv@startlisting%
+  \sv@read{#1}\sv@verbline{\endlistinglist#2}%
+}
+%    \end{macrocode}
+%
+% Now we define the starred version.  The command name needs to include the
+% `|*|' character, so we must use |\csname|.  There's some hacking here to
+% allow us to read the name using the appropriate catcodes for otherwise
+% normal characters: \LaTeX\ activates some characters and makes them typeset
+% themselves to suppress some ligaturing.
+%
+%    \begin{macrocode}
+\expandafter\def\csname listing*\endcsname{%
+  \listinglist%
+  \listingsize%
+  \begingroup%
+  \@noligs%
+  \def\@tempa##1{\endgroup\sv@listing{##1}{\end{listing*}}}%
+  \@tempa%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{environment}{ignore}
+%
+% The \env{ignore} environment entirely ignores its contents.  Anything at
+% all may be put into the environment: it is discarded utterly.
+%
+% We define some macros for defining ignoring environments, because this can
+% be useful for version control, possibly.
+%
+%    \begin{macrocode}
+\def\sv@ignore#1#2{%
+  \@bsphack%
+  \let\do\@makeother\dospecials%
+  \sv@read{#1}\@gobble{\@esphack#2}%
+}
+\def\ignore{\sv@readenv\sv@ignore}
+\def\ignoreenv#1{%
+  \expandafter\let\csname #1\endcsname\ignore%
+}
+\def\unignoreenv#1{%
+  \expandafter\def\csname #1\endcsname{\endgroup}%
+  \expandafter\def\csname end#1\endcsname%
+      {\begingroup\def\@currenvir{#1}}%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \subsection{The \env{verbwrite} environment}
+%
+% The \env{verbwrite} environment allows text to be written to a file in a
+% verbatim way.  Note that tab characters don't work, because \TeX\ refuses
+% to be nice.
+%
+% \begin{macro}{\sv@write}
+%
+% As seems to be traditional now, we first define a general hookable macro
+% which allows a caller to specify the end-text and what to do afterwards.
+%
+%    \begin{macrocode}
+\newwrite\sv@writefile
+\def\sv@write#1#2{%
+  \begingroup%
+  \@bsphack%
+  \let\do\@makeother\dospecials%
+  \sv@safespc%
+  \sv@read{#1}\sv@writeline{\sv@endwrite#2}%
+}
+\def\sv@writeline#1{%
+  \immediate\write\sv@writefile{#1}%
+}
+\def\sv@endwrite{%
+  \@esphack%
+  \endgroup%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{verbwrite}
+%
+% Now we can define the actual environment.  We define a $*$-variant which
+% allows the user to specify the end-text, just to make sure.
+%
+%    \begin{macrocode}
+\def\verbwrite#1{%
+  \immediate\openout\sv@writefile#1\relax%
+  \sv@readenv\sv@write%
+}
+\def\endverbwrite{\immediate\closeout\sv@writefile}
+\expandafter\def\csname verbwrite*\endcsname#1#2{%
+  \immediate\openout\sv@writefile#2\relax%
+  \sv@write{#1}{\immediate\closeout\sv@writefile\end{verbwrite*}}%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \subsection{The \env{demo} environment}
+%
+% By way of tying all of this together, I present an environment for
+% displaying demonstrations of \LaTeX\ markup.  We read the contents of the
+% environment, write it to a temporary file, and read it back twice,
+% typesetting it the first time and displaying it verbatim the second time.
+%
+% \begin{macro}{\sv@demoname}
+%
+% This macro expands to the filename to use for the temporary data.  To
+% allow the package documentation to demonstrate the \env{demo} environment
+% itself, we need to keep a nesting count.  This avoids too much hackery,
+% which unfortunately appears to plague all of my \TeX\ code.
+%
+%    \begin{macrocode}
+\newcount\sv@nestcount
+\def\sv@demoname{demo\number\sv@nestcount.tmp}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sv@demo}
+%
+% As for listing, we do all the business through a private macro.  This is
+% good because it means we can leave the main macro readable.  The argument
+% is the end-text to spot.
+%
+%    \begin{macrocode}
+\def\sv@demo#1#2{%
+  \@ifnextchar[{\sv@demo@i{#1}{#2}}{\sv@demo@i{#1}{#2}[n]}%
+}
+\def\sv@demo@i#1#2[#3]#4{%
+  \advance\sv@nestcount by\@ne%
+  \immediate\openout\sv@writefile\sv@demoname\relax%
+  \sv@write{#1}{%
+    \immediate\closeout\sv@writefile%
+    \sv@dodemo{#2}{#3}{#4}%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{demo}
+%
+% This is the real environment.  We provide \env{demo$*$} too, to allow the
+% user to choose the end-text.
+%
+%    \begin{macrocode}
+\def\demo{\sv@readenv\sv@demo}
+\expandafter\def\csname demo*\endcsname#1{\sv@demo{#1}{\end{demo*}}}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{macro}{\sv@dodemo}
+%
+% First, let's define some common bits of code in the stuff below.  The
+% minipages used to typeset the material has some clever stuff to avoid
+% strange spacing in the output.
+%
+%    \begin{macrocode}
+\def\sv@demosmp{%
+  \begin{minipage}[t]{\@tempdima}%
+  \vskip8\p@%
+  \hrule\@height\z@%
+  \raggedright%
+  \vbox\bgroup%
+}
+\def\sv@demoemp{%
+    \par\unpenalty\unskip%
+  \egroup%
+  \vskip8\p@%
+  \hrule\@height\z@%
+  \end{minipage}%
+}
+%    \end{macrocode}
+%
+% This is the macro which actually typesets the demonstration.
+%
+%    \begin{macrocode}
+\def\sv@dodemo#1#2#3{%
+%    \end{macrocode}
+%
+% Now work out some values.  We set |\hsize| to the line width leaving 2\,em
+% of space on either side.  The size of the minipages is calculated depending
+% on the shape of the demonstration.  This is all fairly simple.
+%
+%    \begin{macrocode}
+  \begingroup%
+  \@tempdima\linewidth%
+  \advance\@tempdima-2em%
+  \hsize\@tempdima%
+  \if#2w%
+    \advance\@tempdima-2em%
+  \else%
+    \advance\@tempdima-3em%
+    \divide\@tempdima2%
+  \fi%
+%    \end{macrocode}
+%
+% Now we open a big vertical box, and put in a header to mark off the
+% demonstration.
+%
+%    \begin{macrocode}
+  \par%
+  \setbox\z@\hbox{\strut\enspace#3\enspace\strut}%
+  \@tempdimb.5\dp\z@%
+  \advance\@tempdimb-.5\ht\z@%
+  \ht\z@\@tempdimb\dp\z@\@tempdimb%
+  \noindent\hskip1em\vtop{%
+    \hb@xt@\hsize{%
+      \hrulefill%
+      \raise\@tempdimb\box\z@%
+      \hrulefill%
+    }%
+    \nointerlineskip%
+    \hb@xt@\hsize{\vrule\@height5\p@\hfil\vrule\@height5\p@}%
+    \nointerlineskip%
+%    \end{macrocode}
+%
+% Now we insert the output text in the first minipage.  I'll force `|%|'
+% to be a comment character, in case something like \package{doc} has had its
+% wicked way.
+%
+%    \begin{macrocode}
+    \vskip-\parskip%
+    \noindent\hbox{}\hskip1em%
+    \sv@demosmp%
+    \catcode`\%14\relax%
+    \input{\sv@demoname}%
+    \sv@demoemp%
+%    \end{macrocode}
+%
+% Insert some kind of separation between the two.  In `wide' format, we start
+% a new line, and put a ruleoff between the two.  In `narrow' format, we just
+% leave some space.
+%
+%    \begin{macrocode}
+    \if#2w%
+      \vskip8\p@\hrule\vskip8\p@%
+      \noindent\hbox{}%
+    \fi%
+    \hskip1em%
+%    \end{macrocode}
+%
+% Now we put the verbatim copy of the text in the other minipage.
+%
+%    \begin{macrocode}
+    \sv@demosmp%
+    \listingindent\z@%
+    \verbinput\sv@demoname%
+    \sv@demoemp%
+    \par%
+    \nointerlineskip%
+    \hb@xt@\hsize{\vrule\@height5\p@\hfil\vrule\@height5\p@}%
+    \hrule%
+  }%
+  \endgroup%
+  \par%
+  \vskip\baselineskip%
+  #1%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% That's all there is.  Have fun.
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
diff --git a/syntax.dtx b/syntax.dtx
new file mode 100644
index 0000000..627f8c8
--- /dev/null
+++ b/syntax.dtx
@@ -0,0 +1,2940 @@
+% \begin{meta-comment}
+%
+% syntax.dtx
+%
+% Syntax typesetting package for LaTeX 2e
+%
+% (c) 1996 Mark Wooding
+%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <general public licence>
+%%
+%% syntax package -- typesetting syntax descriptions
+%% Copyright (c) 1996 Mark Wooding
+%%
+%% This program is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU General Public License as published by
+%% the Free Software Foundation; either version 2 of the License, or
+%% (at your option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with this program; if not, write to the Free Software
+%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%%
+% \end{meta-comment}
+%
+% \begin{meta-comment} <Package preamble>
+%<+package>\NeedsTeXFormat{LaTeX2e}
+%<+package>\ProvidesPackage{syntax}
+%<+package>                [1996/05/17 1.07 Syntax typesetting (MDW)]
+% \end{meta-comment}
+%
+% ^^A \CheckSum{1504}
+%% \CharacterTable
+%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%%   Digits        \0\1\2\3\4\5\6\7\8\9
+%%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%%   Dollar        \$     Percent       \%     Ampersand     \&
+%%   Acute accent  \'     Left paren    \(     Right paren   \)
+%%   Asterisk      \*     Plus          \+     Comma         \,
+%%   Minus         \-     Point         \.     Solidus       \/
+%%   Colon         \:     Semicolon     \;     Less than     \<
+%%   Equals        \=     Greater than  \>     Question mark \?
+%%   Commercial at \@     Left bracket  \[     Backslash     \\
+%%   Right bracket \]     Circumflex    \^     Underscore    \_
+%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%%   Right brace   \}     Tilde         \~}
+%%
+%
+% \begin{meta-comment} <driver>
+%
+%<*driver>
+%
+% This hacking will remember the old default underscore character.  Even if
+% T1 fonts are being used, it will get the grotty version.  Why is it that
+% all of the encoding handling ends up looking like this?
+%
+\expandafter\let\expandafter\oldus\csname?\string\textunderscore\endcsname
+%
+\input{mdwtools}
+\describespackage{syntax}
+\DeclareRobustCommand\syn{\package{syntax}}
+\mdwdoc
+%</driver>
+%
+% \end{meta-comment}
+%
+% \section{User guide}
+%
+% \subsection{Introduction}
+%
+% The \syn\ package provides a number of commands and environments which
+% extend \LaTeX\ and allow you to typeset good expositions of syntax.
+%
+% The package provides several different types of features: probably not all
+% of these will be required by every document which needs the package:
+% \begin{itemize}
+% \item A system of abbreviated forms for typesetting syntactic items.
+% \item An environment for typesetting BNF-type grammars
+% \item A collection of environments for building syntax diagrams.
+% \end{itemize}
+%
+% The package also includes some other features which, while not necessarily
+% syntax-related, will probably come in handy for similar types of document:
+% \begin{itemize}
+% \item An abbreviated notation for verbatim text, similar to the
+%       \package{shortvrb} package.
+% \item A slightly different underscore character, which works as expected
+%       in text and maths modes.
+% \end{itemize}
+%
+% \subsection{The abbreviated verbatim notation}
+%
+% In documents describing programming languages and libraries, it can become
+% tedious to type "\verb|...|" every time.  Like Frank Mittelbach's
+% \package{shortvrb} package, \syn\ provides a way of setting up single-^^A
+% character abbreviations.  The only real difference between the two is that
+% the declarations provided by \syn\ obey \LaTeX's normal scoping rules.
+%
+% \DescribeMacro\shortverb
+% You can set up a character as a `verbatim shorthand' character using the
+% |\shortverb| command.  This takes a single argument, which should be a
+% single-character control sequence containing the character you want to use.
+% So, for example, the command
+% \begin{listing}
+%\shortverb{\|}
+% \end{listing}
+% would set up the `"|"' character to act as a verbatim delimiter.  While a
+% |\shortverb| declaration is in force, any text surrounded by (in this case)
+% vertical bar characters will be typeset as if using the normal |\verb|
+% command.
+%
+% \DescribeEnv{shortverb}
+% Since \LaTeX\ allows any declaration to be used as an environment, you can
+% use a \env{shortverb} environment to delimit the text over which your
+% character is active:
+% \begin{listing}
+%Some text...
+%\begin{shortverb}{\|}
+%...
+%\end{shortverb}
+% \end{listing}
+%
+% \DescribeMacro\unverb
+% If you want to disable a |\shortverb| character without ending the scope
+% of other declarations, you can use the |\unverb| command, passing it
+% a character as a control sequence, in the same way as above.
+%
+% The default \TeX/\LaTeX\ underscore character is rather too short for
+% use in identifiers.  For example:
+%
+% \begingroup \let\_=\oldus
+% \begin{demo}{Old-style underscores}
+%Typing long underscore-filled
+%names, like big\_function\_name,
+%is normally tedious.  The normal
+%positioning of the underscore
+%is wrong, too.
+% \end{demo}
+% \endgroup
+%
+% The \syn\ package redefines the |\_| command to draw a more attractive
+% underscore character.  It also allows you to use the |_|~character
+% directly to produce an underscore outside of maths mode: |_|~behaves
+% as a subscript character as usual inside maths mode.
+%
+% \begin{demo}{New \syn\ underscores}
+%You can use underscore-filled
+%names, like big_function_name,
+%simply and naturally.  Of
+%course, subscripts still work
+%normally in maths mode, e.g.,
+%$x_i$.
+% \end{demo}
+%
+% \subsection{Typesetting syntactic items}
+% \begin{synshorts}
+%
+% The \syn\ package provides some simple commands for typesetting syntactic
+% items.
+%
+% \DescribeMacro\synt
+% Typing "\\synt{"<text>"}" typesets <text> as a \lq non-terminal',
+% in italics and surrounded by angle brackets.  If you use "\\synt" a lot,
+% you can use the incantation
+% \begin{listing}
+%\def\<#1>{\synt{#1}}
+% \end{listing}
+% to allow you to type "\\<"<text>">" as an alternative to 
+% "\\synt{"<text>"}".
+%
+% \DescribeMacro\lit
+% You can also display literal text, which the reader should type directly,
+% using the "\\lit" command.
+%
+% \begin{demo}{Use of \cmd\lit}
+%Type \lit{ls} to display a
+%list of files.
+% \end{demo}
+%
+% Note that the literal text appears in quotes.  To suppress the quotes,
+% use the `*' variant.
+%
+% The "\\lit" command produces slightly better output than "\\verb" for
+% running text, since the spaces are somewhat narrower.  However, "\\verb"
+% allows you to type arbitrary characters, which are treated literally,
+% whereas you must use commands such as "\\{" to use special characters
+% within the argument to "\\lit".  Of course, you can use "\\lit" anywhere
+% in the document: "\\verb" mustn't be used inside a command argument.
+% \end{synshorts}
+%
+% \subsection{Abbreviated forms for syntactic items}
+%
+% It would be very tedious to require the use of commands like |\synt|
+% when building syntax descriptions like BNF grammars.  It would also make
+% your \LaTeX\ source hard to read.  Therefore, \syn\ provides some
+% abbreviated forms which make typesetting syntax quicker and easier.
+%
+% Since the abbreviated forms use several characters which you may want to
+% use in normal text, they aren't enabled by default.  They only work
+% with special commands and environments provided by the \syn\ package.
+%
+% The abbreviated forms are shown in the table below:
+%
+% \begin{tab}[\synshorts]{ll}                                       \hline
+% \bf Input        & \bf Output                                  \\ \hline
+% "<some text>"    & <some text>                                 \\
+% "`some text'"    & `some text'                                 \\
+% "\"some text\""  & "some text"                                 \\ \hline
+% \end{tab}
+%
+% Within one of these abbreviated forms, text is treated more-or-less
+% verbatim:
+% \begin{itemize}
+%
+% \item Any |$|, |%|, |^|, |&|, |{|, |}|, |~| or |#| characters are treated
+%       literally: their normal special meanings are ignored.
+%
+% \item Other special characters, with the exception of |\|, are also treated
+%       literally: this includes any characters made special by |\shortverb|.
+%
+% \end{itemize}
+%
+% However, the |\| character retains its meaning.  Since the brace
+% characters are not recognised, most commands can't be used within
+% abbreviated forms.  However, you can use special commands to type some
+% of the remaining special characters:
+%
+% \begin{tab}[\synshorts]{ll}                                       \hline
+% \bf Command   & \bf Result                                     \\ \hline
+% "\\\\"        & A `\\' character                               \\
+% "\\>"         & A `>' character                                \\
+% "\\'"         & A `\'' character                               \\
+% "\\\""        & A `"' character                                \\
+% "\\\ "        & A `\ ' character (not a space)                 \\ \hline
+% \end{tab}
+%
+% Note that |\\|, |\>|, |\"| and \verb*|\ | are only useful in a |\tt| font,
+% i.e., inside |`...'| and |"..."| forms, since the characters don't exist
+% in normal fonts.  The |\>|, |\"| and |\'| commands are only provided so
+% you can use these characters within |<...>|, |"..."| and |`...'| forms
+% respectively: in the other forms, there is no need to use the special
+% command.
+%
+% In addition, when the above abbreviations are enabled, the character "|"
+% is set to typeset a \syntax{|} symbol, which is conventionally used to
+% separate alternatives in syntax descriptions.
+%
+% \DescribeMacro\syntax
+% Normally, these abbreviated forms are enabled only within special
+% environments, such as \env{grammar} and \env{syntdiag}.  To use them
+% in running text, use the |\syntax| command.  The abbreviations are made
+% active within the argument of the |\syntax| command.\footnote{^^A
+%   The argument of the \cmd\syntax\ command may contain commands such
+%   as \cmd\verb, which are normally not allowed within arguments.
+% }  Note that you cannot use the |\syntax| command within the argument
+% of another command.
+%
+% \DescribeMacro\synshorts
+% \DescribeEnv{synshorts}
+% You can also enable the syntax shortcuts using the |\synshorts| declaration
+% or the \env{synshorts} environment.  This enables the syntax shortcuts
+% until the scope of the declaration ends.
+%
+% \DescribeMacro\synshortsoff
+% If syntax shortcuts are enabled, you can disable them using the
+% |\synshortsoff| declaration.
+%
+% \subsection{The \env{grammar} environment}
+%
+% \DescribeEnv{grammar}
+% For typesetting formal grammars, for example, of programming languages,
+% the \syn\ package provides a \env{grammar} environment.  Within this
+% environment, the abbreviated forms described above are enabled.
+%
+% Within the environment, separate production rules should be separated by
+% blank lines.  You can use the normal |\\| command to perform line-breaking
+% of a production rule.  Note that a production rule must begin with a
+% nonterminal name enclosed in angle brackets (|<| \dots |>|), followed by
+% whitespace, then some kind of production operator (usually `::=') and then
+% some more whitespace.  You can control how this text is actually typeset,
+% however.
+%
+% \DescribeMacro{\[[}
+% \DescribeMacro{\]]}
+% You can use syntax diagrams (see below) instead of a straight piece of BNF
+% by enclosing it in a |\[[| \dots |\]]| pair.  Note that you can't mix 
+% syntax diagrams and BNF in a production rule, and you will get something
+% which looks very strange if you try.
+%
+% \DescribeMacro\alt
+% In addition, a command |\alt| is provided for splitting long production
+% rules over several lines: the |\alt| command starts a new line and places
+% a \syntax{|} character slightly in the left margin.  This is useful when
+% a symbol has many alternative productions.
+%
+% \begin{demo}[w]{The \env{grammar} environment}
+%\begin{grammar}
+%<statement> ::= <ident> `=' <expr>
+%  \alt `for' <ident> `=' <expr> `to' <expr> `do' <statement>
+%  \alt `{' <stat-list> `}'
+%  \alt <empty>
+%
+%<stat-list> ::= <statement> `;' <stat-list> | <statement>
+%\end{grammar}
+% \end{demo}
+%
+% You can modify the appearance of grammars using three length parameters:
+%
+% \begin{description} \def\makelabel{\hskip\labelsep\cmd}
+%
+% \item [\grammarparsep] is the amount of space inserted between production
+%       rules.  It is a rubber length whose default value is 8\,pt, with
+%       1\,pt of stretch and shrink.
+%
+% \item [\grammarindent] is the amount by which the right hand side of a
+%       production rule is indented from the left margin.  It is a rigid
+%       length.  Its default value is 2\,em.
+%
+% \end{description}
+%
+% \DescribeMacro\grammarlabel
+% You can also control how the `label' is typeset by redefining the
+% |\grammarlabel| command.  The command is given two arguments: the name of
+% the nonterminal (which was enclosed in angle brackets), and the `production
+% operator'.  The command is expected to produce the label.  By default, it
+% typesets the nonterminal name using |\synt| and the operator at opposite
+% ends of the label, separated by an |\hfill|.
+%
+% \subsection{Syntax diagrams}
+%
+% A full formal BNF grammar can be somewhat overwhelming for less technical
+% readers.  Documents aimed at such readers tend to display grammatical
+% structures as \emph{syntax diagrams}.
+%
+% \DescribeEnv{syntdiag}
+% A syntax diagram is always enclosed in a \env{syntdiag} environment.  You
+% should think of the environment as enclosing a new sort of \LaTeX\ mode:
+% trying to type normal text into a syntax diagram will result in very ugly
+% output.  \LaTeX\ ignores spaces and return characters while in syntax
+% diagram mode.
+%
+% The syntax of the environment is very simple:
+%
+% \begin{grammar}
+% <synt-diag-env> ::= \[[
+%   "\\begin{syntdiag}"
+%   \begin{stack} \\ "[" <decls> "]" \end{stack}
+%   <text>
+%   "\\end{syntdiag}"
+% \]]
+% \end{grammar}
+%
+% The \<decls> contain any declarations you want to insert, to control
+% the environment.  The parameters to tweak are described below.
+%
+% Within a syntax diagram, you can include syntactic items using the
+% abbreviated forms described elsewhere.  The output from these forms is
+% modified slightly in syntax diagram mode so that the diagram looks
+% right.
+%
+% I probably ought to point out now that the syntax diagram typesetting
+% commands produce beautiful-looking diagrams with all the rules and curves
+% accurately positioned.  Some device drivers don't position these objects
+% correctly in their output.  I've had particular trouble with |dvips|.  I'll
+% say it again: it's not my fault!
+%
+% \DescribeEnv{syntdiag*}
+% The \env{syntdiag} environment only works in paragraph mode, and it acts
+% rather like a paragraph, splitting over several lines when appropriate.
+% If you just want to typeset a snippet of a syntax diagram, you can
+% use the starred environment \env{syntdiag$*$}.
+%
+% \begin{grammar}
+% <synt-diag-star-env> ::= \[[
+%   "\\begin{syntdiag*}"
+%   \begin{stack} \\ "[" <decls> "]" \end{stack}
+%   \begin{stack} \\ "[" <width> "]" \end{stack}
+%   <text>
+%   "\\end{syntdiag*}"
+% \]]
+% \end{grammar}
+%
+% When typesetting little demos like this, it's not normal to fully adorn
+% the syntax diagram with the full double arrows
+% (`\begin{syntdiag*}[\left{>>-}\right{-><}]\tok{$\cdots$}\end{syntdiag*}').
+% The two declarations \syntax{"\\left{"<arrow>"}" and "\\right{"<arrow>"}"}
+% allow you to choose the arrows on each side of the syntax diagram snippet.
+% The possible values of \<arrow> are shown in the table-ette below:
+%
+% ^^A Time to remember what I learned about tables while writing mdwtab.
+% ^^A Just for the embarassment factor, here's the number of attempts I
+% ^^A took to get the table below to look right: __6.  Hmm... not as bad
+% ^^A as I expected.  Most of them were fine-tuning things.
+%
+% \medskip					^^A Leave a vertical gap
+% \hbox to\columnwidth{\hfil\vbox{\tabskip=0pt	^^A Centre it horizontally
+% \sdsize \csname sd@setsize\endcsname		^^A Position syntdiag arrows
+% \halign to .5\columnwidth{			^^A Set the table width
+%   &\ttfamily\ignorespaces#\unskip\hfil\tabskip=0pt ^^A Typeset the name
+%   &\quad\csname sd@arr@#\endcsname\hfil	^^A Typeset the arrow
+%   &\setbox0=\hbox{#}\tabskip=0pt plus 1fil\cr	^^A Stretch between columns
+%   >>-&>>-&   &>-&>-&   &->&->\cr
+%   -><&-><&   &...&...& &-&-\cr
+% }}\hfil}					^^A Close the boxing
+% \medskip					^^A And leave another gap
+%
+% These declarations should be used only in the optional argument to the
+% \env{syntdiag$*$} command.  The second optional argument to the
+% environment, if specified, fixes the width of the syntax diagram snippet;
+% if you omit this argument, the diagram is made just wide enough to
+% fit everything in.
+%
+% \begin{figure}
+% \begin{demo}[w]{Example of \env{syntdiag$*$}}
+%\newcommand{\bs}[2]{%
+%  \begin{minipage}{1.6in}%
+%  \begin{syntdiag*}[\left{#1}\right{#2}][1.6in]%
+%}
+%\newcommand{\es}{\end{syntdiag*}\end{minipage}}
+%
+%\begin{center}
+%\begin{tabular}{cl}                                      \\ \hline
+%\bf Construction    & \bf Meaning                        \\ \hline
+%\bs {>>-} {...} \es & Start of syntax diagram            \\
+%\bs {...} {-><} \es & End of syntax diagram              \\
+%\bs {>-}  {...} \es & Continued on next line             \\
+%\bs {...} {->}  \es & Continued from previous line       \\ \hline
+%\bs {...} {...}
+%  \begin{stack} <option-a> \\ <option-b> \\ <option-c> \end{stack}
+%\es                 & Alternatives: choose any one       \\
+%\bs {...} {...}
+%  \begin{rep} <repeat-me> \\ <separator> \end{rep}
+%\es                 & One or more items, with separators \\ \hline
+%\end{tabular}
+%\end{center}
+% \end{demo}
+% \end{figure}
+%
+% \DescribeMacro\tok
+% You can also include text using the |\tok| command.  The argument of this
+% command is typeset in \LaTeX's LR~mode and inserted into the diagram. 
+% Syntax abbreviations are allowed within the argument, so you can, for
+% example, include textual descriptions like
+% \begin{listing}
+%\tok{any <char> except `"'}
+% \end{listing}
+%
+% \DescribeEnv{stack}
+% Within a syntax diagram, a choice between several different items is
+% shown by stacking the alternatives vertically.  In \LaTeX, this is done
+% by enclosing the items in a \env{stack} environment.  Each individual item
+% is separated by |\\| commands, as in the \env{array} and \env{tabular}
+% environments.  Each row may contain any syntax diagram material, including
+% |\tok| commands and other \env{stack} environments.
+%
+% Note if you end a \env{stack} environment with a |\\| command, a blank
+% row is added to the bottom of the stack, indicating that none of the items
+% need be specified.
+%
+% \DescribeEnv{rep}
+% Text which can be repeated is enclosed in a \env{rep} environment: the
+% text is displayed with a backwards pointing arrow drawn over it, showing
+% that it may be repeated.  Optionally, you can specify text to be
+% displayed in the arrow, separating it from the main text with a |\\|
+% command.
+%
+% Note that items on the backwards arrow of a \env{rep} construction should
+% be displayed \emph{backwards}.  You must put the individual items in
+% reverse order when building this part of your diagrams.  \syn\ will 
+% correctly reverse the arrows on \env{rep} structures, but apart from
+% this, you must cope on your own.  You are recommended to keep these parts
+% of your diagrams as simple as possible to avoid confusing readers.
+%
+% \begin{demo}[w]{A syntax diagram}
+%\begin{syntdiag}
+%<ident> `('
+%  \begin{rep} \begin{stack} \\
+%    <type> \begin{stack} \\ <ident> \end{stack}
+%  \end{stack} \\ `,' \end{rep}
+%\begin{stack} \\ `...' \end{stack} `)'
+%\end{syntdiag}
+% \end{demo}
+%
+% \DescribeMacro\(
+% \DescribeMacro\)
+% \DescribeMacro\<
+% \DescribeMacro\>
+% \DescribeMacro\[
+% \DescribeMacro\]
+% The environments \env{stack} and \env{rep} are rather cumbersome to use.
+% As an alternative, the commands |\(| and |\)| are equivalent to
+% |\begin{stack}| and |\end{stack}| respectively, and |\<| and |\>| are
+% equivalent to |\begin{rep}| and |\end{rep}|.  Also, |\[| and |\]| are
+% like |\begin{stack}| and |\end{stack}| except that an empty initial row is
+% implicitly added.
+%
+% \subsubsection{Line breaking in syntax diagrams}
+%
+% Syntax diagrams are automatically broken over lines and across pages.
+% Lines are only broken between items on the outermost level of the diagram:
+% i.e., not within \env{stack} or \env{rep} environments.
+%
+% You can force a line break at a particular place by using the |\\| command
+% as usual.  This supports all the usual \LaTeX\ features: a `|*|' variant
+% which prohibits page breaking, and an optional argument specifying the
+% extra vertical space between lines.
+%
+% \subsubsection{Customising syntax diagrams}
+%
+% There are two basic styles of syntax diagrams supported:
+%
+% \begin{description}
+%
+% \item [square] Lines in the syntax diagram join at squared-off corners.
+%       This appears to be the standard way of displaying syntax diagrams
+%       in IBM manuals, and most other documents I've seen.
+%
+% \item [rounded] Lines curve around corners.  Also, no arrows are drawn
+%       around repeating loops: the curving of the lines provides this
+%       information instead.  This style is used in various texts on
+%       Pascal, and appears to be more popular in academic circles.
+%
+% \end{description}
+%
+% You can specify the style you want to use for syntax diagrams by giving
+% the style name as an option on the |\usepackage| command.  For example,
+% to force rounded edges to be used, you could say
+%
+% \begin{listing}
+%\usepackage[rounded]{syntax}
+% \end{listing}
+%
+% \DescribeMacro\sdsize
+% \DescribeMacro\sdlengths
+% The \env{syntdiag} environment takes an option argument, which should
+% contain declarations which are obeyed while the environment is set up.
+% The default value of this argument is `|\sdsize\sdlengths|'.  The
+% |\sdsize| command sets the default type size for the environment: this is
+% normally |\small|.  |\sdlengths| sets the values of the length parameters
+% used by the environment based on the current text size.  These parameters
+% are described below.
+%
+% For example, if you wanted to reduce the type size of the diagrams still
+% further, you could use the command
+% \begin{listing}
+%\begin{syntdiag}[\tiny\sdlengths]
+% \end{listing}
+%
+% The following length parameters may be altered:
+%
+% \begin{description} \def\makelabel{\hskip\labelsep\cmd}
+%
+% \item [\sdstartspace] The length of the rule between the arrows which
+%       begin each line of the syntax diagram and the first item on the line.
+%       Note that most objects have some space on either side of them as
+%       well.  This is a rubber length.  Its default value is 1\,em, although
+%       it can shrink by up to 10\,pt.
+%
+% \item [\sdendspace] The length of the rule between the last item on a
+%       line and the arrow at the very end.  Note that the final line also
+%       has extra rubber space on the end.  This is a rubber length.  Its
+%       default value is 1\,em, although it will shrink by up to 10\,pt.
+%
+% \item [\sdmidskip] The length of the rule on either side of a large
+%       construction (either a \env{stack} or a \env{rep}).  It is a rubber
+%       length.  Its default value is \smallf 1/2\,em, with a very small
+%       amount of infinite stretch.
+%
+% \item [\sdtokskip] The length of the rule on either side of a |\tok|
+%       item or syntax abbreviation.  It is a rubber length.  Its default
+%       value is \smallf 1/4\,em, with a very small amount of inifnite
+%       stretch.
+%
+% \item [\sdfinalskip] The length of the rule which finishes the last line
+%       of a syntax diagram.  It is a rubber length.  Its default value is
+%       \smallf 1/2\,em, with 10000\,fil of stretch, which will left-align
+%       the items on the line.\footnote{^^A
+%         This is a little \TeX nical.  The idea is that if a stray 1\,fil
+%         of stretch is added to the end of the line, it won't be noticed.
+%         However, the alignment of the text on the line can still be
+%         modified using \cmd{\sd@rule}\cmd{\hfill}, if you're feeling
+%         brave.
+%       }
+%
+% \item [\sdrulewidth] Half the width of the rules used in the diagram.
+%       It is a rigid length.  Its default value is 0.2\,pt.
+%
+% \item [\sdcirclediam] The diameter of the circle from which the quadrants
+%       used in rounded-style diagrams are taken.  This must be a multiple
+%       of 4\,pt, or else the lines on the diagram won't match up.
+%
+% \end{description}
+%
+% In addition, you should call |\sdsetstrut| passing it the total height
+% (\({\rm height}+{\rm depth}\)) of a normal line of text at the current
+% size.  Normally, the value of |\baselineskip| will be appropriate.
+%
+% You can also alter the appearance of \env{stack}s and \env{rep}s by using
+% their optional positioning arguments.  By default, \env{stack}s descend
+% below the main line of the diagram, and \env{rep}s extend above it.  
+% Specifying an optional argument of |[b]| for either environment reverses
+% this, putting \env{stack}s above and \env{rep}s below the line.
+%
+% \subsection{Changing the presentation styles}
+%
+% You can change the way in which the syntax items are typeset by altering
+% some simple commands (using |\renewcommand|).  Each item (nonterminals,
+% as typeset by |\synt|, and quoted and unquoted terminals, as typeset by
+% |\lit| and |\lit*|) has two style commands associated with it, as shown
+% in the table below.
+%
+% \begin{tab}{lll}						   \hline
+% \bf Syntax item	& \bf Left command & \bf Right command	\\ \hline
+% Nonterminals		& |\syntleft|	   & |\syntright|	\\
+% Quoted terminals	& |\litleft|	   & |\litright|	\\
+% Unquoted terminals	& |\ulitleft|	   & |\ulitright|	\\ \hline
+% \end{tab}
+%
+% It's not too hard to see how this works.  For example, if you look at
+% the implementation for |\syntleft| and |\syntright| in the implementation
+% section, you'll notice that they're defined like this:
+% \begin{listing}
+%\newcommand{\syntleft}{$\langle$\normalfont\itshape}
+%\newcommand{\syntright}{$\rangle$}
+% \end{listing}
+% I think this is fairly simple, if you understand things like font changing.
+%
+% Note that changing these style commands alters the appearance of all syntax
+% objects of the appropriate types, as created by the |\synt| and |\lit|
+% commands, in \env{grammar} environments, and in syntax diagrams.
+%
+%
+% \section{Change history}
+%
+% \subsection*{Version 1.07}
+%
+% \begin{itemize}
+% \item Fixed problem with underscore hacking in a \env{tabbing} environment.
+% \end{itemize}
+%
+% \subsection*{Version 1.06}
+%
+% \begin{itemize}
+% \item Added style hooks for syntax items.
+% \item Improved colour handling in syntax diagrams, thanks to the |\doafter|
+%       package.
+% \item Fixed some nasty bugs in the \env{grammar} environment which confused
+%       other lists and ruined the spacing.  The \env{grammar} handling is
+%       now much tidier in general.
+% \end{itemize}
+%
+% \subsection*{Version 1.05}
+%
+% \begin{itemize}
+% \item Fixed `the bug' in the syntax diagram typesetting.  It now breaks
+%       lines almost psychically, and doesn't break in the wrong places.
+% \item Almost rewrote the \env{grammar} environment.  It now does lots of
+%       the list handling itself, to allow more versatile typesetting of the
+%       left hand sides.  There's lots of evil in there now.
+% \item Added some more configurability.  In particular, two new settings
+%       have been added to control \env{grammar} environments, and a neat
+%       way of adding new syntax diagram structures has been introduced.
+% \end{itemize}
+%
+% \subsection*{Version 1.04}
+%
+% \begin{itemize}
+% \item Changed the vertical positioning of the rules, to make all the text
+%       line up properly.  While the old version was elegant and simple, it
+%       had the drawback of looking nasty.
+% \item Allow line breaks at underscores, but don't if there's another one
+%       afterwards.  Also, prevent losing following space if underscore is
+%       written to a file.
+% \end{itemize}
+%
+% \subsection*{Version 1.02}
+%
+% \begin{itemize}
+% \item Added support for rounded corners in syntax diagrams.
+% \item Changed lots of |\hskip| commands to |\kern|s, to prevent possible
+%       line breaks.
+% \end{itemize}
+%
+% \subsection*{Version 1.01}
+%
+% \begin{itemize}
+% \item Allowed disabling of underscore active character, to avoid messing
+%       up filenames.
+% \item Added |\grammarparsep| and |\grammarindent| length parameters to
+%       control the appearance of grammars.
+% \end{itemize}
+%
+% \implementation
+%
+% \section{Implementation of \syn}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+% \subsection{Options handling}
+%
+% We define all the options we know about, and then see what's been put
+% on the usepackage line.
+%
+% The options we provide currently are as follows:
+%
+% \begin{description}
+% \item [rounded] draws neatly rounded edges on the diagram.
+% \item [square] draws squared-off edges on the diagram.  This is the
+%       default.
+% \item [nounderscore] disables the undescore active character,  The |\_|
+%       command still produces the nice version created here.
+% \end{description}
+%
+%    \begin{macrocode}
+\DeclareOption{rounded}{\sd@roundtrue}
+\DeclareOption{square}{\sd@roundfalse}
+\DeclareOption{nounderscore}{\@uscorefalse}
+%    \end{macrocode}
+%
+% Now process the options:
+%
+%    \begin{macrocode}
+\newif\ifsd@round
+\newif\if@uscore\@uscoretrue
+\newif\ifsd@left\newif\ifsd@right
+\ExecuteOptions{square}
+\ProcessOptions
+%    \end{macrocode}
+%
+% \subsection{Special character handling}
+%
+% A lot of the \syn\ package requires the use special active characters.
+% These must be added to two lists: |\dospecials|, which is used by |\verb|
+% and friends, and |\@sanitize|, which is used by |\index|.  The two macros
+% here, |\addspecial| and |\remspecial|, provide these registration
+% facilities.
+%
+% Two similar macros are found in Frank Mittelbach's \package{doc} package:
+% these have the disadvantage of global operation.  My macros here are based
+% on Frank's, which in turn appear to be based on Donald Knuth's list
+% handling code presented in Appendix~D of \textit{The \TeX book}.
+%
+% Both these macros take a single argument: a single-character control
+% sequence containing the special character to be added to or removed from
+% the lists.
+%
+% \begin{macro}{\addspecial}
+%
+% This is reasonably straightforward.  We remove the sequence from the lists,
+% in case it's already there, and add it in in the obvious way.  This
+% requires a little bit of fun with |\expandafter|.
+%
+%    \begin{macrocode}
+\def\addspecial#1{%
+  \remspecial{#1}%
+  \expandafter\def\expandafter\dospecials\expandafter{\dospecials\do#1}%
+  \expandafter\def\expandafter\@santize\expandafter{%
+    \@sanitize\@makeother#1}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\remspecial}
+%
+% This is the difficult bit.  Since |\dospecials| and |\@sanitize| have the
+% form of list macros, we can redefine |\do| and |\@makeother| to do the
+% job for us.  We must be careful to put the old meaning of |\@makeother|
+% back.  The current implementation assumes it knows what |\@makeother| does.
+%
+%    \begin{macrocode}
+\def\remspecial#1{%
+  \def\do##1{\ifnum`#1=`##1 \else\noexpand\do\noexpand##1\fi}%
+  \edef\dospecials{\dospecials}%
+  \def\@makeother##1{\ifnum`#1=`##1 \else%
+    \noexpand\@makeother\noexpand##1\fi}%
+  \edef\@sanitize{\@sanitize}%
+  \def\@makeother##1{\catcode`##112}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{Underscore handling}
+%
+% When typing a lot of identifiers, it can be irksome to have to escape
+% all `|_|' characters in the manuscript.  We make the underscore character
+% active, so that it typesets an underscore in horizontal mode, and does
+% its usual job as a subscript operator in maths mode.  Underscore must
+% already be in the special character lists, because of its use as a
+% subscript character, so this doesn't cause us a problem.
+%
+% \begin{macro}{\underscore}
+%
+% The |\underscore| macro typesets an underline character, using a horizontal
+% rule.  This is positioned slightly below the baseline, and is also slightly
+% wider than the default \TeX\ underscore.  This code is based on a similar
+% implementation found in the \package{lgrind} package.
+%
+%    \begin{macrocode}
+\def\underscore{%
+  \leavevmode%
+  \kern.06em%
+  \vbox{%
+    \hrule\@width.6em\@depth.4ex\@height-.34ex%
+  }%
+  \ifdim\fontdimen\@ne\font=\z@%
+    \kern.06em%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\@foundunderscore}
+%
+% This macro is called by the `|_|' active character to sort out what to do.
+%
+% If this is maths mode, we use the |\sb| macro, which is already defined
+% to do subscripting.  Otherwise, we call |\textunderscore|, which picks the
+% nicest underscore it can find.
+%
+% There's some extra cunningness here, because I'd like to be able to
+% hyphenate after underscores usually, but not when there's another one
+% following.  And then, because \env{tabbing} redefines |\_|, there's some
+% more yukkiness to handle that: the usual |\@tabacckludge| mechanism doesn't
+% cope with this particular case.
+%
+%    \begin{macrocode}
+\let\usc@builtindischyphen\-
+\def\@uscore.{%
+  \ifmmode%
+    \expandafter\@firstoftwo%
+  \else%
+    \expandafter\@secondoftwo%
+  \fi%
+  \sb%
+  {\textunderscore\@ifnextchar_{}{\usc@builtindischyphen}}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% Now we set up the active character.  Note the |\protect|, which makes
+% underscores work reasonably well in moving arguments.  Note also the way
+% we end with a some funny stuff to prevent spaces being lost if this is
+% written to a file.
+%
+%    \begin{macrocode}
+\if@uscore
+  \AtBeginDocument{%
+    \catcode`\_\active%
+    \begingroup%
+    \lccode`\~`\_%
+    \lowercase{\endgroup\def~{\protect\@uscore.}}%
+  }
+\fi
+%    \end{macrocode}
+%
+% Finally, we redefine the |\_| macro to use our own |\underscore|, because
+% it's prettier.  Actually, we don't: we just redefine the
+% |\?\textunderscore| command (funny name, isn't it?).
+%
+%    \begin{macrocode}
+\expandafter\let\csname?\string\textunderscore\endcsname\underscore
+%    \end{macrocode}
+%
+% \subsection{Abbreviated verbatim notation}
+%
+%  In similar style to the \package{doc} package, we allow the user to set up
+% characters which delimit verbatim text.  Unlike \package{doc}, we make
+% such changes local to the current group.  This is performed through the
+% |\shortverb| and |\unverb| commands.
+%
+% The implementations of these commands are based upon the |\MakeShortVerb|
+% and |\DeleteShortVerb| commands of the \package{doc} package, although
+% these versions have effect local to the current grouping level.  This
+% prevents their redefinition of |\dospecials| from interfering with the
+% grammar shortcuts, which require local changes only.
+%
+% The command |\shortverb| takes a single argument: a single-character
+% control sequence defining which character to make into the verbatim text
+% delimiter.  We store the old meaning of the active character in a control
+% sequence called |\mn@\|\<char>.  Note that this control sequence
+% contains a backslash character, which is a little odd.  We also define a
+% command |\cc@\|\<char> which will return everything to normal.  This
+% is used by the |\unverb| command.
+%
+% \begin{macro}{\shortverb}
+%
+% Here we build the control sequences we need to make everything work nicely.
+% The active character is defined via |\lowercase|, using the |~| character:
+% this is already made active by \TeX\@.
+%
+% The actual code requires lots of fiddling with |\expandafter| and friends.
+%
+%    \begin{macrocode}
+\def\shortverb#1{%
+%    \end{macrocode}
+%
+% First, we check to see if the command |\cc@\|\<char> has been defined.
+%
+%    \begin{macrocode}
+  \@ifundefined{cc@\string#1}{%
+%    \end{macrocode}
+%
+% If it hasn't been defined, we add the character to the specials list.
+%
+%    \begin{macrocode}
+    \addspecial#1%
+%    \end{macrocode}
+%
+% Now we set our character to be the lowercase version of |~|, which allows
+% us to use it, even though we don't know what it is.
+%
+%    \begin{macrocode}
+    \begingroup%
+    \lccode`\~`#1%
+%    \end{macrocode}
+%
+% Finally, we reach the tricky bit.  All of this is lowercased, so any
+% occurrences of |~| are replaced by the user's special character.
+%
+%    \begin{macrocode}
+    \lowercase{%
+      \endgroup%
+%    \end{macrocode}
+%
+% We remember the current meaning of the character, in case it has one.  We
+% have to use |\csname| to build the rather strange name we use for this.
+%
+%    \begin{macrocode}
+      \expandafter\let\csname mn@\string#1\endcsname~%
+%    \end{macrocode}
+%
+% Now we build |\cc@\|\<char>.  This is done with |\edef|, since more
+% of this needs to be expanded now than not.  In this way, the actual macros
+% we create end up being very short.
+%
+%    \begin{macrocode}
+      \expandafter\edef\csname cc@\string#1\endcsname{%
+%    \end{macrocode}
+%
+% First, add a command to restore the character's old catcode.
+%
+%    \begin{macrocode}
+        \catcode`\noexpand#1\the\catcode`#1%
+%    \end{macrocode}
+%
+% Now we restore the character's old meaning, using the version we saved
+% earlier.
+%
+%    \begin{macrocode}
+        \let\noexpand~\expandafter\noexpand%
+          \csname mn@\string#1\endcsname%
+%    \end{macrocode}
+%
+% Now we remove the character from the specials lists.
+%
+%    \begin{macrocode}
+        \noexpand\remspecial\noexpand#1%
+%    \end{macrocode}
+%
+% Finally, we delete this macro, so that |\unverb| will generate a warning
+% if the character is |\unverb|ed again.
+%
+%    \begin{macrocode}
+        \let\csname cc@\string#1\endcsname\relax%
+      }%
+%    \end{macrocode}
+%
+% All of that's over now.  We set up the new definition of the character,
+% in terms of |\verb|, and make the character active.  The nasty |\syn@ttspace|
+% is there to make the spacing come out right.  It's all right really.  Honest.
+%
+%    \begin{macrocode}
+      \def~{\verb~\syn@ttspace}%
+    }%
+    \catcode`#1\active%
+%    \end{macrocode}
+%
+% If our magic control sequence already existed, we can assume that the
+% character is already a verbatim delimiter, and raise a warning.
+%
+%    \begin{macrocode}
+  }{%
+    \PackageWarning{syntax}{Character `\expandafter\@gobble\string#1'
+                            is already a verbatim\MessageBreak
+                            delimiter}%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\unverb}
+%
+% This is actually terribly easy: we just use the |\cc@\|\<char> command
+% we definied earlier, after making sure that it's been defined.
+%
+%    \begin{macrocode}
+\def\unverb#1{%
+  \@ifundefined{cc@\string#1}{%
+    \PackageWarning{syntax}{Character `\expandafter\@gobble\string#1'
+                            is not a verbatim\MessageBreak
+                            delimiter}%
+  }{%
+    \csname cc@\string#1\endcsname%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{Style hooks for syntax forms}
+%
+% To allow the appearance of syntax things to be configured, we provide some
+% redefinable bits.
+%
+% The three types of objects (nonterminal symbols, and quoted and unquoted
+% terminals) each have two macros associated with them: one which does the
+% `left' bit of the typesetting, and one which does the `right' bit.  The
+% items are typeset as LR~boxes.  I'll be extra good while defining these
+% hooks, so that it's obvious what's going on; macho \TeX\ hacker things
+% resume after this section.
+%
+% \begin{macro}{\syntleft}
+% \begin{macro}{\syntright}
+%
+% I can't see why anyone would want to change the typesetting of
+% nonterminals, although I'll provide the hooks for symmetry's sake.
+%
+%     \begin{macrocode}
+\newcommand{\syntleft}{$\langle$\normalfont\itshape}
+\newcommand{\syntright}{$\rangle$}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ulitleft}
+% \begin{macro}{\ulitright}
+% \begin{macro}{\litleft}
+% \begin{macro}{\litright}
+%
+% Now we can define the left and right parts of quoted and unquoted
+% terminals.  US~readers may want to put double quotes around the quoted
+% terminals, for example.
+%
+%    \begin{macrocode}
+\newcommand{\ulitleft}{\normalfont\ttfamily\syn@ttspace\frenchspacing}
+\newcommand{\ulitright}{}
+\newcommand{\litleft}{`\bgroup\ulitleft}
+\newcommand{\litright}{\ulitright\egroup'}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Simple syntax typesetting}
+%
+% In general text, we allow access to our typesetting conventions through
+% standard \LaTeX\ commands.
+%
+% \begin{macro}{\synt}
+%
+% The |\synt| macro typesets its argument as a syntactic quantity.  It puts
+% the text of the argument in italics, and sets angle brackets around it.
+% Breaking of a |\synt| object across lines is forbidden.
+%
+%    \begin{macrocode}
+\def\synt#1{\mbox{\syntleft{#1\/}\syntright}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\lit}
+%
+% The |\lit| macro typesets its argument as literal text, to be typed in.
+% Normally, this means setting the text in |\tt| font, and putting quotes
+% around it, although the quotes can be suppressed by using the $*$-variant.
+%
+% The |\syn@ttspace| macro sets up the spacing for the text nicely: |\tt|
+% spaces tend to be a little wide.
+%
+%    \begin{macrocode}
+\def\lit{\@ifstar{\lit@i\ulitleft\ulitright}{\lit@i\litleft\litright}}
+\def\lit@i#1#2#3{\mbox{#1{#3\/}#2}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\syn@ttspace}
+%
+% This sets up the |\spaceskip| value for |\tt| text.
+%
+%    \begin{macrocode}
+\def\syn@ttspace@{\spaceskip.35em\@plus.2em\@minus.15em\relax}
+%    \end{macrocode}
+%
+% However, this isn't always the right thing to do.
+%
+%    \begin{macrocode}
+\def\ttthinspace{\let\syn@ttspace\syn@ttspace@}
+\def\ttthickspace{\let\syn@ttspace\@empty}
+%    \end{macrocode}
+%
+% I know what I like thoough.
+%
+%    \begin{macrocode}
+\ttthinspace
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{The shortcuts}
+%
+% The easy part is over now.  The next job is to set up the `grammar
+% shortcuts' which allow easy changing of styles.
+%
+% We support four shortcuts:
+% \begin{itemize}
+% \item |`literal text'| typesets \syntax{`literal text'}
+% \item |<non-terminal>| typesets \syntax{<non-terminal>}
+% \item |"unquoted text"| typesets \syntax{"unquoted text"}
+% \item \verb"|" typesets a \syntax{|} character
+% \end{itemize}
+% These are all implemented through active characters, which are enabled
+% using the |\syntaxShortcuts| macro, described below.
+%
+% \begin{macro}{\readupto}
+%
+% \syntax{"\\readupto{"<char>"}{"<decls>"}{"<command>"}"} will read all
+% characters up until the next occurrence of \<char>.  Normally, all
+% special characters will be deactivated.  However, you can reactivate some
+% characters, using the \<decls> argument, which is processed before the
+% text is read.
+%
+% The code is borrowed fairly obviously from the \LaTeXe\ source for the
+% |\verb| command.
+%
+%    \begin{macrocode}
+\def\readupto#1#2#3{%
+  \bgroup%
+  \verb@eol@error%
+  \let\do\@makeother\dospecials%
+  #2%
+  \catcode`#1\active%
+  \lccode`\~`#1%
+  \gdef\verb@balance@group{\verb@egroup%
+     \@latex@error{\noexpand\verb illegal in command argument}\@ehc}%
+  \def\@vhook{\verb@egroup#3}%
+  \aftergroup\verb@balance@group%
+  \lowercase{\let~\@vhook}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\syn@assist}
+%
+% The |\syn@assist| macro is used for defining three of the shortcuts.  It
+% is called as
+%
+% \begin{quote}
+% \syntax{"\\syn@assist{"<left-decls>"}{"<actives>"}{"<delimeter>"}" \\
+% \null \quad "{"<right-decls>"}{"<end-cmd>"}"}
+% \end{quote}
+%
+% It creates an hbox, sets up the escape sequences for quoting our magic
+% characters, and then typesets a box containing
+%
+% \begin{quote}
+% \syntax{<left-decls>"{"<delimited-text>"\\/}"<right-decls>}
+% \end{quote}
+%
+% The \<left-decls> and \<right-decls> can be |\relax| if they're not
+% required.
+%
+% The \<actives> argument is passed to |\readupto|, to allow some special
+% characters through.  By default, we re-enable |\|, and make `\verb*" "'
+% typeset some space glue, rather than a space character.  A macro
+% `\verb*"\ "' is defined to actually print a space character, which yield
+% `\verb*" "' in the `|\tt|' font. 
+%
+% Finally, it defines a |\ch| command, which, given a single-character
+% control sequence as its argument, typesets the character.  This is useful,
+% since |`| has been made active when we set up these calls, so the
+% direct |\char`\|\<char> doesn't work.
+%
+%    \begin{macrocode}
+\def\syn@assist#1#2#3#4#5{%
+%    \end{macrocode}
+%
+% First, we start the box, and open a group.  We use |\mbox| because it
+% does all the messing with |\leavevmode| which is needed.
+%
+%    \begin{macrocode}
+  \leavevmode\hbox\bgroup%
+%    \end{macrocode}
+%
+% Next job is to set up the escape sequences.
+%
+%    \begin{macrocode}
+  \chardef\\`\\%
+  \chardef\>`\>%
+  \chardef\'`\'%
+  \chardef\"`\"%
+  \chardef\ `\ %
+%    \end{macrocode}
+%
+% Now to define |\ch|.  This is done the obvious way.
+%
+%    \begin{macrocode}
+  \def\ch##1{\char`##1}%
+%    \end{macrocode}
+%
+% For active characters, we do some fiddling with |\lccode|s.
+%
+%    \begin{macrocode}
+  \def\act##1{%
+    \catcode`##1\active%
+    \begingroup%
+    \lccode`\~`##1%
+    \lowercase{\endgroup\def~}%
+  }%
+%    \end{macrocode}
+%
+% Finally, we do the real work of setting the text.  We use |\readupto| to
+% actually find the text we want.
+%
+%    \begin{macrocode}
+  #1%
+  \begingroup%
+  \readupto#3{%
+    \catcode`\\0%
+    \catcode`\ 10%
+    #2%
+  }{%
+    \/\endgroup#4\egroup#5%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\syn@shorts}
+%
+% This macro actually defines the expansions for the active characters.
+% We have to do this separately because |`| must be active when we use it
+% in the |\def|, but we can't do that and use |\catcode| at the same time.
+% The arguments are commands to do before and after the actual command.
+% These are passed up from |\syntaxShortcuts|.
+%
+% All of the characters use |\syn@assist| in the obvious way except for
+% \verb"|", which drops into maths mode instead.
+%
+% Note that when changing the catcodes, we must save |`| until last.
+%
+%    \begin{macrocode}
+\begingroup
+\catcode`\<\active
+\catcode`\|\active
+\catcode`\"\active
+\catcode`\`\active
+%
+\gdef\syn@shorts#1#2{%
+%    \end{macrocode}
+%
+% The `|<|' character must typeset its argument in italics.  We make `|_|'
+% do the same as the `|\_|' command.
+%
+%    \begin{macrocode}
+  \def<{%
+    #1%
+    \syn@assist%
+      \syntleft%
+      {\act_{\@uscore.}}%
+      >%
+      \syntright%
+      {#2}%
+  }%
+%    \end{macrocode}
+%
+% The `|`|' and `|"|' characters should print its argument in |\tt| font.
+% We change the `|\tt|' space glue to provide nicer spacing on the line.
+%
+%    \begin{macrocode}
+  \def`{%
+    #1%
+    \syn@assist%
+      \litleft%
+      \relax%
+      '%
+      \litright%
+      {#2}%
+  }%
+  \def"{%
+    #1%
+    \syn@assist%
+      \ulitleft%
+      \relax%
+      "%
+      \ulitright%
+      {#2}%
+  }%
+%    \end{macrocode}
+%
+% Finally, the `\verb"|"' character is typeset by using the mysterious
+% |\textbar| command.
+%
+%    \begin{macrocode}
+  \def|{\textbar}%
+%    \end{macrocode}
+%
+% We're finished here now.
+%
+%    \begin{macrocode}
+}
+%
+\endgroup
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\syntaxShortcuts}
+%
+% This is a user-level command which enables the use of our shortcuts in the
+% current group.  It uses |\addspecial|, defined below, to register the
+% active characters, sets up their definitions and activates them.
+%
+% The two arguments are commands to be performed before and after the
+% handling of the abbreviation.  In this way, you can further process the
+% output.
+%
+% This command is not intended to be used directly by users: it should be
+% used by other macros and packages which wish to take advantage of the
+% facilities offered by this package.  We provide a |\synshorts| declaration
+% (which may be used as an environment, of course) which is more `user
+% palatable'.
+%
+%    \begin{macrocode}
+\def\syntaxShortcuts#1#2{%
+  \syn@shorts{#1}{#2}%
+  \addspecial\`%
+  \addspecial\<%
+  \addspecial\|%
+  \addspecial\"%
+  \catcode`\|\active%
+  \catcode`\<\active% 
+  \catcode`\"\active%
+  \catcode`\`\active%
+}
+%
+\def\synshorts{\syntaxShortcuts\relax\relax}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\synshortsoff}
+%
+% This macro can be useful occasionally: it disables the syntax shortcuts,
+% so you can type normal text for a while.
+%
+%    \begin{macrocode}
+\def\synshortsoff{%
+  \catcode`\|12%
+  \catcode`\<12%
+  \catcode`\"12%
+  \catcode`\`12%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\syntax}
+%
+% The |\syntax| macro typesets its argument, allowing the use of our
+% shortcuts within the argument.
+%
+% Actually, we go to some trouble to ensure that the argument to |\syntax|
+% \emph{isn't} a real argument so we can change catcodes as we go.  We
+% use the |\let\@let@token=| trick from \PlainTeX\ to do this.
+%
+%    \begin{macrocode}
+\def\syntax#{\bgroup\syntaxShortcuts\relax\relax\let\@let@token}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{environment}{grammar}
+%
+% The \env{grammar} environment is the final object we have to define.  It
+% allows typesetting of beautiful BNF grammars.
+%
+% First, we define the length parameters we need:
+%
+%    \begin{macrocode}
+\newskip\grammarparsep
+  \grammarparsep8\p@\@plus\p@\@minus\p@
+\newdimen\grammarindent
+  \grammarindent2em
+%    \end{macrocode}
+%
+% Now define the default label typesetting.  This macro is designed to be
+% replaced by a user, so we'll be extra-well-behaved and use genuine \LaTeX\
+% commands.  Well, almost \dots
+%
+%    \begin{macrocode}
+\newcommand{\grammarlabel}[2]{%
+  \synt{#1} \hfill#2%
+}
+%    \end{macrocode}
+%
+% Now for a bit of hacking to make the item stuff work properly.  This gets
+% done for every new paragraph that's started without an |\item| command.
+%
+% First, store the left hand side of the production in a box.  Then I'll
+% end the paragraph, and insert some nasty glue to take up all the space,
+% so no-one will ever notice that there was a paragraph break there.  The
+% strut just makes sure that I know exactly how high the line is.
+%
+%    \begin{macrocode}
+\def\gr@implitem<#1> #2 {%
+  \sbox\z@{\hskip\labelsep\grammarlabel{#1}{#2}}%
+  \strut\@@par%
+  \vskip-\parskip%
+  \vskip-\baselineskip%
+%    \end{macrocode}
+%
+% The |\item| command will notice that I've inserted these funny glues and
+% try to remove them: I'll stymie its efforts by inserting an invisible
+% rule.  Then I'll insert the label using |\item| in the normal way.
+%
+%    \begin{macrocode}
+  \hrule\@height\z@\@depth\z@\relax%
+  \item[\unhbox\z@]%
+%    \end{macrocode}
+%
+% Just before I go, I'll make \lit{<} back into an active character.
+%
+%    \begin{macrocode}
+  \catcode`\<\active%
+}
+%    \end{macrocode}
+%
+% Now for the environment proper.  Deep down, it's a list environment, with
+% some nasty tricks to stop anyone from noticing.
+%
+% The first job is to set up the list from the parameters I'm given.
+%
+%    \begin{macrocode}
+\newenvironment{grammar}{%
+  \list{}{%
+    \labelwidth\grammarindent%
+    \leftmargin\grammarindent%
+    \advance\grammarindent\labelsep
+    \itemindent\z@%
+    \listparindent\z@%
+    \parsep\grammarparsep%
+  }%
+%    \end{macrocode}
+%
+% We have major problems in |\raggedright| layouts, which try to use |\par|
+% to start new lines.  We go back to normal |\\| newlines to try and bodge
+% our way around these problems.
+%
+%    \begin{macrocode}
+  \let\\\@normalcr
+%    \end{macrocode}
+%
+% Now to enable the shortcuts.
+%
+%    \begin{macrocode}
+  \syntaxShortcuts\relax\relax%
+%    \end{macrocode}
+%
+% Now a little bit of magic.  The |\alt| macro moves us to a new line, and
+% typesets a vertical bar in the margin.  This allows typesetting of
+% multiline alternative productions in a pretty way.
+%
+%    \begin{macrocode}
+  \def\alt{\\\llap{\textbar\quad}}%
+%    \end{macrocode}
+%
+% Now for another bit of magic.  We set up some |\par| cleverness to spot
+% the start of each production rule and format it in some cunning and
+% user-defined way.
+%
+%    \begin{macrocode}
+  \def\gr@setpar{%
+    \def\par{%
+      \parshape\@ne\@totalleftmargin\linewidth%
+      \@@par%
+      \catcode`\<12%
+      \everypar{%
+        \everypar{}%
+        \catcode`\<\active%
+        \gr@implitem%
+      }%
+    }%
+  }%
+  \gr@setpar%
+  \par%
+%    \end{macrocode}
+%
+% Now set up the |\[[| and |\]]| commands to do the right thing.  We have
+% to check the next character to see if it's correct, otherwise we'll
+% open a maths display as usual.
+%
+%    \begin{macrocode}
+  \let\gr@leftsq\[%
+  \let\gr@rightsq\]%
+  \def\gr@endsyntdiag]{\end{syntdiag}\gr@setpar\par}%
+  \def\[{\@ifnextchar[{\begin{syntdiag}\@gobble}\gr@leftsq}%
+  \def\]{\@ifnextchar]\gr@endsyntdiag\gr@rightsq}%
+%    \end{macrocode}
+%
+% Well, that's it for this side of the environment.
+%
+%    \begin{macrocode}
+}{%
+%    \end{macrocode}
+%
+% Closing the environment is a simple matter of tidying away the list.
+%
+%    \begin{macrocode}
+  \@newlistfalse%
+  \everypar{}%
+  \endlist%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \subsection{Syntax diagrams}
+%
+% Now we come to the final and most complicated part of the package.
+%
+% Syntax diagrams are drawn using arrow characters from \LaTeX's line font,
+% used in the \env{picture} environment, and rules.  The horizontal rules
+% of the diagram are drawn along the baselines of the lines in which they
+% are placed.  The text items in the diagram are placed in boxes and lowered
+% below the main baseline.  Struts are added throughout to keep the vertical
+% spacing consistent.
+%
+% The vertical structures (stacks and loops) are all implemented with \TeX's
+% primitive |\halign| command.
+%
+% \subsubsection{User-configurable parameters}
+%
+% First, we allocate the \<dimen> and \<skip> arguments needed.  Fixed
+% lengths, as the \LaTeX book calls them, are allocated as \<dimen>s, to
+% take some of the load off of all the \<skip> registers.
+%
+%    \begin{macrocode}
+\newskip\sdstartspace
+\newskip\sdendspace
+\newskip\sdmidskip
+\newskip\sdtokskip
+\newskip\sdfinalskip
+\newdimen\sdrulewidth
+\newdimen\sdcirclediam
+\newdimen\sdindent
+%    \end{macrocode}
+%
+% We need some \TeX\ \<dimen>s for our own purposes, to get everything in
+% the right places.  We use labels for the `temporary' \TeX\ parameters
+% which we use, to avoid wasting registers.
+%
+%    \begin{macrocode}
+\dimendef\sd@lower\z@
+\dimendef\sd@upper\tw@
+\dimendef\sd@mid4
+\dimendef\sd@topcirc6
+\dimendef\sd@botcirc8
+\skipdef\sd@qskip2
+%    \end{macrocode}
+%
+% \begin{macro}{\sd@setsize}
+% When the text size for syntax diagrams changes, it's necessary to work out
+% the height for various rules in the diagram.
+%
+%    \begin{macrocode}
+\def\sd@setsize{%
+  \sd@mid\ht\strutbox%
+  \advance\sd@mid-\dp\strutbox%
+  \sd@mid.5\sd@mid%
+  \sd@upper\sdrulewidth%
+    \advance\sd@upper\sd@mid%
+  \sd@lower\sdrulewidth%
+    \advance\sd@lower-\sd@mid%
+  \sd@topcirc-.5\sdcirclediam%
+    \advance\sd@topcirc\sd@mid%
+  \sd@botcirc-.5\sdcirclediam%
+    \advance\sd@botcirc-\sd@mid%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sdsize}
+%
+% You can set the default type size used by syntax diagrams by redefining
+% the |\sdsize| command, using the |\renewcommand| command.
+%
+% By default, syntax diagrams are set slightly smaller than the main body
+% text.\footnote{^^A
+%   I've used pure \LaTeX\ commands for this and the \cmd\sdlengths\ macro,
+%   to try and illustrate how these values might be changed by a user.  The
+%   rest of the code is almost obfuscted in its use of raw \TeX\ features,
+%   in an attempt to dissuade more na\"\i ve users from fiddling with it.
+%   I suppose this is what you get when you let assembler hackers loose with
+%   something like \LaTeX.
+% }
+%
+%    \begin{macrocode}
+\newcommand{\sdsize}{%
+  \small%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sdlengths}
+%
+% Finally, the default length parameters are set in the |\sdlengths| command.
+% You can redefine the command using |\renewcommand|.
+%
+% We set up the length parameters here.
+%
+%    \begin{macrocode}
+\newcommand{\sdlengths}{%
+  \setlength{\sdstartspace}{1em minus 10pt}%
+  \setlength{\sdendspace}{1em minus 10pt}%
+  \setlength{\sdmidskip}{0.5em plus 1em}%
+  \setlength{\sdtokskip}{0.25em plus 1em}%
+  \setlength{\sdfinalskip}{0.5em plus 10000fil}%
+  \setlength{\sdrulewidth}{0.2pt}%
+  \setlength{\sdcirclediam}{8pt}%
+  \setlength{\sdindent}{0pt}%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Other declarations}
+%
+% We define four switches.  The table shows what they're used for.
+%
+% \begin{table}
+% \begin{tab}{lp{3in}}                                              \hline
+%
+% \bf Switch        & \bf Meaning                                \\ \hline
+%
+% |\ifsd@base|      & We are at `base level' in the diagram:
+%                     i.e., not in any other sorts of
+%                     constructions.  This is used to decide
+%                     whether to allow line breaking.            \\[2pt]
+%
+% |\ifsd@top|       & The current loop construct is being
+%                     typeset with the loop arrow above the
+%                     baseline.                                  \\[2pt]
+%
+% |\ifsd@toplayer|  & We are typesetting the top layer of
+%                     a stack.  This is used to ensure that
+%                     the vertical rules on either side are
+%                     typeset at the right height.               \\[2pt]
+%
+% |\ifsd@backwards| & We're typesetting backwards, because
+%                     we're in the middle of a loop arrow.
+%                     the only difference this makes is that
+%                     any subloops have the arrow on the
+%                     side.                                      \\ \hline
+%
+% \end{tab}
+% \caption{Syntax diagram switches}
+% \end{table}
+%
+%    \begin{macrocode}
+\newif\ifsd@base
+\newif\ifsd@top
+\newif\ifsd@toplayer
+\newif\ifsd@backwards
+%    \end{macrocode}
+%
+% \begin{macro}{\sd@err}
+%
+% We output our errors through this macro, which saves a little typing.
+%
+%    \begin{macrocode}
+\def\sd@err{\PackageError{syntax}}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Arrow-drawing}
+%
+% We need to draw some arrows.  \LaTeX\ tries to make this as awkward as
+% possible, so we have to start moving the arrows around in boxes quite a
+% lot.
+%
+% The left and right pointing arrows are fairly simple: we just add some
+% horizontal spacing to prevent the width of the arrow looking odd.
+%
+%    \begin{macrocode}
+\def\sd@arrow{%
+  \ht\tw@\z@%
+  \dp\tw@\z@%
+  \raise\sd@mid\box\tw@%
+  \egroup%
+}
+\def\sd@rightarr{%
+  \bgroup%
+  \setbox\tw@\hbox{\kern-6\p@\@linefnt\char'55}%
+  \sd@arrow%
+}
+\def\sd@leftarr{%
+  \bgroup%
+  \raise\sd@mid\hbox{\@linefnt\char'33\kern-6\p@}%
+  \sd@arrow%
+}
+%    \end{macrocode}
+%
+% The up arrow is very strange.  We need to bring the arrow down to base
+% level, and smash its height.
+%
+%    \begin{macrocode}
+\def\sd@uparr{%
+  \bgroup%
+  \setbox\tw@\hb@xt@\z@{\kern-\sdrulewidth\@linefnt\char'66\hss}%
+  \setbox\tw@\hbox{\lower10\p@\box\tw@}%
+  \sd@arrow%
+}
+%    \end{macrocode}
+%
+% The down arrow is similar, although it's already at the right height.
+% Thus, we can just smash the box.
+%
+%    \begin{macrocode}
+\def\sd@downarr{%
+  \bgroup%
+  \setbox\tw@\hb@xt@\z@{\kern-\sdrulewidth\@linefnt\char'77\hss}%
+  \sd@arrow%
+}
+%    \end{macrocode}
+%
+% \subsubsection{Drawing curves}
+%
+% If the user has selected curved edges, we use the \LaTeX\ features provided
+% to obtain the curves.  These are drawn slightly oddly to make it easier
+% to fit them into the diagram.
+%
+% Some explanation about the \LaTeX\ circle font is probably called for
+% before we go any further.  The font consists of sets of four quadrants
+% of a particular size (and some other characters, which aren't important
+% at the moment).  Each collection of quadrants fit together to form a
+% perfect circle of a given diameter.  The individual quadrant characters
+% have strange bounding boxes, as described in the files \textit{lcircle.mf}
+% and \textit{ltpict.dtx}, and also in Appendix~D of \textit{The \TeX book}.
+% Our job here is to make these quadrants useful in the context of
+% drawing syntax diagrams.
+%
+% \begin{macro}{\sd@circ}
+% First, we define |\sd@circ|, which performs the common parts of the four
+% routines.  Since the characters in the circle font are grouped together,
+% we can pick out a particular corner piece by specifying its index into
+% the group for the required size.  The |\sd@circ| routine will pick out
+% the required character, given this index as an argument, and put it in
+% box~2, after fiddling with the sizes a little:
+% \begin{itemize}
+%
+% \item We clear the width to zero.  The individual routines then add a kern
+%       of the correct amount, so that the quadrant appears in the right
+%       place.
+%
+% \item The piece is lowered by half the rule width.  This positions the
+%       top and bottom pieces of the circle to be half way over the baseline,
+%       which is the correct position for the rest of the diagram.
+%
+% \end{itemize}
+%
+% Finally, we make sure we're in horizontal mode: horrific results occur
+% if this is not the case.  I'm sure I don't need to explain this any more
+% graphically.
+%
+%    \begin{macrocode}
+\def\sd@circ#1{%
+  \@getcirc\sdcirclediam%
+  \advance\@tempcnta#1%
+  \setbox\tw@\hbox{\lower\sdrulewidth%
+    \hbox{\@circlefnt\char\@tempcnta}}%
+  \wd\tw@\z@%
+  \leavevmode%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sd@tlcirc}
+% \begin{macro}{\sd@trcirc}
+% \begin{macro}{\sd@blcirc}
+% \begin{macro}{\sd@brcirc}
+%
+% These are the macros which actually draw quadrants of circles.  They all
+% call |\sd@circ|, passing an appropriate index, and then fiddle with the
+% box sizes and apply kerning specific to the quadrant positioning.
+%
+% The exact requirements for positioning are as follows:
+%
+% \begin{itemize}
+%
+% \item The horizontal parts of the arcs must lie along the baseline (i.e.,
+%       half the line must be above the baseline, and half must be below).
+%       This is consistent with the horizontal rules used in the diagram.
+%
+% \item The vertical parts must overlap vertical rules on either side, so
+%       that a |\vrule\sd@|\textit{xx}|circ| makes the arc appear to be
+%       a real curve in the line.  The requirements are actually somewhat
+%       inconsistent; for example, the \env{stack} environment uses curves
+%       \emph{before} the |\vrule|s.  Special requirements like this are
+%       handled as special cases later.
+%
+% \item The height and width of the arc are at least roughly correct.
+%
+% \end{itemize}
+%
+%    \begin{macrocode}
+\def\sd@tlcirc{{%
+  \sd@circ3%
+  \ht\tw@\sdrulewidth%
+  \dp\tw@.5\sdcirclediam%
+  \kern-\tw@\sdrulewidth%
+  \raise\sd@mid\box\tw@%
+  \kern.5\sdcirclediam%
+}}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\sd@trcirc{{%
+  \sd@circ0%
+  \ht\tw@\sdrulewidth%
+  \dp\tw@.5\sdcirclediam%
+  \kern.5\sdcirclediam%
+  \raise\sd@mid\box\tw@%
+}}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\sd@blcirc{{%
+  \sd@circ2%
+  \ht\tw@.5\sdcirclediam%
+  \dp\tw@\sdrulewidth%
+  \kern-\tw@\sdrulewidth%
+  \raise\sd@mid\box\tw@%
+  \kern.5\sdcirclediam%
+}}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\sd@brcirc{{%
+  \sd@circ1%
+  \ht\tw@.5\sdcirclediam%
+  \dp\tw@\sdrulewidth%
+  \kern.5\sdcirclediam%
+  \raise\sd@mid\box\tw@%
+}}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\sd@nocirc{\sd@rule\hskip.5\sdcirclediam\relax}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\sd@llc}
+% \begin{macro}{\sd@rlc}
+%
+% In the \env{rep} environment, we need to be able to draw arcs with
+% horizontal lines running through them.  The two macros here do the job
+% nicely.  |\sd@llc| (which is short for left overlapping circle) is
+% analogous to |\llap|: it puts its argument in a box of zero width, sticking
+% out to the left.  However, it also draws a rule along the baseline.  This
+% is important, as it prevents text from overprinting the arc.  |\sd@rlc|
+% is very similar, just the other way around.
+%
+%    \begin{macrocode}
+\def\sd@llc#1{%
+  \hb@xt@.5\sdcirclediam{%
+    \sd@rule\hskip.5\sdcirclediam%
+    \hss%
+    #1%
+  }%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\def\sd@rlc#1{%
+  \hb@xt@.5\sdcirclediam{%
+    #1%
+    \hss%
+    \sd@rule\hskip.5\sdcirclediam%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+% \subsubsection{Drawing rules}
+%
+% It's important to draw the rules \emph{along} the baseline, rather than
+% above it: hence, the depth of the rule must be equal to the height.
+%
+% \begin{macro}{\sd@rule}
+%
+% We use rule leaders instead of glue through most of the syntax diagrams.
+% The command \syntax{"\\sd@rule"<skip>} draws a rule of the correct
+% dimensions, which has the behaviour of an \syntax{"\\hskip"<skip>}.
+%
+%    \begin{macrocode}
+\def\sd@rule{\leaders\hrule\@height\sd@upper\@depth\sd@lower}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sd@gap}
+%
+% The gap between elements is added using this macro.  It will allow a
+% line break if we're at the top level of the diagram, using a rather
+% strange discretionary.
+%
+% This is called as \syntax{"\\sd@gap{"<skip-register>"}"}.
+%
+%    \begin{macrocode}
+\def\sd@gap#1{%
+%    \end{macrocode}
+%
+% First, we see if we're at the top level.  Within constructs, we avoid the
+% overhead of a |\discretionary|.  We put half of the width of the skip on
+% each side of the discretionary break.
+%
+%    \begin{macrocode}
+  \ifsd@left%
+    \ifsd@base%
+      \skip@#1%
+        \divide\skip\z@\tw@%
+      \nobreak\sd@rule\hskip\skip@%
+      \discretionary{%
+        \sd@qarrow{->}%
+      }{%
+        \hbox{%
+          \sd@qarrow{>-}%
+          \sd@rule\hskip\sdstartspace%
+          \sd@rule\hskip3.5\p@%
+        }%
+      }{%
+      }%
+      \nobreak\sd@rule\hskip\skip@%
+%    \end{macrocode}
+%
+% If we're not at the base level, we just put in a rule of the correct
+% width.
+%
+%    \begin{macrocode}
+    \else%
+      \sd@rule\hskip#1%
+    \fi%
+  \fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sd@qgap}
+% \begin{macro}{\sd@dequeue}
+%
+% This is the high-level interface to spacing in syntax diagrams.  Stuff only
+% gets printed if the diagram's actually started yet, and hasn't finished.
+%
+%    \begin{macrocode}
+\def\sd@qgap#1{%
+  \ifsd@left%
+    \ifsd@right\advance\sd@qskip#1\relax%
+    \else\sd@gap#1\fi%
+  \fi%
+}
+\def\sd@dequeue{\ifsd@left\sd@gap\sd@qskip\sd@qskip\z@\fi}
+%    \end{macrocode}
+%
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\sd@abbrev}
+%
+% Sets up syntax diagram abbreviations.
+%
+%    \begin{macrocode}
+\def\sd@abbrev{%
+  \def\({\begin{stack}}%
+  \def\){\end{stack}}%
+  \def\<{\begin{rep}}%
+  \def\>{\end{rep}}%
+  \expandafter\def%
+    \csname\ifx\gr@leftsq\@@undefined[\else gr@leftsq\fi\endcsname%
+    {\begin{stack}\\}%
+  \expandafter\let%
+    \csname\ifx\gr@rightsq\@@undefined]\else gr@rightsq\fi\endcsname%
+    \)%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{The \protect\env{syntdiag} environment}
+%
+% All syntax diagrams are contained within a \env{syntdiag} environment.
+%
+% \begin{environment}{syntdiag}
+%
+% The only argument is a collection of declarations, which by
+% default is
+%
+% \begin{listing}
+%\sdsize\sdlengths
+% \end{listing}
+%
+% However, if the optional argument is not specified, \TeX\ reads the first
+% character of the environment, which may not be catcoded correctly.  We set
+% up the catcodes first, using the |\syntaxShortcuts| command, and then read
+% the argument.  We don't use |\newcommand|, because that would involve
+% creating yet \emph{another} macro.  Time to fiddle with |\@ifnextchar|
+% \dots
+%
+%    \begin{macrocode}
+\def\syntdiag{%
+  \syntaxShortcuts\sd@tok@i\sd@tok@ii%
+  \sd@abbrev%
+  \@ifnextchar[\syntdiag@i{\syntdiag@i[]}%
+}
+\def\syntdiag@i[#1]{\@ifnextchar[{\syntdiag@ii{#1}}{\syntdiag@ii{#1}[b]}}
+%    \end{macrocode}
+%
+% Now we actually do the job we're meant to.
+%
+%    \begin{macrocode}
+\def\syntdiag@ii#1[#2]{%
+%    \end{macrocode}
+%
+% The first thing to do is execute the user's declarations.  We then set
+% up things for the font size.
+%
+%    \begin{macrocode}
+  \sdsize\sdlengths%
+  #1%
+  \sd@setsize%
+%    \end{macrocode}
+%
+% Sort out the omission of left or right sides.
+%
+%    \begin{macrocode}
+  \sd@lefttrue\sd@righttrue%
+  \if#2l\sd@rightfalse\fi%
+  \if#2r\sd@leftfalse\fi%
+%    \end{macrocode}
+%
+% Next, we start a list, to change the text layout.
+%
+%    \begin{macrocode}
+  \list{}{%
+    \leftmargin\sdindent%
+    \rightmargin\leftmargin%
+    \labelsep\z@%
+    \labelwidth\z@%
+  }%
+  \item[]%
+%    \end{macrocode}
+%
+% We reconfigure the paragraph format quite a lot now.  We clear
+% |\parfillskip| to avoid any justification at the end of the paragraph.
+% We also turn off paragraph indentation.
+%
+%    \begin{macrocode}
+  \parfillskip\z@%
+  \noindent%
+%    \end{macrocode}
+%
+% Next, we add in the arrows on the beginning of the line, and a bit of
+% glue.
+%
+%    \begin{macrocode}
+  \ifsd@left%
+    \sd@qarrow{>>-}%
+    \nobreak\sd@rule\hskip\sdstartspace%
+   \fi%
+%    \end{macrocode}
+%
+% This is the base level of the diagram, so we enable line breaking.
+%
+%    \begin{macrocode}
+  \sd@basetrue%
+%    \end{macrocode}
+%
+% Since the objects being broken are rather large, we enable sloppy line
+% breaking.  We also try to avoid page breaks in mid-diagram, by upping the
+% |\interlinepenalty|.
+%
+%    \begin{macrocode}
+  \sloppy%
+  \interlinepenalty100%
+  \hyphenpenalty0%
+%    \end{macrocode}
+%
+% We handle all the spacing within the environment, so we make \TeX\ ignore
+% spaces and newlines.
+%
+%    \begin{macrocode}
+  \catcode`\ 9%
+  \catcode`\^^M9%
+%    \end{macrocode}
+%
+% We now have to change the behaviour of |\\| to line-break syntax diagrams.
+%
+%    \begin{macrocode}
+  \let\\\sd@newline%
+  \ignorespaces%
+}
+%    \end{macrocode}
+%
+% When we end the diagram, we just have to add in the final fillskip, and
+% double arrow.
+%
+%    \begin{macrocode}
+\def\endsyntdiag{%
+  \unskip%
+  \ifsd@right%
+    \nobreak\sd@rule\hskip\sdmidskip%
+    \sd@rule\hskip\sdfinalskip%
+    \sd@qarrow{-><}%
+  \else%
+    \hskip\sdfinalskip%
+    \vadjust{}%
+  \fi%
+  \endlist%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{environment}{syntdiag*}
+%
+% The starred form of \env{syntdiag} typesets a syntax diagram in LR-mode;
+% this is useful if you're describing parts of syntax diagrams, for example.
+%
+% This is in fact really easy.  The first bit which checks for an optional
+% argument is almost identical to the non-$*$ version.
+%
+%    \begin{macrocode}
+\@namedef{syntdiag*}{%
+  \syntaxShortcuts\sd@tok@i\sd@tok@ii%
+  \sd@abbrev%
+  \@tempswatrue%
+  \@ifnextchar[\syntdiag@s@i{\syntdiag@s@i[]}%
+}
+%    \end{macrocode}
+%
+% Handle another optional argument giving the width of the box to fill.
+%
+%    \begin{macrocode}
+\def\syntdiag@s@i[#1]{%
+  \@ifnextchar[{\syntdiag@s@ii{#1}}{\syntdiag@s@iii{#1}{\hbox}}%
+}
+\def\syntdiag@s@ii#1[#2]{%
+  \def\@tempa{#2}\def\@tempb{*}%
+  \ifx\@tempa\@tempb%
+    \@tempswafalse%
+    \syntdiag@s@iii{#1}{}%
+  \else%
+    \syntdiag@s@iii{#1}{\hb@xt@#2}%
+  \fi%
+}
+%    \end{macrocode}
+%
+% Now to actually start the display.  This is mostly simple.  Just to make
+% sure about the LR-ness of the typesetting, I'll put everything in an hbox.
+%
+%    \begin{macrocode}
+\def\syntdiag@s@iii#1#2{%
+  \leavevmode%
+  #2\bgroup%
+%    \end{macrocode}
+%
+% Now configure the typesetting according to the user's wishes.
+%
+%    \begin{macrocode}
+  \let\@@left\left%
+  \let\@@right\right%
+  \def\left##1{\def\sd@startarr{##1}}%
+  \def\right##1{\def\sd@endarr{##1}}%
+  \left{>-}\right{->}%
+  \sdsize\sdlengths%
+  #1%
+  \sd@setsize%
+  \let\left\@@left%
+  \let\right\@@right%
+  \sd@lefttrue\sd@righttrue%
+  \ifx\sd@startarr\@empty\sd@leftfalse\fi%
+  \ifx\sd@endarr\@empty\sd@rightfalse\fi%
+%    \end{macrocode}
+%
+% Put in the initial double-arrow.
+%
+%    \begin{macrocode}
+  \ifsd@left%
+    \sd@qarrow\sd@startarr%
+    \sd@rule\hskip\sdmidskip%
+  \fi%
+%    \end{macrocode}
+%
+% We're in horizontal mode, so don't bother with linebreaking.
+%
+%    \begin{macrocode}
+  \if@tempswa\sd@basefalse\else\sd@basetrue\fi%
+%    \end{macrocode}
+%
+% Finally, disable spaces and things.
+%
+%    \begin{macrocode}
+  \catcode`\ 9%
+  \catcode`\^^M9%
+  \ignorespaces%
+}
+%    \end{macrocode}
+%
+% Ending the environment is very similar.
+%
+%    \begin{macrocode}
+\@namedef{endsyntdiag*}{%
+  \unskip%
+  \ifsd@right%
+    \sd@rule\hskip\sdmidskip%
+    \ifsd@base\else\sd@rule\hskip\sdfinalskip\fi%
+    \sd@qarrow\sd@endarr%
+  \else%
+    \hskip\sdmidskip%
+    \ifsd@base\else\hskip\sdfinalskip\fi%
+  \fi%
+  \egroup%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \begin{macro}{\sd@qarrow}
+%
+% This typesets the various left and right arrows required in syntax
+% diagrams.  The argument is one of \syntax{`>>-', `->', `>-' or `-><'}.
+%
+%    \begin{macrocode}
+\def\sd@qarrow#1{%
+  \begingroup%
+  \lccode`\~=`\<\lowercase{\def~{<}}%
+  \hbox{\csname sd@arr@#1\endcsname}%
+  \endgroup%
+}
+\@namedef{sd@arr@>>-}{\sd@rightarr\kern-.5\p@\sd@rightarr\kern-\p@}
+\@namedef{sd@arr@>-}{\sd@rightarr\kern-\p@}
+\@namedef{sd@arr@->}{\sd@rightarr}
+\@namedef{sd@arr@-><}{\sd@rightarr\kern-\p@\sd@leftarr}
+\@namedef{sd@arr@...}{$\cdots$}
+\@namedef{sd@arr@-}{}
+\@namedef{sd@arr@}{}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sd@newline}
+%
+% The line breaking within a syntax diagram is controlled by the
+% |\sd@newline| command, to which |\\| is assigned.
+%
+% We support all the standard \LaTeX\ features here.  The line breaking
+% involves adding a fill skip and arrow, moving to the next line, adding
+% an arrow and a rule, and continuing.
+%
+%    \begin{macrocode}
+\def\sd@newline{\@ifstar{\vadjust{\penalty\@M}\sd@nl@i}\sd@nl@i}
+\def\sd@nl@i{\@ifnextchar[\sd@nl@ii\sd@nl@iii}
+\def\sd@nl@ii[#1]{\vspace{#1}\sd@nl@iii}
+\def\sd@nl@iii{%
+  \nobreak\sd@rule\hskip\sdmidskip%
+  \sd@rule\hskip\sdfinalskip%
+  \kern-3\p@%
+  \sd@rightarr%
+  \newline%
+  \sd@rightarr%
+  \nobreak\sd@rule\hskip\sdstartspace%
+  \sd@rule\hskip3.5\p@%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Putting things in the right place}
+%
+% Syntax diagrams have fairly stiff requirements on the positioning of text
+% relative to the diagram's rules.  To help people (and me) to write
+% extensions to the syntax diagram typesetting which automatically put things
+% in the right place, I provide some simple macros.
+%
+% \begin{environment}{sdbox}
+%
+% By placing some text in the \env{sdbox} environment, it will be read into a
+% box and then output at the correct height for the syntax diagram.  Note
+% that stuff in the box is set in horizontal (LR) mode, so you'll have to use
+% a \env{minipage} if you want formatted text.  The macro also supplies rules
+% on either side of the box, with a length given in the environment's
+% argument.
+%
+% Macro writers are given explicit permission to use this environment through
+% the |\sdbox| and |\endsdbox| commands if this makes life easier.
+%
+% The calculation in the |\endsdbox| macro works out how to centre the box
+% vertically over the baseline.  If the box's height is~$h$, and its depth
+% is~$d$, then its centre-line is $(h+d)/2$ from the bottom of the box.
+% Since the baseline is already $d$ from the bottom, we need to lower the box
+% by $(h+d)/2 - d$, or $h/2-d/2$.
+%
+%    \begin{macrocode}
+\def\sdbox#1{%
+  \@tempskipa#1\relax%
+  \sd@gap\@tempskipa%
+  \setbox\z@\hbox\bgroup%
+    \begingroup%
+    \catcode`\ 10%
+    \catcode`\^^M5%
+    \synshortsoff%
+}
+\def\endsdbox{%
+    \endgroup%
+  \egroup%
+  \@tempdima\ht\z@%
+  \advance\@tempdima-\dp\z@%
+  \advance\@tempdima-\tw@\sd@mid%
+  \lower.5\@tempdima\box\z@%
+  \sd@lefttrue%
+  \sd@gap\@tempskipa%
+}
+%    \end{macrocode}
+%
+% \end{environment}
+%
+% \subsubsection{Typesetting syntactic items}
+%
+% Using the hooks built into the syntax abbreviations above, we typeset
+% the text into a box, and write it out, centred over the baseline.  A strut
+% helps to keep the actual text baselines level for short pieces of text.
+%
+% \begin{macro}{\sd@tok@i}
+%
+% The preamble for a syntax abbreviation.  We start a box, and set the
+% space and return characters to work again.  A strut is added to the box to
+% ensure correct vertical spacing for normal text.
+%
+%    \begin{macrocode}
+\def\sd@tok@i{%
+  \sdbox\sdtokskip%
+  \strut%
+  \space%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sd@tok@ii}
+%
+%    \begin{macrocode}
+\def\sd@tok@ii{%
+  \space%
+  \endsdbox%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{Inserting other pieces of text}
+%
+% Arbitrary text may be put into a syntax diagram through the use of the
+% |\tok| macro.  Its `argument' is typeset in the same way as a syntactic
+% item (centred over the baseline).  The implementation goes to some effort
+% to ensure that the text is not actually an argument, to allow category
+% codes to change while the text is being typeset.
+%
+% \begin{macro}{\tok}
+%
+% We start a box, and make space and return do their normal jobs.  We use
+% |\aftergroup| to regain control once the box is finished.  |\doafter| is
+% used to get control after the group finishes.
+%
+%    \begin{macrocode}
+\def\tok#{%
+  \sdbox\sdtokskip%
+  \strut%
+  \enspace%
+  \syntaxShortcuts\relax\relax%
+  \doafter\sd@tok%
+}
+%    \end{macrocode}
+%
+% The |\sd@tok| macro is similar to |\sd@tok@ii| above.
+%
+%    \begin{macrocode}
+\def\sd@tok{%
+  \enspace%
+  \endsdbox%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{The \protect\env{stack} environment}
+%
+% The \env{stack} environment is used to present alternatives in a syntax
+% diagram.  The alternatives are separated by |\\| commands.
+%
+% \begin{macro}{\stack}
+%
+% Handle the optional arguments.
+%
+%    \begin{macrocode}
+\def\stack{\@ifnextchar[\stack@i{\stack@i[t]}}
+\def\stack@i[#1]{\@ifnextchar[{\stack@ii{#1}}{\stack@ii{#1}[b]}}
+\def\stack@ii#1[#2]{%
+%    \end{macrocode}
+%
+% First, we add some horizontal space.
+%
+%    \begin{macrocode}
+  \sd@gap\sdmidskip%
+%    \end{macrocode}
+%
+% We're within a complex construction, so we need to clear the |\ifsd@base|
+% flag.
+%
+%    \begin{macrocode}
+  \begingroup\sd@basefalse%
+%    \end{macrocode}
+%
+% The top and bottom rows of the stack are different to the others, since
+% the vertical rules mustn't extend all the way up the side of the item.
+% The bottom row is handled separately by |\endstack| below.  The top row
+% must be handled via a flag, |\ifsd@toplayer|.
+%
+% Initially, the flag must be set true.
+%
+%    \begin{macrocode}
+  \sd@toplayertrue%
+%    \end{macrocode}
+%
+% We set the |\\| command to separate the items in the |\halign|.
+%
+%    \begin{macrocode}
+  \let\\\sd@stackcr%
+%    \end{macrocode}
+%
+% Sort out which sides of the construction are actually emitted.
+%
+%    \begin{macrocode}
+  \sd@righttrue\if#2l\sd@rightfalse\fi%
+%    \end{macrocode}
+%
+% The actual structure must be set in vertical mode, so we must place it
+% in a box.  The position argument determines whether this must be a
+% |\vbox| or a |\vtop|.  We also insert a bit of rounding if the options say
+% we must.
+%
+%    \begin{macrocode}
+  \if#1t%
+    \let\@tempa\vtop%
+    \sd@toptrue%
+    \ifsd@left\ifsd@round\llap{\sd@trcirc\kern\tw@\sdrulewidth}\fi\fi%
+  \else\if#1b%
+    \let\@tempa\vbox%
+    \sd@topfalse%
+    \ifsd@left\ifsd@round\llap{\sd@brcirc\kern\tw@\sdrulewidth}\fi\fi%
+  \else%
+    \sd@err{Bad position argument passed to stack}%
+           {The positioning argument must be one of `t' or `b'.  I%
+            have^^Jassumed you meant to type `t'.}%
+    \let\@tempa\vtop%
+  \fi\fi%
+%    \end{macrocode}
+%
+% Now we start the box, which we will complete at the end of the environment.
+%
+%    \begin{macrocode}
+  \@tempa\bgroup%
+%    \end{macrocode}
+%
+% We must remove any extra space between rows of the table, since the rules
+% will not join up correctly.  We can use |\offinterlineskip| safely, since
+% each individual row contains a strut.
+%
+%    \begin{macrocode}
+  \offinterlineskip%
+%    \end{macrocode}
+%
+% Now we can start the alignment.  We actually use \PlainTeX's |\ialign|
+% macro, which also clears |\tabskip| for us.
+%
+%    \begin{macrocode}
+  \ialign\bgroup%
+%    \end{macrocode}
+%
+% The preamble is trivial, since we must do all of the work ourselves
+%
+%    \begin{macrocode}
+    ##\cr%
+%    \end{macrocode}
+%
+% We can now start putting the text into a box ready for typesetting later.
+% The strut makes the vertical spacing correct.
+%
+%    \begin{macrocode}
+  \setbox\z@\hbox\bgroup%
+    \strut%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\endstack}
+%
+% The first part of this is similar to the |\sd@stackcr| macro below, except
+% that the vertical rules are different.  We don't support rounded edges
+% on single-row stacks, although this isn't a great loss to humanity.
+%
+%    \begin{macrocode}
+\def\endstack{%
+  \ifsd@right\else\unskip\fi%
+  \egroup%
+  \ifsd@toplayer%
+    \sd@dostack\sd@upper\sd@lower\sd@nocirc\sd@nocirc%
+  \else%
+    \ifsd@round%
+      \ifsd@top%
+        \sd@dostack{\ht\z@}\sd@botcirc\sd@blcirc\sd@brcirc%
+      \else%
+        \sd@dostack{\ht\z@}\sd@botcirc\sd@nocirc\sd@nocirc%
+      \fi%
+    \else%
+      \sd@dostack{\ht\z@}\sd@lower\relax\relax%
+    \fi%
+  \fi%
+%    \end{macrocode}
+%
+% We now close the |\halign| and the vbox we created.
+%
+%    \begin{macrocode}
+  \egroup%
+  \egroup%
+%    \end{macrocode}
+%
+% Deal with any rounding we started off.
+%
+%    \begin{macrocode}
+  \ifsd@right\ifsd@round%
+    \ifsd@top
+      \rlap{\kern\tw@\sdrulewidth\sd@tlcirc}%
+    \else%
+      \rlap{\kern\tw@\sdrulewidth\sd@blcirc}%
+    \fi%
+  \fi\fi%
+%    \end{macrocode}
+%
+% Finally, we add some horizontal glue to space the diagram out.
+%
+%    \begin{macrocode}
+  \endgroup\sd@lefttrue\ifsd@right\sd@gap\sdmidskip\fi%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sd@stackcr}
+%
+% The |\\| command is set to this macro during a \env{stack} environment.
+%
+%    \begin{macrocode}
+\def\sd@stackcr{%
+%    \end{macrocode}
+%
+% The first job is to close the box containing the previous item.
+%
+%    \begin{macrocode}
+  \ifsd@right\else\unskip\fi%
+  \egroup%
+%    \end{macrocode}
+%
+% Now we typeset the vertical rules differently depending on whether this is
+% the first item in the stack.  This looks quite terrifying initially, but
+% it's just an enumeration of the possible cases for the different values
+% of |\ifsd@toplayer|, |\ifsd@top| and |\ifsd@round|, putting in appropriate
+% rules and arcs in the right places.
+%
+%    \begin{macrocode}
+  \ifsd@toplayer%
+    \ifsd@round%
+      \ifsd@top%
+        \sd@dostack\sd@topcirc{\dp\z@}\sd@nocirc\sd@nocirc%
+      \else%
+        \sd@dostack\sd@topcirc{\dp\z@}\sd@tlcirc\sd@trcirc%
+      \fi%
+    \else%
+      \sd@dostack\sd@upper{\dp\z@}\relax\relax%
+    \fi%
+  \else%
+    \ifsd@round%
+      \ifsd@top%
+        \sd@dostack{\ht\z@}{\dp\z@}\sd@blcirc\sd@brcirc%
+      \else%
+        \sd@dostack{\ht\z@}{\dp\z@}\sd@tlcirc\sd@trcirc%
+      \fi%
+    \else%
+      \sd@dostack{\ht\z@}{\dp\z@}\relax\relax%
+    \fi%
+  \fi%
+%    \end{macrocode}
+%
+% The next item won't be the first, so we clear the flag.
+%
+%    \begin{macrocode}
+  \sd@toplayerfalse%
+%    \end{macrocode}
+%
+% Now we have to set up the next cell.  We put the text into a box again.
+%
+%    \begin{macrocode}
+  \setbox\z@\hbox\bgroup%
+    \strut%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sd@dostack}
+%
+% Actually typesetting the text in a cell is performed here.  The macro is
+% called as
+% \begin{quote}\synshorts
+% "\\sd@dostack{"<height>"}{"<depth>"}{"<left-arc>"}{"<right-arc>"}"
+% \end{quote}
+% where \<height> and \<depth> are the height and depth of the vertical
+% rules to put around the item, and \<left-arc> and \<right-arc> are
+% commands to draw rounded edges on the left and right hand sides of the
+% item.
+%
+% The values for the height and depth are quite often going to be the height
+% and depth of box~0.  Since we empty box~0 in the course of typesetting the
+% row, we need to cache the sizes on entry.
+%
+%    \begin{macrocode}
+\def\sd@dostack#1#2#3#4{%
+  \@tempdima#1%
+  \@tempdimb#2%
+  \ifsd@left%
+    \kern-\tw@\sdrulewidth%
+    \vrule\@height\@tempdima\@depth\@tempdimb\@width\tw@\sdrulewidth%
+    #3%
+    \sd@rule\hfil%
+    \sd@gap\sdtokskip%
+  \else%
+    \hfill%
+  \fi%
+  \unhbox\z@%
+  \ifsd@right%
+    \sd@gap\sdtokskip%
+    \sd@rule\hfil%
+    #4%
+    \vrule\@height\@tempdima\@depth\@tempdimb\@width\tw@\sdrulewidth%
+    \kern-\tw@\sdrulewidth%
+  \else%
+    \hfill%
+  \fi%
+  \cr%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsubsection{The \protect\env{rep} environment}
+%
+% The \env{rep} environment is used for typesetting loops in the diagram.
+% Again, we use |\halign| for the typesetting.  Loops are simpler than
+% stacks, however, since there are always two rows.  We store both rows in
+% box registers, and build the loop at the end.
+%
+% \begin{macro}{\rep}
+%
+% Again, we use |\newcommand| to process the optional argument.
+%
+%    \begin{macrocode}
+\newcommand\rep[1][t]{%
+%    \end{macrocode}
+%
+% First, leave a gap on the left side.
+%
+%    \begin{macrocode}
+  \sd@gap\sdmidskip%
+%    \end{macrocode}
+%
+% We're not at base level any more, so disable linebreaking.
+%
+%    \begin{macrocode}
+  \begingroup\sd@basefalse%
+%    \end{macrocode}
+%
+% Remember we're going backwards now.
+%
+%    \begin{macrocode}
+  \ifsd@backwards\sd@backwardsfalse\else\sd@backwardstrue\fi%
+%    \end{macrocode}
+%
+% Define |\\| to separate the two parts of the loop.
+%
+%    \begin{macrocode}
+   \let\\\sd@loop%
+%    \end{macrocode}
+%
+% Now check the argument, and use the appropriate type of box.  In addition
+% to changing the typesetting, we must remember which way up to typeset the
+% loop, since the end code must always put the first argument on the
+% baseline, with the loop either above or below.
+%
+%    \begin{macrocode}
+  \if#1t%
+    \let\@tempa\vbox%
+    \sd@toptrue%
+  \else\if#1b%
+    \let\@tempa\vtop%
+    \sd@topfalse%
+  \else%
+    \sd@err{Bad position argument passed to loop}%
+           {The positioning argument must be `t' or `b'.  I have^^J%
+            assumed you meant to type `t'.}%
+    \let\@tempa\vbox%
+    \sd@toptrue%
+  \fi\fi%
+%    \end{macrocode}
+%
+% Now we start the box.
+%
+%    \begin{macrocode}
+  \@tempa\bgroup%
+%    \end{macrocode}
+%
+% The loop is by default empty, apart from a strut.  This is put into box~1.
+%
+%    \begin{macrocode}
+  \setbox\tw@\copy\strutbox%
+%    \end{macrocode}
+%
+% Now start typesetting the main text in box~0.
+%
+%    \begin{macrocode}
+  \setbox\z@\hbox\bgroup\strut%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\endrep}
+%
+% The final code must first close whatever box was open.
+%
+%    \begin{macrocode}
+\def\endrep{%
+  \egroup%
+%    \end{macrocode}
+%
+% Now we typeset the loop, depending on which way up it was meant to be.
+% Again, this terrifying piece of code is a simple list of possibile values
+% of our various flags.
+%
+%    \begin{macrocode}
+  \ifsd@top%
+    \ifsd@round%
+      \sd@doloop\tw@\z@\relax\relax%
+        \sd@tlcirc\sd@trcirc{\sd@rlc\sd@blcirc}{\sd@llc\sd@brcirc}%
+    \else%
+      \sd@doloop\tw@\z@\relax\sd@downarr\relax\relax\relax\relax%
+    \fi%
+  \else%
+    \ifsd@round%
+      \sd@doloop\z@\tw@\relax\relax%
+        {\sd@rlc\sd@tlcirc}{\sd@llc\sd@trcirc}\sd@blcirc\sd@brcirc%
+    \else%
+      \sd@doloop\z@\tw@\sd@uparr\relax\relax\relax\relax\relax%
+    \fi%
+  \fi%
+%    \end{macrocode}
+%
+% Close the vbox we opened.
+%
+%    \begin{macrocode}
+  \egroup%
+%    \end{macrocode}
+%
+% Finally, we leave a gap before the next structure.
+%
+%    \begin{macrocode}
+  \endgroup\sd@gap\sdmidskip%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sd@loop}
+%
+% This macro handles the |\\| command within a loop environment.  We close
+% the current box, and start filling in box~1.  We also redefine |\\| to
+% raise an error when the |\\| command is used again.
+%
+%    \begin{macrocode}
+\def\sd@loop{%
+  \egroup%
+  \def\\{\sd@err{Too many \string\\\space commands in loop}\@ehc}%
+  \setbox\tw@\hbox\bgroup\strut%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sd@doloop}
+%
+% This is the macro which actually creates the |\halign| for the loop.  It
+% is called with four arguments, as:
+% \begin{quote}\synshorts
+% "\\sd@doloop{"<top-box>"}{"<bottom-box>"}"^^A
+%                "{"<top-arrow>"}{"<btm-arrow>"}" \\
+% \hbox{}\quad "{"<top-left-arc>"}{"<top-right-arc>"}"^^A
+%                "{"<bottom-left-arc>"}{"<btm-right-arc>"}"^^A
+% \kern-1in ^^A It may be overfull, but it looks OK to me ;-)
+% \end{quote}
+%
+% The two \<box> arguments give the numbers of boxes to extract in the top
+% and bottom rows of the alignment.  The \<arrow> arguments specify
+% characters to typeset at the end of the top and bottom rows for arrows.
+% The various \<arc> arguments are commands which typeset arcs around the
+% various parts of the items.
+%
+% We calculate the height and depth of the two boxes, and store them in
+% \<dimen> registers, because the boxes are emptied before the right-hand
+% rules are typeset.
+%
+% Actually, the two rows of the alignment are typeset in a different macro:
+% we just pass the correct information on.
+%
+%    \begin{macrocode}
+\def\sd@doloop#1#2#3#4#5#6#7#8{%
+  \@tempdima\dp#1\relax%
+  \@tempdimb\ht#2\relax%
+  \offinterlineskip%
+  \ialign{%
+    ##\cr%
+    \ifsd@round%
+      \sd@doloop@i#1#3\sd@topcirc\@tempdima{#5}{#6}%
+      \sd@doloop@i#2#4\@tempdimb\sd@botcirc{#7}{#8}%
+    \else%
+      \sd@doloop@i#1#3\sd@upper\@tempdima{#5}{#6}%
+      \sd@doloop@i#2#4\@tempdimb\sd@lower{#7}{#8}%
+    \fi%
+  }%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \begin{macro}{\sd@doloop@i}
+%
+% Here we do the actual job of typesetting the rows of a loop alignment.
+% The four arguments are:
+% \begin{quote}\synshorts
+% "\\sd@doloop@i{"<box>"}{"<arrow>"}"^^A
+%              "{"<rule-height>"}{"<rule-depth>"}" \\
+% \hbox{}\quad "{"<left-arc>"}{"<right-arc>"}"^^A
+% \end{quote}
+%
+% The arrow position is determined by the |\ifsd@backwards| flag.  The rest
+% is fairly simple.
+%
+%    \begin{macrocode}
+\def\sd@doloop@i#1#2#3#4#5#6{%
+  \ifsd@backwards#2\fi%
+  \kern-\tw@\sdrulewidth%
+  \vrule\@height#3\@depth#4\@width\tw@\sdrulewidth%
+  #5%
+  \sd@rule\hfill%
+  \sd@gap\sdtokskip%
+  \unhbox#1%
+  \sd@gap\sdtokskip%
+  \sd@rule\hfill%
+  #6%
+  \vrule\@height#3\@depth#4\@width\tw@\sdrulewidth%
+  \ifsd@backwards\else#2\fi%
+  \kern-\tw@\sdrulewidth%
+  \cr%
+}
+%    \end{macrocode}
+%
+% \end{macro}
+%
+% \subsection{The end}
+%
+% Phew!  That's all of it completed.  I hope this collection of commands
+% and environments is of some help to someone.
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \hfill Mark Wooding, \today
+%
+% \Finale
+%
+\endinput
-- 
2.11.0

