summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/generic/arobend/AroundTheBend.tex
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/doc/generic/arobend/AroundTheBend.tex')
-rw-r--r--Master/texmf-dist/doc/generic/arobend/AroundTheBend.tex7419
1 files changed, 7419 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/generic/arobend/AroundTheBend.tex b/Master/texmf-dist/doc/generic/arobend/AroundTheBend.tex
new file mode 100644
index 00000000000..ac01d718075
--- /dev/null
+++ b/Master/texmf-dist/doc/generic/arobend/AroundTheBend.tex
@@ -0,0 +1,7419 @@
+% AroundTheBend.tex concatenation of Around The Bend
+
+\begin{filecontents}{bend.ist}
+% MakeIndex style file bend.ist for use with AroundTheBend.tex
+
+% @ may be a valid character in the index, use ? instead
+actual '?'
+
+\end{filecontents}
+
+%\documentclass[draft,openany]{memoir}
+\documentclass[openany]{memoir}
+\usepackage{comment}
+\usepackage{url}
+\ifpdf
+ \usepackage[pdftex,
+ plainpages=false,
+ pdfpagelabels,
+ bookmarksnumbered
+ ]{hyperref}
+\else
+ \usepackage[%pdf,
+ plainpages=false,
+ pdfpagelabels,
+ bookmarksnumbered
+ ]{hyperref}
+\fi
+\usepackage{graphicx}
+
+\settrimmedsize{11in}{210mm}{*}% min letterpaper/A4 sizes
+\setlength{\trimtop}{0pt}
+\setlength{\trimedge}{\stockwidth}
+\addtolength{\trimedge}{-\paperwidth}
+\settypeblocksize{7.75in}{33pc}{*}
+\setulmargins{4cm}{*}{*}
+\setlrmargins{1.25in}{*}{*}
+\setmarginnotes{17pt}{51pt}{\onelineskip}
+\setheadfoot{\onelineskip}{2\onelineskip}
+\setheaderspaces{*}{2\onelineskip}{*}
+\checkandfixthelayout
+
+%\addtolength{\textwidth}{1in}
+%\addtolength{\oddsidemargin}{-0.5in}
+%\addtolength{\evensidemargin}{-0.5in}
+
+\newcommand{\ed}[1]{\emph{(Ed: #1)}}
+\newcommand*{\oposted}[1]{Originally posted on #1}
+\newcommand*{\arch}[1]{Archived as {\normalfont \ttfamily #1}}
+\newenvironment{solution}[1]{%
+ \begin{description}
+ \item[#1]\mbox{}}%
+% {\par\noindent\textbf{End solution}\end{description}}
+ {\end{description}\vspace{-0.5\onelineskip}\textbf{End solution}}
+\newcommand*{\pfile}[1]{\texttt{#1}}% print a file name
+\newfixedcaption{\freetabcaption}{table}
+\renewcommand*{\chaptername}{QA}
+\renewcommand*{\chaptername}{}
+
+% \piif{if...} print and index \if...
+\newcommand*{\piif}[1]{\cs{#1}\index{#1?\cs{#1}}}
+\makeatletter
+\newcommand*{\zeroseps}{%
+ \topsep\z@
+ \partopsep\z@
+ \parskip\z@}
+\newlength{\gparindent} \gparindent 0.5\parindent
+\newenvironment{lcode}{\zeroseps
+ \renewcommand{\verbatim@startline}%
+ {\verbatim@line{\hskip\gparindent}}%
+ \small\setlength{\baselineskip}{\onelineskip}\verbatim}%
+ {\endverbatim
+ \vspace{-\baselineskip}\noindent}
+\makeatother
+
+\nouppercaseheads
+\headstyles{bringhurst}
+%\setlength{\beforechapskip}{2\onelineskip}
+\chapterstyle{section}
+\setlength{\beforechapskip}{2\onelineskip}
+\setlength{\beforechapskip}{0pt}
+\setlength{\afterchapskip}{1\onelineskip}
+\settocdepth{subsubsection}
+\setsecnumdepth{subsubsection}
+
+\makeindex
+
+%\title{Around The Bend}
+%\author{Michael Downes \\
+%(edited by Peter Wilson)}
+%\date{}
+\newlength{\drop}
+\providecommand*{\wb}[2]{\fontsize{#1}{#2}\usefont{U}{webo}{xl}{n}}
+\newcommand*{\titleAB}{\begingroup
+\drop=4\baselineskip
+\centering
+\vspace*{\drop}
+{\Huge AROUND THE BEND}\\[\drop]
+{\hspace*{1.5em}\scalebox{8}[1]{{\wb{10}{12}4}}}\\[\drop]
+{\Large\itshape A Collection of TeX Challenges by}\\[\baselineskip]
+{\Large MICHAEL DOWNES}\\[\baselineskip]
+{\wb{10}{12}4}\\[\baselineskip]
+{\Large\itshape edited by}\\[\baselineskip]
+{\Large Peter Wilson}\par
+\vfill
+{\hspace*{1.5em}\scalebox{8}[1]{{\wb{10}{12}4}}}\\[\drop]
+{\large The Herries Press}\\
+{July 2008}\par
+\vspace*{\drop}
+\endgroup}
+%% normally \parindent = 1.5em, but 0pt in \titleAB
+
+\begin{document}
+\tightlists
+\raggedbottom
+
+\frontmatter
+
+%\maketitle
+\thispagestyle{empty}
+\titleAB
+\cleardoublepage
+\tableofcontents
+
+\chapter{Preface}
+
+ In the early 90's the late and much missed Michael Downes (1958--2003)
+ran a column in the INFO-TeX mailing list
+called \emph{Around The Bend} where he proposed macro-related problems and
+then posted
+submitted solutions. Although it was archived on CTAN in \url{info/aro-bend}
+it is not well known which is a shame as it provides
+answers to many problems that keep cropping up. (The archive is now
+at \url{info/challenges/aro-bend}). This is an attempt to
+make his work more accessible by providing the collection as a single
+document.
+
+ As much as possible what follows is what Michael wrote; I have tried to
+limit myself to marking up the original ASCII text emails but I have not
+repeated administrative elements such as email headers.
+
+ In some cases the
+original TeX code was replete with comments explaining what was going on.
+Where the comments were long with respect to the code I have set them in
+the regular body type so as to make the actual code more obvious; this has a
+side effect of slightly decreasing the amount of paper required to
+print the document. If you
+want to use the code solutions I suggest that you cut and paste them
+from the original archived versions.
+
+ I thought that there were eighteen Around the Bends as that is all that
+are archived on CTAN. However I googled the Google Groups \url{comp.text.tex}
+group
+and found three more, nos.~19, 20 and~21. I have included what I could find
+of these, but answers to no.~19 appear to be missing, which is a pity as
+I think that I could have put them to use. Perhaps some of you might be
+willing to take up the challenge on this, or on any of the others.
+
+
+
+{\raggedleft \textsc{PW}\\ July, 2008 \par}
+
+\chapter{Introduction}
+
+\ed{This is Michael's introduction to his scheme, originally posted on
+1991/10/10 as the initial portion of exercise~1.}
+
+
+%%[Exercises 1,2,3 were originally posted together on 10 Oct 91]
+\begin{verbatim}
+Date: Thu 10 Oct 91 09:51:32-EST
+From: Michael Downes <MJD@MATH.AMS.COM>
+Subject: Around the bend
+To: info-tex@shsu.edu
+\end{verbatim}
+
+Proposal for a regular feature:
+
+ AROUND THE BEND
+
+With the encouragement of George Greenwade (the INFO-TeX list owner), I
+would like to propose a regular department for INFO-TeX, called `Around
+the bend'. It will consist of macro-writing challenges on the level of
+the dangerous-bend exercises in the \emph{TeXbook}, with interested parties
+invited to collaborate and/or compete to find the best solution. My
+motivation for doing this is partly selfish: to get more feedback from
+other macro writers about some of the interesting macro-writing
+problems that I run into.
+
+I originally approached George for advice about setting up a separate
+mailing list, but he thought that INFO-TeX and comp.text.tex readers
+would be interested. Since INFO-TeX mail is also channeled to
+comp.text.tex, readers of the latter should let me know if they don't
+want the extra traffic (although I don't expect it to be that much). I
+don't currently have access to read comp.text.tex directly, although
+George has been investigating the possibility of piping it through the
+INFO-TeX mailing list. So if you object by posting to comp.text.tex, I
+may not see your objection; send me mail, instead.
+
+The sample below should give a pretty good idea of what `Around the
+bend' would be like. Solutions should be sent to me instead of to
+INFO-TeX or comp.text.tex, on the premise that people usually won't want
+to read others' solutions until they've had a chance to try their own
+hand. A summary of the results would then be posted to the INFO-TeX
+list after two or three weeks; to those who submit solutions before the
+deadline, I could forward without delay solutions submitted by other
+people, for comparison.
+
+I will try to keep the difficulty of the exercises down to something
+reasonable, let's say, on the level of a homework assignment which a
+university student must complete in two weeks, finding time in the
+normal way from the usual busy schedule of other homework, class
+attendance, sports, and social life. However, be warned that the
+challenges will be hard. I'm planning to follow a `hard and fast'
+format: one or two hard questions, followed by one or two fast
+questions, where if you don't know the answer off the top of your head,
+you can either look it up in the \emph{TeXbook} or find it by running a quick
+test.
+
+
+\mainmatter
+
+
+\chapter{Expansion}
+
+\section{Exercise (hard)}
+
+%%\input{ex001.tex}
+% ex001.tex
+
+\begin{comment}
+
+(Originally posted on 1991/10/10)
+
+[Exercises 1,2,3 were originally posted together on 10 Oct 91]
+Date: Thu 10 Oct 91 09:51:32-EST
+From: Michael Downes <MJD@MATH.AMS.COM>
+Subject: Around the bend
+To: info-tex@shsu.edu
+
+Proposal for a regular feature:
+
+ AROUND THE BEND
+
+With the encouragement of George Greenwade (the INFO-TeX list owner), I
+would like to propose a regular department for INFO-TeX, called `Around
+the bend'. It will consist of macro-writing challenges on the level of
+the dangerous-bend exercises in the TeXbook, with interested parties
+invited to collaborate and/or compete to find the best solution. My
+motivation for doing this is partly selfish: to get more feedback from
+other macro writers about some of the interesting macro-writing
+problems that I run into.
+
+I originally approached George for advice about setting up a separate
+mailing list, but he thought that INFO-TeX and comp.text.tex readers
+would be interested. Since INFO-TeX mail is also channeled to
+comp.text.tex, readers of the latter should let me know if they don't
+want the extra traffic (although I don't expect it to be that much). I
+don't currently have access to read comp.text.tex directly, although
+George has been investigating the possibility of piping it through the
+INFO-TeX mailing list. So if you object by posting to comp.text.tex, I
+may not see your objection; send me mail, instead.
+
+The sample below should give a pretty good idea of what `Around the
+bend' would be like. Solutions should be sent to me instead of to
+INFO-TeX or comp.text.tex, on the premise that people usually won't want
+to read others' solutions until they've had a chance to try their own
+hand. A summary of the results would then be posted to the INFO-TeX
+list after two or three weeks; to those who submit solutions before the
+deadline, I could forward without delay solutions submitted by other
+people, for comparison.
+
+I will try to keep the difficulty of the exercises down to something
+reasonable, let's say, on the level of a homework assignment which a
+university student must complete in two weeks, finding time in the
+normal way from the usual busy schedule of other homework, class
+attendance, sports, and social life. However, be warned that the
+challenges will be hard. I'm planning to follow a `hard and fast'
+format: one or two hard questions, followed by one or two fast
+questions, where if you don't know the answer off the top of your head,
+you can either look it up in the TeXbook or find it by running a quick
+test.
+
+All right, here are the first three.
+
+\end{comment}
+
+%**********************************************************************
+%*** Exercise 1 (hard):
+
+\ed{\oposted{1991/10/10}. \arch{exercise.001}.}\\%[0.5\baselineskip]
+
+Given arbitrary \cmd{\b}, \cmd{\c}, \cmd{\d} (macros without arguments), for example
+\begin{lcode}
+ \def\b{\c\c} \def\c{*} \def\d{\b\c}
+\end{lcode}
+figure out how to define \cmd{\a} so that its replacement text consists
+of \cmd{\b} fully expanded plus \cmd{\c} not expanded plus \cmd{\d} expanded
+exactly once.
+I.e., with the above definitions the replacement text of \cmd{\a}
+should be
+\begin{lcode}
+ **\c\b\c
+\end{lcode}
+You may not use \cmd{\the} or \cmd{\noexpand} in your solution. This is Exercise
+20.16 in the \emph{TeXbook}, except that there's an added restriction: your
+answer must also not use the \cmd{\halign}\texttt{\ldots}\cmd{\span} method given in the
+answer to 20.16. (Yes, that means you can't use \cmd{\valign} either!)
+
+Why would anyone want to do such a hard exercise? Answer: advanced
+macro writing requires a thorough knowledge of expansion control
+principles.
+
+\begin{comment}
+[Exercise 2 moved to exercise.002]
+
+[Exercise 3 moved to exercise.003]
+
+Send answers to:
+
+Michael Downes mjd@math.ams.com (Internet)
+
+A summary will be posted Friday, October 25, 1991.
+\end{comment}
+
+%%\endinput
+
+
+\section{Answers}
+
+%%\input{ans001.tex}
+% ans001.tex
+
+\ed{\oposted{1991/10/25}. \arch{answer.001}.}\\
+
+
+\begin{comment}
+[Solutions for exercises 1,2,3 were originally posted together on 25 Oct 91]
+Date: Fri 25 Oct 91 15:19:44-EST
+From: Michael Downes <MJD@MATH.AMS.COM>
+Subject: `Around the bend' #1 solutions
+To: info-tex@shsu.edu
+
+Solutions to the exercises of `Around the bend' #1.
+
+"*** Exercise 1 (hard):
+"Given arbitrary \b, \c, \d (macros without arguments), for example
+"
+" \def\b{\c\c} \def\c{*} \def\d{\b\c}
+"
+"figure out how to define \a so that its replacement text consists
+"of \b fully expanded plus \c not expanded plus \d expanded exactly once.
+"I.e., with the above definitions the replacement text of \a
+"should be
+"
+" **\c\b\c
+"
+"You may not use \the or \noexpand in your solution. This is Exercise
+"20.16 in the TeXbook, except that there's an added restriction: your
+"answer must also not use the \halign ... \span method given in the
+"answer to 20.16. (Yes, that means you can't use \valign either!)
+\end{comment}
+
+The restrictions leave us with (essentially) three expansion-control
+commands: \\
+ \cmd{\expandafter}, \cmd{\edef} and \cmd{\def}.
+
+%\begin{description}
+%\item[Solution 1 {[Peter Schmitt]}] \mbox{}
+\begin{solution}{Solution 1 (Peter Schmitt)}\index{Schmitt, Peter}
+\begin{lcode}
+ \edef\B{\b}
+ \def\defA#1{\def\defa##1##2{\def\a{#1##2##1}}}
+ \expandafter\defA\expandafter{\B}
+ \expandafter\defa\expandafter{\d}{\c}
+\end{lcode}
+\end{solution}
+
+%%>>EndSolution
+
+%\item[Solution 2 {[Donald Arseneau]}] \mbox{}
+\begin{solution}{Solution 2 (Donald Arseneau)}\index{Arseneau, Donald}
+\begin{lcode}
+\edef\e{\b}
+\expandafter \expandafter \expandafter \def\expandafter \expandafter
+\expandafter \a\expandafter \expandafter \expandafter {\expandafter
+\e\expandafter \c\d}
+\end{lcode}
+\end{solution}
+%%>>EndSolution
+
+%\item[Solution 3 {[mine]}] \mbox{}
+\begin{solution}{Solution 3 (mine)}\index{Downes, Michael}
+\begin{lcode}
+\edef\a{\b}
+\expandafter\expandafter\expandafter\def
+\expandafter\expandafter\expandafter\a
+\expandafter\expandafter\expandafter{\expandafter\a\expandafter\c\d}
+\end{lcode}
+\end{solution}
+%%>>EndSolution
+%\end{description}
+
+My solution differed from Arseneau's only in using \cmd{\a} rather than \cmd{\e}
+in the first step.
+
+\begin{comment}
+[Solution for exercise 2 moved to answer.002]
+[Solution for exercise 3 moved to answer.003]
+
+Michael Downes mjd@math.ams.com (Internet)
+
+\end{comment}
+
+%%\endinput
+
+
+\chapter{Empty argument}
+
+\section{Exercise (hard)}
+
+%%\input{ex002.tex}
+% ex002.tex
+
+\begin{comment}
+
+[Posted to info-tex on 10 Oct 91; see exercise.001]
+**********************************************************************
+*** Exercise 2 (hard):
+\end{comment}
+
+\ed{\oposted{1991/10/10}. \arch{exercise.002}.}\\
+
+Define an `ifempty' macro that takes one argument and resolves
+essentially to \piif{iftrue} if the argument is empty, and \piif{iffalse}
+otherwise. This is useful for handling arguments given by
+users to commands defined in a macro package.
+
+Plain TeX or LaTeX-style solutions are both acceptable, that
+is,
+\begin{lcode}
+ \ifempty{...}TRUE CASE\else FALSE CASE\fi
+\end{lcode}
+or
+\begin{lcode}
+ \ifempty{...}{TRUE CASE}{FALSE CASE}
+\end{lcode}
+
+(In the former case you will need to do something to avoid problems
+in the situation
+\begin{lcode}
+ \iffalse ... \ifempty{...} ... \fi ... \fi
+\end{lcode}
+there
+are different possibilities here, so I will refrain from
+indicating any particular one.)
+
+Use the following test suite to verify the robustness of your
+solution:
+
+\begin{lcode}
+\long\def\test#1{\begingroup \toks0{[#1]}%
+ \newlinechar`\/\message{/\the\toks0:
+% LaTeX-style solution; modify the following line according
+% to the syntax of your solution.
+ \ifempty{#1}{EMPTY}{NOT empty}%
+}\endgroup}
+
+ \test{} \test{ }
+ \test{aabc} \test{-}
+ \test{$} \test{\empty}
+ \test{\endinput} \test{\iftrue a\else b\fi}
+ \test{\else} \test{#}
+ \test{\par} \halign{#\cr\test{&}\cr}
+ \test{\relax} \test{\relax\relax\relax}
+ \expandafter\iffalse\test{x}\fi \test{{}}
+\end{lcode}
+%$
+
+The two tests on the first line should produce a message `EMPTY' and
+the remaining ones, `NOT empty'. The reason for saying that the second
+test should return `EMPTY' is that (1) this is the ideal behavior for
+the applications I've encountered so far; (2) at least one other person
+working independently arrived before me at a solution essentially
+identical to mine, including this behavior. The details and credit to
+the other guy will be given at solution time.
+
+%%\endinput
+
+
+\section{Answers}
+
+%%\input{ans002.tex}
+% ans002.tex
+
+\begin{comment}
+
+[Posted to info-tex on 25 Oct 91; see answer.001]
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+"*** Exercise 2 (hard):
+"Define an "ifempty" macro that takes one argument and resolves
+"essentially to \iftrue if the argument is empty, and \iffalse
+"otherwise. This is useful for handling arguments given by
+"users to commands defined in a macro package such as LaTeX.
+"
+"Plain TeX or LaTeX-style solutions are both acceptable, that
+"is,
+"
+" \ifempty{...}TRUE CASE\else FALSE CASE\fi
+"
+"or
+"
+" \ifempty{...}{TRUE CASE}{FALSE CASE}
+\end{comment}
+
+\ed{\oposted{1991/10/25}. \arch{answer.002}.}\\
+
+The LaTeX-style solution that I had prepared was, I thought, pretty
+good, but Donald Arseneau\index{Arseneau, Donald}
+observed that it fails the test
+\begin{lcode}
+\test{{\iftrue a\else b\fi}}
+\end{lcode}
+which was not in my list of tests.
+
+%\begin{description}
+%\item[Solution 1 {[mine]}] \mbox{}
+\begin{solution}{Solution 1 (mine)}\index{Downes, Michael}
+\begin{lcode}
+\catcode`\@=11
+% \@car is actually already defined in latex.tex, but for
+% maximum robustness it needs to have the \long prefix:
+\long\def\@car#1#2\@nil{#1}
+\long\def\@first#1#2{#1}
+\long\def\@second#1#2{#2}
+\long\def\ifempty#1{\expandafter\ifx\@car#1@\@nil @\@empty
+ \expandafter\@first\else\expandafter\@second\fi}
+\catcode`\@=12
+
+\long\def\test#1{\begingroup \toks0{[#1]}%
+ \newlinechar`\/\message{/\the\toks0:
+ \ifempty{#1}{EMPTY}{NOT empty}%
+}\endgroup}
+\end{lcode}
+\end{solution}
+%%>>EndSolution
+
+The advantage of using the auxiliary macros \cmd{\@first} and \cmd{\@second},
+together with the \cmd{\expandafter}'s, is that it allows the true and/or
+false cases to end with arbitrary things, even macros that require
+arguments that have not yet been read (any number of arguments, even
+delimited arguments).
+
+From here it is easy to implement an \piif{ifnotempty} test that has a
+null false case. This is often useful in dealing with user-supplied
+arguments: `If \#1 is empty, do nothing; otherwise, do the following
+with \#1: ...'
+\begin{lcode}
+\long\def\ifnotempty#1{\ifempty{#1}{}}
+\end{lcode}
+
+
+%\item[Solution 2 {[Donald Arseneau]}]
+\begin{solution}{Solution 2 (Donald Arseneau)}\index{Arseneau, Donald}
+Don Arseneau came up with a plain TeX style solution, using an
+ingenious device with \cmd{\then} to pass the test case
+\begin{lcode}
+\expandafter\iffalse\test{x}\fi
+\end{lcode}
+ The comments in the solution are his.
+
+\begin{lcode}
+% \ifblank{...}\then Test if a parameter is blank (null or spaces).
+% Use the inaccessable "letter" @ to separate parameters. The two cases are:
+% _text_is_not_blank_ _text_is_blank_
+% #1<- whatever #1<-@
+% #2<- whatever (possibly null) #2<-
+% #3<- @ #3<-.
+% #4<- .. #4<-.
+% \if @.. {false} \if .. {true}
+% In the {false} case, the extra period is skipped so it doesn't hurt.
+
+\catcode`\@=11 % as in plain.tex
+\let\then\iftrue
+\long\def\ifblank#1\then{\Ifbl@nk#1@@..\then}%
+\long\def\Ifbl@nk#1#2@#3#4\then{\if#3#4}
+\catcode`\@=12
+
+\long\def\test#1{\begingroup \toks0{[#1]}%
+ \newlinechar`\/\message{/\the\toks0:
+ \ifblank{#1}\then EMPTY\else NOT empty\fi%
+}\endgroup}
+\end{lcode}
+\end{solution}
+%%>>EndSolution
+
+The good thing about this solution is that it doesn't subject any part
+of the user-supplied argument to the \piif{ifx} test. Using @ with category
+code of 11 as a delimiter for the user-supplied text is extremely safe
+because even in internal code @ doesn't appear by itself, only as part
+of control sequence names. In a partial solution,
+Peter Schmitt\index{Schmitt, Peter} pushed
+the idea a little further by using space with category code 3 as the
+delimiter.
+
+There is another way of handling the problematic \piif{iffalse} test, in a
+plain-TeX style solution, by using a suggestion of Donald Knuth that
+appeared in TeXhax a while ago, in reply to a query of Stephan von
+Bechtolsheim (texhax89, \#38 (post from svb, 17 Apr 89)).
+
+%\item[Solution 3 {[Arseneau/Knuth]}] \mbox{}
+\begin{solution}{Solution 3 (Arseneau/Knuth)}\index{Arseneau, Donald}\index{Knuth, Donald}
+\begin{lcode}
+% Usage: \if\blank{#1}...\else...\fi
+
+\catcode`\@=11 % as in plain.tex
+\long\def\blank#1{\bl@nk#1@@..\bl@nk}%
+\long\def\bl@nk#1#2@#3#4\bl@nk{#3#4}
+\catcode`\@=12
+
+\long\def\test#1{\begingroup \toks0{[#1]}%
+ \newlinechar`\/\message{/\the\toks0:
+ \if\blank{#1}EMPTY\else NOT empty\fi%
+}\endgroup}
+\end{lcode}
+\end{solution}
+
+%>>EndSolution
+
+At the end of Exercise 2 I wrote:
+\begin{quote}
+The two tests on the first line should produce a message `EMPTY' and
+the remaining ones, `NOT empty'. The reason for saying that the second
+test should return `EMPTY' is that (1) this is the ideal behavior for
+the applications I've encountered so far; (2) at least one other person
+working independently arrived before me at a solution essentially
+identical to mine, including this behavior. The details and credit to
+the other guy will be given at solution time.
+\end{quote}
+
+The name of the `other guy' is Michael Wester\index{Wester, Michael};
+a listing of his macros
+was published in the preprints for the July 1991 TUG meeting in Dedham,
+Massachusetts (`Form Letter in LaTeX with 3-across Mailing Labels
+Capability', joint paper with Jackie Damrau). In rereading the preprint
+recently, it seems to me the presentation is more different from
+Exercise 2 and its solutions than I had previously imagined, but the
+essential ideas are there. See \cmd{\wcar}, \cmd{\wcdr} and related macros.
+
+By the way, if anyone came up with a fully expandable test (suitable
+for use inside a \cmd{\message}) for which \verb?\test{ }? came up
+false instead of
+true, I would be interested to hear about it. I didn't mean to
+eliminate that possibility in my original statement of the problem.
+
+%%\endinput
+
+
+\chapter{Discretionary}
+
+\section{Exercise (fast)}
+
+%%\input{ex003.tex}
+% ex003.tex
+
+\ed{\oposted{1991/10/10}. \arch{exercise.003}.}\\
+
+\begin{comment}
+
+[Posted to info-tex on 10 Oct 91; see exercise.001]
+**********************************************************************
+*** Exercise 3 (fast):
+\end{comment}
+
+What's the most important difference between \cs{-} and
+\begin{lcode}
+\discretionary{-}{}{} ?
+\end{lcode}
+
+%%**********************************************************************
+%%\endinput
+
+
+\section{Answers}
+
+%%\input{ans003.tex}
+% ans003.tex
+
+\ed{\oposted{1991/10/25}. \arch{answer.003}.}\\
+
+\begin{comment}
+
+[Posted to info-tex on 25 Oct 91; see answer.001]
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+"*** Exercise 3 (fast):
+"What's the most important difference between \- and
+"\discretionary{-}{}{}?
+\end{comment}
+
+The most important difference between \cs{-} and \cmd{\discretionary}\verb?{-}{}{}?
+is that the latter always puts in the character from font position 45
+("2D, '55) of the current font when a word must be broken at the end of
+a line; \cs{-} puts in the character from font position \cmd{\hyphenchar} of the
+current font, which is NOT NECESSARILY position 45. It would be rather
+unusual for \cmd{\hyphenchar} to be something other than 45; in certain
+special applications, however (possibly in some foreign languages as
+well?) a variant value of \cmd{\hyphenchar} can be useful. I have an idea for
+using this in a future exercise\ldots
+
+Credit to Donald Arseneau\index{Arseneau, Donald} for a correct answer.
+Thanks to Peter Schmitt\index{Schmitt, Peter}
+for providing the perfect opening for another point I wanted to make:
+\begin{quotation}
+ The \emph{TeXbook} states explicitly: \\
+ \cs{-} is equivalent to \verb?\discretionary{-}{}{}? \\
+ and both are internal.
+
+ I do not see where to the question aims:
+\begin{itemize}
+\item control symbol : control sequence
+\item no paramaters : three parameters
+\item two characters : 21 characters to type
+\item ???
+\end{itemize}
+\end{quotation}
+
+Schmitt is quoting from the last page of Chapter 25; the point is,
+that in newer versions of the \emph{TeXbook} that sentence has been revised.
+I'm not sure what the latest printing says, since I don't have a copy,
+but I think it simply refers the reader to Appendix H, where the
+significance of \cmd{\hyphenchar} is explained. \cmd{\hyphenchar} is a feature that
+was added late in the development of TeX82 (\pfile{TeX82.bug} reveals that is
+was not added until May 25, 1983). Even if the source files for the
+\emph{TeXbook} were immediately updated by Knuth at that time, the changes did
+not appear in the published version being sold to the general public
+until some time later when the first revised edition was published,
+which was no earlier than October 1984, the date of the \emph{TeXbook} copy
+that I have on hand, and probably later.
+
+The statement of purpose in `Around the bend' \#1 said something
+about finding the `best solution', but conspicuously failed to define
+what `best' should mean in this context. It was my intention to address
+this question in future exercises; for now, let me just say that I
+don't intend to arbitrarily rule out of consideration answers such as
+Schmitt's `two characters : 21 characters to type', since depending on
+how you look at it, it could be argued that this is much more
+significant than dumb old \cmd{\hyphenchar} minutiae. I promised that these
+exercises would be challenging; that means, among other things, that
+they won't always be well-defined, well-bounded, or well-behaved, and
+part of the job of finding the `best solution' will be to decide what
+parts of the problem need to be specified further, and to examine the
+ramifications of alternatives.
+
+%%\endinput
+
+
+\chapter{What is `best'?}
+
+\section{Exercise (essay)}
+
+%%\input{ex004}
+% ex004.tex
+
+\begin{comment}
+[Exercises 4,5,6,7 were originally posted together on 4 Nov 91]
+Date: Mon 4 Nov 91 16:42:44-EST
+From: Michael Downes <MJD@MATH.AMS.COM>
+Subject: Around the bend #2
+To: info-tex@shsu.edu
+\end{comment}
+
+\ed{\oposted{1991/11/04}. \arch{exercise.004}.}
+
+The statement of purpose in `Around the bend' \#1 said something about
+finding the `best solution', but failed to define what `best' should
+mean when comparing pieces of TeX code. I'll start by throwing out
+a few ideas.
+
+\begin{description}
+\item[Simplicity] A good solution gets hold of the essential idea of the
+problem and attacks it directly, rather than beating around the bush
+and resorting to separate clauses to handle troublesome subcases.
+
+\item[Economy] If two solutions compare equal in other respects, then the
+better solution is the one that uses less of TeX's resources (main
+memory, hash table, string pool, and so forth). Therefore I
+(immodestly) say that my solution to Exercise 1 was ever so slightly
+better than the other two given, because it avoided introducing any
+auxiliary macros that were not included in the original statement of
+the problem.
+
+\item[Robustness] If a solution only works under limited friendly
+circumstances, and otherwise blows up with an error message, that's not
+good. My solution to Exercise 2 was flawed in this respect, since D.A.
+found a test case that caused it to go wrong.
+\end{description}
+
+%%***********************************************************************
+*** Exercise 4 (essay):
+
+What should `best' mean when comparing solutions to an `Around the
+bend' exercise? What qualities of a good solution are most important?
+Why? How can they be objectively measured? (Or can they?) On the
+negative side, what qualities indicate an inferior solution?
+
+%%***********************************************************************
+
+\begin{comment}
+
+[Exercise 5 moved to exercise.005]
+[Exercise 6 moved to exercise.006]
+[Exercise 7 moved to exercise.007]
+
+Send answers to:
+
+Michael Downes mjd@math.ams.com (Internet)
+
+A summary will be posted Tuesday, December 4, 1991. However, because of
+the difficulty of E7, I will probably procrastinate on posting the
+solutions for that exercise until the first or second week of December.
+\end{comment}
+
+Table of special characters, to verify accurate transmission:
+
+\begin{lcode}
+ASCII 33: ! exclamation point ASCII 60: < left elbow
+ASCII 34: " double quote ASCII 61: = equals sign
+ASCII 35: # number/pound sign ASCII 62: > right elbow
+ASCII 36: $ dollar sign ASCII 63: ? question mark
+ASCII 37: % percent sign ASCII 64: @ at sign
+ASCII 38: & ampersand ASCII 91: [ left square bracket
+ASCII 39: ' right quote/apostrophe ASCII 92: \ backslash
+ASCII 40: ( left parenthesis ASCII 93: ] right square bracket
+ASCII 41: ) right parenthesis ASCII 94: ^ circumflex/hat/caret
+ASCII 42: * star/asterisk ASCII 95: _ underscore
+ASCII 45: - hyphen ASCII 96: ` left quote
+ASCII 47: / slash ASCII 123: { left curly brace
+ASCII 58: : colon ASCII 124: | vert bar
+ASCII 59: ; semicolon ASCII 125: } right curly brace
+ ASCII 126: ~ tilde
+\end{lcode}
+%$
+
+%%\endinput
+
+
+\section{Answers}
+
+%%\input{ans004}
+% ans004.tex
+
+\ed{\oposted{1991/12/10}. \arch{answer.004}.}
+
+\begin{comment}
+[Solutions for exercises 4,5 were originally posted together on 5 Dec 91]
+Date: Thu 5 Dec 91 10:26:58-EST
+From: Michael Downes <MJD@MATH.AMS.COM>
+Subject: `Around the bend' #2 solutions (4,5)
+To: info-tex@shsu.edu
+
+Answers to exercises 4 and 5 of `Around the bend' #2. Discussion of E6
+will follow in a separate post because it is rather lengthy. Discussion
+of E7 will follow in another couple of weeks (I'm going to be on
+vacation next week.)
+
+"***********************************************************************
+"*** Exercise 4 (essay):
+"
+"What should `best' mean when comparing solutions to an `Around the
+"bend' exercise? What qualities of a good solution are most important?
+"Why? How can they be objectively measured? (Or can they?) On the
+"negative side, what qualities indicate an inferior solution?
+\end{comment}
+
+Peter Schmitt\index{Schmitt, Peter} writes:
+\begin{quotation}
+ What is to be rated as `best' clearly depends on the function used to
+ measure quality. And therefore the question makes sense only with
+ respect to some particular rating function. Seemingly nothing is gained
+ by this statement: Instead of discussing what qualities are required
+ for a good solution one has to discuss how the rating system should be
+ defined. But nevertheless this shifted point of view has an important
+ an important advantage. It makes clear that there is no unique answer:
+ Quality is not an absolute notion but a notion relative to some
+ (agreed) measure. This measure is not independent of the context ---
+ under different conditions different rating functions may be used.
+
+ One further important point must not be forgotten: If matters of
+ personal taste are to be excluded than the measuring function has to be
+ precisely defined --- demanding simplicity, without giving this notion
+ a precise (formal) meaning, is not sufficient.
+
+ Therefore I would like to split the original question into two seperate
+ questions:
+
+ (a) What (formal and informal) rating functions are likely to be
+ useful, and under what circumstances?
+
+ (b) With respect to some formal rating function, is there always a best
+ solution?
+
+ Some answers to the first questions are the following (no completeness
+ claimed or even intended):
+
+ (1) the first solution:
+
+ If some special effect is needed for a single application then the
+ best solution is the first solution (the solution that can be
+ realized with the least effort). This is, however, a purely
+ individual criterion that cannot be formalized.
+
+ (2) the most economic (in some sense) solution:
+
+ Economic considerations are important if a code is used frequently,
+ Depending on the nature of the applications running time, memory
+ usage, and others, may be relevant. But the time spent for finding
+ a good solution still cannot be neglected in a real world
+ situation. Of course, for theoretical investigations the time spent
+ for research does not matter.
+
+ (3) the more robust solution:
+
+ If some set of macros is used by a large number of people who not
+ always know how to use them correctly (or even do not care to know)
+ then it is certainly an advantage if they are robust, i.e. work in
+ as many cases (even strange ones) as possible. But again, one has
+ to decide what price (in terms of resources) is acceptable for this
+ robustness. (In many cases the item (4) below will be more
+ important.)
+
+ (4) ease-of-use:
+
+ If a set of macros is used frequently (by one or more persons) then
+ ease-of-use is certainly a mark of quality: easy to remember
+ syntax, short commands, natural and good readable embedding into
+ the surrounding text, and similar criteria, decide about this.
+
+ (5) simplicity:
+
+ Simple solutions certainly have a strong appeal --- but what is a
+ simple solution? Again this is hard to formalize, since simplicity
+ basically is an aesthetic value, closely related to the concepts of
+ elegance and beauty. (This is similar to the situation in
+ mathematics.) But be careful: Simple is not equivalent to short!
+
+ (6) the shortest solution:
+
+ This may seem to be an easy rating function, but is it? Should
+ length be measured by the number of characters (probably not!), or
+ by the number of tokens, or by the number of control sequences? Or
+ by something else?
+
+ Most of the measures mentioned are difficult to formalize, or cannot be
+ formalized at all. Only the resources used (in (2)) and the length of a
+ code (in (6)) can be precisely defined. Therefore, with respect to one
+ of these cases two solutions of the same problem can be compared.
+ Furthermore, in many cases it will be possible to proof that an optimal
+ solution exists. (For instance, since the length of a code (in any
+ interpretation) is a positive integer, there must exist one or more
+ solutions with minimal length, provided there is at least one
+ solution.) But unfortunately this does not imply that one is able to
+ construct an optimal solution, or to decide whether a given piece of
+ code is an optimal solution (or at least near to one). And in some
+ cases it may happen that no optimal solution exists, e.g. if to every
+ solution there is better --- but longer! --- one.
+
+ What is the conclusion of all this? That there may be a best solution
+ relative to some side conditions. But that there is no globally best
+ solution. This statement is, of course, not very satisfying. One
+ would rather prefer to have at least some notion (even a tentative one)
+ of a best solution than none at all. I propose therefore the following
+ informal definition (often subject to personal taste): If some code is
+ optimal or near-optimal in more than one category then it is probably
+ as near to a globally optimal solution as this is possible.
+\end{quotation}
+
+
+My comments:
+
+I propose the following list, based on (1) [my interpretation of]
+Knuth's ideas about good macro writing as demonstrated in the \emph{TeXbook}
+and plain.tex, (2) various articles in TUGboat, (3) Schmitt's comments,
+(4) discussions I've had in the past with other macro writers, and so
+forth.
+
+The characteristics of a good solution to an `Around the bend' exercise
+are (in order of decreasing importance):
+
+\begin{enumerate}
+\item Robustness
+\item Brevity (= minimal usage of TeX's main memory)3
+\item Simplicity
+\item Ease of use
+\item Suitable commentary
+\item Speed
+\item Minimal hash table load
+\item Minimal save stack load
+\item Minimal load in other categories of TeX's memory
+\item Comprehensive test suite (when applicable)
+\end{enumerate}
+Schmitt's\index{Schmitt, Peter} point about 'first solution' is well taken
+but does not apply
+to `Around the bend' exercises, because of the stated goal of finding a
+'best' solution, with the presumption that normally more than one
+solution will be found.
+
+Measurement of these qualities is not too difficult, I think,
+except for 3 and 5. Here's how I see the measurements:
+
+\begin{description}
+\item[1. Robustness] A solution is robust if no one who reads it offers a
+counterexample that causes it to fail. If two solutions both fail, the
+one with more counterexamples is less robust; if two solutions have
+different counterexamples, the solution whose counterexample is more
+likely to occur in normal use is the less robust solution.
+
+\item[2. Brevity] Of two different solutions, the one that is
+briefer/shorter/more compact is the one that uses less of TeX's main
+memory as measured by \cmd{\tracingstats}.
+
+\item[3. Simplicity] Of two different solutions, the shorter one (in the
+sense of the previous item) is usually the simpler one, but not always.
+A solution that condenses all the necessary operations into a dense,
+incomprehensible Gordian knot is less simple than a longer solution
+that lays out the operations in a series of easily comprehended steps.
+A solution that relies on arcane dirty tricks is less simple than a
+solution that uses better-known techniques in a straightforward
+approach.
+
+\item[4. Ease of use] I believe this will not be extremely hard to measure in
+the context of the particular application; it can't sensibly be
+discussed out of context.
+
+\item[5. Suitable commentary] The commentary surrounding a solution should
+explicitly mention any necessary assumptions. If the code is complex,
+the commentary should give an outline or overview of the intended
+algorithm. It should explain the operation of any macro if its
+operation is not evident from the code. If an unusual construction is
+used where a different construction would normally be expected, the
+commentary should give the reason.
+
+\item[6. Speed] Of two solutions, the speedier one is the one that runs
+faster on common computer systems. If one solution runs faster and
+slower than another, depending on the system \ldots well, let's not cross
+that bridge unless it turns out to be real.
+
+\item[7,8,9. Minimal hash table load, save stack load, etc.] These can be
+measured by \\
+\cmd{\tracingstats}.
+
+\item[10. Comprehensive test suite] If two solutions are equal in other
+respects, the one whose accompanying test suite covers more distinct
+cases than the other's is better by that much.
+\end{description}
+
+It may be argued that I have not sufficiently answered the question of
+subjectivity. For example, who's to decide what's an 'arcane dirty
+trick' and what's not? What does 'suitable' mean in number 5? The
+answer is that I will say that something is an 'arcane dirty trick' if
+I think so, and anyone else can do the same. In most cases I believe
+that there will be general agreement on such a question; if not, and an
+ensuing discussion fails to reach a clear settlement, then each of the
+solutions in question will be decreed 'subjectively just as good as the
+others'.
+
+Other qualities of a good solution can be expressed in terms of the
+ones listed above. For example, self-sufficiency may be considered an
+aspect of robustness---if a solution is not entirely self-sufficient,
+it can easily be shown to be not robust by giving a counterexample that
+exploits the assumption that makes the solution non-self-sufficient.
+Elegance? If a solution is simple and easy to use, then I say it is
+elegant. A solution doesn't necessarily have to be robust in order to
+be elegant, nor even short (although of two solutions that are
+otherwise equal, the shorter one is undoubtedly more elegant).
+
+\begin{comment}
+
+[Solution for exercise 5 moved to answer.005]
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Table of special characters (ASCII):
+
+33: ! exclamation point; 59: ; semicolon;
+34: " double quote; 60: < left elbow;
+35: # number/pound sign; 61: = equals sign;
+36: $ dollar sign; 62: > right elbow;
+37: % percent sign; 63: ? question mark;
+38: & ampersand; 64: @ at sign;
+39: ' right quote/apostrophe; 91: [ left square bracket;
+40: ( left parenthesis; 92: \ backslash;
+41: ) right parenthesis; 93: ] right square bracket;
+42: * star/asterisk; 94: ^ circumflex/hat/caret;
+43: + plus sign; 95: _ underscore;
+44: , comma; 96: ` left quote;
+45: - hyphen; 123: { left curly brace;
+46: . period/dot/point; 124: | vert bar;
+47: / slash; 125: } right curly brace;
+58: : colon; 126: ~ tilde
+%$
+Michael Downes mjd@math.ams.com (Internet)
+
+\end{comment}
+
+%%\endinput
+
+
+\chapter{\cs{string} tokens}
+
+\section{Exercise (fast)}
+
+%%\input{ex005}
+% ex005.tex
+
+\ed{\oposted{1991/11/04}. \arch{exercise.005}.}
+
+\begin{comment}
+
+[Posted to info-tex on 4 Nov 91; see exercise.004]
+***********************************************************************
+*** Exercise 5 (fast):
+\end{comment}
+
+Assuming a normal value for \cmd{\escapechar}
+\begin{lcode}
+ \string\a
+\end{lcode}
+produces two character tokens. What is the category code of the second?
+Write an experiment (as short as possible) to demonstrate the
+correctness of your answer.
+
+%%%**********************************************************************
+
+%%\endinput
+
+
+\section{Answers}
+
+%%\input{ans005}
+% ans005.tex
+
+\ed{\oposted{1991/12/05}. \arch{answer.005}.}
+
+\begin{comment}
+
+[Posted to info-tex on 5 Dec 91; see answer.004]
+"***********************************************************************
+"*** Exercise 5 (fast):
+"
+"Assuming a normal value for \escapechar,
+"
+" \string\a
+"
+"produces two character tokens. What is the category code of the second?
+"Write an experiment (as short as possible) to demonstrate the
+"correctness of your answer.
+\end{comment}
+
+The category of the 'a' token is 12. All tokens produced by \cmd{\string}
+have category 12, except for space tokens, which have category 10.
+
+\begin{solution}{Solution 1 (mine)}
+\begin{lcode}
+\def\answercheck#1#2{\message{#2: \ifcat0#2\else NOT \fi Category 12}}
+\expandafter\answercheck\string\a
+\answercheck bb
+\end{lcode}
+This produces on screen the following message:
+\begin{lcode}
+a: Category 12 b: NOT Category 12
+\end{lcode}
+\end{solution}
+%%>>EndSolution
+
+%%>>Solution 2 [Peter Schmitt]:
+\begin{solution}{Solution 2 (Peter Schmitt)}\index{Schmitt, Peter}
+\begin{lcode}
+\def\test#1#2#3{%
+ \message{\ifcat#2#3 #2 and #3 have the same category code
+ \else #2 and #3 have not the same category code
+ \fi}}
+
+\def\Test#1#2#3{%
+ \ifcat#2#3 \message{#2 and #3 have the same category code}
+ \else \message{#2 and #3 have not the same category code}
+ \fi}
+
+\catcode`\A12
+\test 1aA
+\Test 1aA
+\expandafter\test\string\a A
+\expandafter\Test\string\a A
+\end{lcode}
+
+Comment: \\
+I have given two essentially equivalent Tests --- \cmd{\test} and \cmd{\Test}.
+
+(i) \cmd{\test} is slightly more simple because it contains only one \cmd{\message}
+command, but I think that \cmd{\Test} is more adequate because it avoids to
+perform the test inside the \cmd{\message} --- there might be some side
+effect one is not aware off.
+
+(ii) Both tests are not as short as possible --- the \piif{true} and \piif{false}
+cases could be much shorter, e.g. a T (for true) and a F (for false)
+would suffice --- the result could be checked in the dvi-file. (I
+regard this difference as inessential.)
+
+Furthermore, setting the catcode of the model character to 12 could
+easily be omitted (use some character that is known to be an `other
+character'), but I think it should be included: It makes the test
+independent of any assumption on the format running. This makes the
+solution more closed and selfsufficient, and therefore also simpler and
+more elegant (if I may say so).
+\end{solution}
+%%>>EndSolution
+%%\endinput
+
+
+\chapter{Counting arguments}
+
+\section{Exercise (hard)}
+
+%%\input{ex006}
+\begin{comment}
+[Posted to info-tex on 4 Nov 91; see exercise.004]
+**********************************************************************
+*** Exercise 6 (hard):
+\end{comment}
+
+\ed{\oposted{1991/11/04}. \arch{exercise.006}.}
+
+Define a macro \cmd{\args} that can be used to fill in the proper number
+in the following sentence no matter how \cmd{\foo} is defined (except
+you may assume it is not \cmd{\outer}).
+
+ The macro \verb?\tt\string\foo? has \verb?\args\foo? arguments.
+
+Is it possible to solve this if \cmd{\foo} is \cmd{\outer} also? Is it possible
+to make \cmd{\args} fully expandable, so that it could be used in a
+message:
+\begin{lcode}
+ \message{The macro \noexpand\foo has \args\foo\space arguments.}
+\end{lcode}
+
+%%**********************************************************************
+%%\endinput
+
+\section{Answers}
+
+%%\input{ans006}
+% ans006.tex
+\begin{comment}
+Date: Mon 23 Dec 91 11:46:33-EST
+From: Michael Downes <MJD@MATH.AMS.COM>
+Subject: Answers to 'Around the bend' #2 Exercise 6
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+
+"*** Exercise 6 (hard):
+"
+"Define a macro \args that can be used to fill in the proper number
+"in the following sentence no matter how \foo is defined (except
+"you may assume it is not \outer).
+"
+" The macro {\tt\string\foo} has {\args\foo} arguments.
+"
+"Is it possible to solve this if \foo is \outer also? Is it possible
+"to make \args fully expandable, so that it could be used in a
+"message:
+"
+" \message{The macro \noexpand\foo has \args\foo\space arguments.}
+\end{comment}
+
+\ed{\oposted{1991/12/23}. \arch{answer.006}.}
+
+This was a tough one. All who sent in answers to this exercise
+(counting myself) used the approach of applying \cmd{\meaning} to \cmd{\foo} and
+analyzing the resulting string. There are some drawbacks to this.
+
+(1) In a \cmd{\meaning} string, all characters (other than spaces) have
+catcode 12. This means that all occurrences in a \cmd{\meaning} string of
+the character \# are indistinguishable, regardless of their true
+significance in the parameter text or replacement text of the macro
+in question. Consequently, an occurrence of a \# character, not
+category 6, followed by a number, in the parameter text of \cmd{\foo} can
+potentially make \cmd{\args} report an incorrect number of arguments. For
+example, in the following definitions \cmd{\foo} has no arguments, only
+delimiter text, in all three cases, but the \cmd{\meaning} string would
+appear to show that \cmd{\foo} has one argument:
+\begin{lcode}
+ \def\foo\#1{}
+ \expandafter\def\expandafter\foo\string #1{}
+ \catcode`\#=12 \def\foo#1{}
+\end{lcode}
+
+(2) The following two examples produce identical \cmd{\meaning} strings:
+\begin{lcode}
+ \def\foo&1{} % no arguments
+ \catcode`\&=6 \def\foo&1{} % one argument
+\end{lcode}
+
+(The string is \verb?"macro:&1->"?.) I.e., characters other than \# can
+be used to create parameter markers in a macro definition, and
+such a parameter marker cannot be distinguished in a \cmd{\meaning}
+string from a normal use of the character in question.
+
+(3) There is no completely general way to isolate the parameter text
+of an arbitrary macro from the replacement text. The best you can do
+is remove the tail of the \cmd{\meaning} string---everything after the last
+occurrence of \verb?->? in the string---and say 'This is not part of the
+parameter text'. Likewise, anything preceding the first occurrence of
+\verb?->? is certainly part of the parameter text. If there are two or more
+occurrences of \verb?->? in the string, however, you cannot say for sure
+whether anything between the first and last occurrences is parameter
+text or replacement text. This raises a slight additional possibility
+that pseudo 'parameter markers' in the replacement text could cause
+\cmd{\args} to give an incorrrect result. For example:
+\begin{lcode}
+ \edef\foo #1{\string#2->}
+\end{lcode}
+defining \cmd{\foo} with one argument, produces a \cmd{\meaning} string of
+\begin{lcode}
+ macro:#1->#2->
+\end{lcode}
+which is exactly the same as the \cmd{\meaning} string for
+\begin{lcode}
+ \def\foo#1->#2{}
+\end{lcode}
+where \cmd{\foo} has two arguments.
+
+
+Speaking practically, however, rather than theoretically, using
+\cmd{\meaning} to analyze the number of arguments of an arbitrary macro
+works fine. Donald Arseneau's solution, below, is admirably
+brief and demonstrates an easy way of handling an outer argument
+that I had never seen before.
+
+\begin{solution}{Solution 1 (Donald Arseneau)}\index{Arseneau, Donald}
+
+Here is my solution for counting arguments. It is totally expandable,
+and relies on the fact that the parameter numbers must be in
+increasing order, that they are only single digits, and that there is
+no parameter zero. Also important is that \cmd{\meaning} of a macro defined
+by \verb?\def\x#{...}? reports a syntax of \verb?{? rather than \#.
+\begin{lcode}
+{\catcode`\*=6 \catcode`\#=12 % use * for macro parameters while # is "other"
+%
+\gdef\args{\expandafter\Args\noexpand}% get rid of \outerness
+%
+\long\gdef\Args*1{\expandafter\countargs \meaning*1:->{}\end}%
+% ... \meaning will display the parameter syntax (as "other" characters).
+%
+\gdef\countargs*1:*2->*3\end{\twoargs#0*2#0}% get just the parameter syntax
+% ... in format #0junk#1junk...#njunk#0. \twoargs processes the list to
+% ... give "n", the last number before #0.
+\end{lcode}
+
+ Here's what tests the parameter numbers, two at a time. (Thus, the two
+ \verb?#0?'s in \cmd{\countargs}, so there are always at least two
+\verb?#n?'s detected.)
+ When the second number of a comparison isn't zero, \cmd{\twoargs} re-executes
+ itself to test the next pair; when the second \verb?n? is 0, the first
+\verb?n? is the
+ highest parameter number, so it is output.
+\begin{lcode}
+\gdef\twoargs*1#*2*3#*4{\ifnum0=*4 *2\else % note the space to end the number
+ \expandafter\twoargs\expandafter#\expandafter*4\fi}
+}
+\end{lcode}
+
+Here is my test suite. The character ``:'' works in a funny way: it
+confuses how \cmd{\countargs} reads its parameter list, and another colon
+gets into the supposed syntax. But it works because there are no
+parameters. The primitive \cmd{\halign} is reported to have no parameters
+because it is not a macro. This could be confusing to someone. The
+same confusion could arise with \cmd{\args} itself because it doesn't read
+the parameter right away.
+\begin{lcode}
+\def\test#1#{nothing}
+\def\Test[#1]#2:{\##1,#2##}
+\def\#{haha}
+
+\show\test \show\Test
+\end{lcode}
+
+(I condensed this test suite---MJD)
+\begin{lcode}
+\long\def\msg#1{\message{The object \string#1 has \args#1 arguments.}}
+
+\msg\mathpalette \msg\mathhexbox \msg\par \msg\halign \msg\args
+\msg\relax \msg # \msg\# \msg\test \msg\Test \msg : \msg\: \msg\csname
+\msg t \msg ~ \msg $ \msg ^
+\end{lcode}
+
+(Outer macros---MJD)
+\begin{lcode}
+\message{The object \string\bye\space has \args\bye\space arguments.}
+\message{The object \string\newhelp\space has \args\newhelp\space
+ arguments.}
+
+\bye % -- Donald Arseneau
+\end{lcode}
+\end{solution}
+%%>>EndSolution
+
+Although the problem statement only mentioned `macros' Arseneau
+earned some thoroughness points by including primitives \cmd{\halign},
+\cmd{\relax}, and \cmd{\csname}, as well as characters \verb?# : t $ ^?
+in his tests.
+This is of some interest because of the difference in \cmd{\meaning}
+strings between macros and non-macros.
+
+In my solution for this exercise, I amused myself by trying to pack
+everything into as few control sequences as possible. Although I got
+it down to two, that's really only one less than Arseneau's four,
+because one control sequence in his solution is expended to
+handle outer macros, something my solution didn't attempt to do.
+
+%>>Solution 2 (mine)
+\begin{solution}{Solution 2 (mine)}
+\begin{lcode}
+% Use & instead of # temporarily.
+\catcode`\&=6 \catcode`\#=12
+
+\long\def\args &1{\expandafter\countargs\meaning &1#\args->\countargs 0}
+\end{lcode}
+
+ Analysis is restricted to the parameter text by chopping off everything
+ after \verb?->? in the meaning string (this will leave possibly only part
+ of the parameter text).
+
+ Then we look in the parameter text for \# followed by a number
+ (checking to make sure that the thing after \# is a number handles a
+ few extra possibilities, such as \verb?\#? followed by non-number in the
+ parameter text). If we find \# plus a number, we pass the number
+ onward to the next invocation of \cmd{\countargs}, where it will end up as
+ the returned value (argument \#5) if the next \cmd{\countargs} determines
+ that the remaining parameter text contains no more parameter markers.
+\begin{lcode}
+\def\countargs &1#&2&3->&4\countargs &5{%
+ \ifx\args&2&5%
+ \else
+ \ifodd0&21 % Then &2 is a number, carry forward.
+ \countargs&3#\args->\countargs&2%
+ \else % &2 not a number---ignore, carry forward last number instead
+ \countargs&3#\args->\countargs&5%
+ \fi
+ \fi}
+
+\catcode`\#=6
+
+\def\test{\message{The macro \noexpand\foo has \args\foo\space
+ arguments (\meaning\foo).}}
+
+%\tracingmacros=2 \tracingcommands=2
+% Success:
+\def\foo{No args}\test
+\def\foo#1{One arg}\test
+\def\foo#1#2{Two args}\test
+\def\foo./{No args, delimited}\test
+\def\foo#1#2#3#4#5#6#7#8#9{Nine args}\test
+\def\foo//#1#2#3#4#5#6#7#8#9//{Nine args, delimited}\test
+\def\foo#{Weird}\test
+\def\foo#1#{Weird, one arg}\test
+\def\foo#1#2#3#4#5#6#7#8#9#{Weird, nine args}\test
+\def\foo#1 {One arg, space delimited}\test
+\def\foo#1 #2 #3 #4 #5 #6 #7 #8 #9 {Nine args, space delimited}\test
+\def\foo/{\def\foo}
+\foo/ #1{Interesting}\test
+
+\edef\foo#1#2{\string #3\string #4}\test
+\edef\foo{\string #}\test
+\expandafter\edef\expandafter\foo
+ \csname 0\string #\string #\endcsname#1#2{#1#2}\test
+
+% Failure:
+\def\foo->#1->#2->#3->#4->#5->#6->#7->#8->#9->{Nine args, devious
+ delimiter}\test
+\expandafter\edef\expandafter\foo
+ \csname 0\string #1\string #2\endcsname{...}\test
+\let\foo=\bye \test % \outer bomb
+\end{lcode}
+\end{solution}
+%%>>EndSolution
+
+When I originally posed this problem, I had seen far enough ahead to
+suspect that the drawbacks of \cmd{\meaning} mentioned above would be
+impossible to overcome. But \cmd{\meaning} is the only way to analyze a
+macro that has a nonsimple parameter text---that is, one containing
+delimited arguments. Another possibility I had in mind was restricting
+the analysis to macros with simple parameter texts---empty or having
+only nondelimited arguments---to see what might be done without
+\cmd{\meaning}. The best that I could manage in my experiments along these
+lines was a definition of \cmd{\args} with an unacceptably cumbersome call
+syntax. But it does have the virtue of correctly identifying any
+number of nondelimited arguments, no matter whether \cmd{\foo} was
+originally defined using \# (category 6) or some other category 6
+character.
+
+%%>>Solution 3 (mine)
+\begin{solution}{Solution 3 (mine)}
+\begin{lcode}
+% This solution is not fully expandable, hence cannot be used
+% inside a \message.
+
+\def\args{\expandafter\argscontinue}
+
+\def\argscontinue{\begingroup
+\end{lcode}
+ Make all digits have category 2 (= end of group) so that
+ they will serve to end the token register assignment
+ \verb?\global\toks1 ...?
+\begin{lcode}
+ \catcode`\0=2 \catcode`\1=2 \catcode`\2=2 \catcode`\3=2 \catcode`\4=2
+ \catcode`\5=2 \catcode`\6=2 \catcode`\7=2 \catcode`\8=2
+\end{lcode}
+
+ We use \cmd{\afterassignment} to put an \cmd{\endgroup} after the
+ token register assignment, so that numbers will revert to
+ their ordinary catcodes. And we use \cmd{\aftergroup} to put
+ a \cmd{\finishup} token after the \cmd{\endgroup}. Thus \cmd{\finishup} can
+ look ahead to see what numbers are remaining; this information
+ reveals how many arguments were used up by the \cmd{\foo} macro call.
+\begin{lcode}
+ \aftergroup\finishup \afterassignment\endgroup
+ \global\toks1\bgroup}
+\end{lcode}
+
+ \cmd{\finishup} takes the first digit following it and returns it
+ as the value of \cmd{\args}; any following numbers are discarded
+ (note that \#2 is delimited by a space).
+\begin{lcode}
+\def\finishup#1#2 {%\showthe\toks1
+ #1}
+
+%\tracingmacros=2 \tracingcommands=2 \tracingonline=1
+\def\foo{}
+The macro {\tt\string\foo} has \args\foo 00123456789 \ arguments.
+
+\def\foo#1{}
+The macro {\tt\string\foo} has \args\foo 00123456789 \ arguments.
+
+\edef\foo#1{\string #2\string #3\string #4->\string #4\string #3#1}
+The macro {\tt\string\foo} has \args\foo 00123456789 \ arguments.
+
+\def\foo#1#2#3{a#1b#2c#3}
+The macro {\tt\string\foo} has \args\foo 00123456789 \ arguments.
+
+\def\foo#1#2#3#4#5#6#7#8#9{#1#2#3#5#8bb#9}
+The macro {\tt\string\foo} has \args\foo 00123456789 \ arguments.
+\end{lcode}
+\end{solution}
+%%>>EndSolution
+
+The fourth solution for Exercise 6 is by Peter Schmitt; it gets the
+robustness prize for carrying out a diligent analysis of \cmd{\meaning}
+strings that enables it to correctly handle a greater variety of
+exotic cases than the other solutions. Schmitt's original method of
+handling outer macros was effective, but more complicated than
+Arseneau's method, incorporated here as noted. Even though my
+approach was rather different from Schmitt's, some of the comments in
+Schmitt's solution inspired me in turn to improve my solution [2]
+from its previous much inferior state.
+
+%%>>Solution 4 (Peter Schmitt)
+\begin{solution}{Solution 4 (Peter Schmitt)}\index{Schmitt, Peter}
+\begin{lcode}
+% \args <token> expands to: - if <token> is not a macro
+% 0..9 according to the number of parameters
+% if the <token> is a macro
+% \args is fully expandable and accepts outer macros as well.
+% It assumes, however, that the tested macro has been defined using the
+% standard parameter symbol #,
+% and that the current value of \escapechar is the standard backslash \.
+\end{lcode}
+
+ The definition of the macros uses the expansion of
+\cmd{\meaning}\verb?\cs?:
+ It is of the form:
+\begin{lcode}
+ [..] macro: [parameter text] -> [replacement text]
+\end{lcode}
+ and consists of `other characters'.
+
+ The macro \cmd{\args} checks:
+\begin{enumerate}
+\item if the expansion contains `macro': \\
+ --- if not, then \verb?\cs? is not a macro and \cmd{\args} yields `-'
+\item if the expansion contains parameters \#1 etc. \\
+ --- if \verb?#n? is the first that is not present
+ then \verb?\cs? takes (n-1) arguments
+ and \cmd{\args} yields `n-1'
+\end{enumerate}
+ The following special characters are chosen to make the definitions as
+ readable as possible. Any characters having catcodes different from 12
+ will serve the same purpose:
+\begin{lcode}
+\catcode`\:3 \catcode`\/3 % : and / are used as parameter delimiters
+\catcode`\^3 % ^ is used to detect empty arguments
+\catcode`\?11 % ? is used to make the control sequences private
+\end{lcode}
+ Since the occurrences of \# in the expansion of \cmd{\meaning}\verb?\cs? has to be
+ detected, it has to be used as an `other character'.
+ To avoid confusion it has been replaced not only where necessary but
+ throughout all the definitions:
+\begin{lcode}
+\catcode`\#12 \catcode`\*6 % * is parameter character
+\end{lcode}
+\begin{itemize}
+\item \verb|\?macro| is defined to be `macro' consisting of `other characters'
+ using the expansion of \verb?\meaning\TeX?.
+\item \verb?\?DEF? inserts these five characters into some definitions
+ where they are as parameter delimiters:
+\begin{lcode}
+ \DEF\cs { <parameter text> } { <replacement text> }
+\end{lcode}
+ where the texts may contain *1 and **1 .. **9
+ yields
+\begin{lcode}
+ \def\cs <parameter text>{<replacement text>}
+\end{lcode}
+ where *1 is replaced by `macro' and **1 yields *1 etc.
+\end{itemize}
+
+\begin{lcode}
+\def\?macro *1:*2:{*1} \edef\?macro{\expandafter\?macro\meaning\TeX:}
+\def\?DEF *1*2{\def*1**1:{\long\def*1*2}\expandafter*1\?macro:}
+\end{lcode}
+
+\begin{itemize}
+\item \cmd{\args} passes the \meta{token} unexpanded to \verb|args?|
+\item (taken from the solution by Donald Arseneau)
+ \verb|\args?| takes one argument, expands its \cmd{\meaning} to TEXT
+ and passes it to \verb|\macro?| after appending \verb|macro^|:
+\item \verb|\macro?| checks the first token after the first occurrence of
+`macro':
+ if this is \verb?^(3)?, then `macro' was not present in TEXT (output: -)
+ otherwise TEXT is further investigated.
+\end{itemize}
+
+\begin{lcode}
+\def\args{\expandafter\args?\noexpand}
+\?DEF \args? {**1{\expandafter\macro?\meaning **1*1^:}}
+ \?DEF\macro? {**1*1**2:{\ifx^**2-\else\expandafter\purge? **2:\fi}}
+\end{lcode}
+
+ The parameters taken by a control sequence all appear (once and in
+ numerical order) in the parameter text --- and no other occurrence
+ of a pair \verb?#n? is allowed in it. Moreover, only the same pairs \verb?#n?
+may
+ occur in the replacement text. It is, however, not possible to simply
+ look for occurrences of these pairs since there are tokens that may ---
+ if followed by some number --- be (wrongly) interpreted as parameters:
+\begin{itemize}
+\item the token \verb?##? in the replacement text, and
+\item (as pointed out by Michael Downes)
+ -the control symbol \verb?\#? both in the parameter text and the
+ replacement text.
+\end{itemize}
+ Since \verb?\\#n? has to be distinguished from \verb?\#n? the control
+symbol \verb?\\? is also important.
+
+ Therefore \verb|\purge?| is used to remove all occurrences of these tokens.
+ After that the search-macro \verb|\head?| is invoked, appending
+ the sequence \verb?#n^(n-1)? for every possible parameter \verb?#n?.
+
+ Since \verb|\purge?| has to identify the character \verb?\(12)? it is
+necessary to change the escapecharacter:
+
+\begin{lcode}
+\catcode`\!0 !catcode`!\=12 % ! is used as escape character
+\end{lcode}
+
+ \verb|\purge?| appends \verb?## \#^ and \\^? to the TEXT as a means to
+stop the search
+ for these tokens, and : as delimiter:
+\begin{enumerate}
+\item \verb|\backslash?| looks for the first occurrence of the character pair
+ \verb?\\? in TEXT (this must be a token \verb?\\?) and replaces it by a
+ space.
+ If it is followed by \verb?^(3)? then the search is completed,
+ otherwise the process is repeated.
+\item \verb|\numbersign?| looks for the first occurrence of the character pair
+ \verb?\#? in the (in the meantime modified) TEXT (since all \verb?\\? have
+ been removed this must correspond to a token \verb?\#?) and replaces it by
+ a space.
+ Again the process is stopped when it is followed by \verb?^(3)?.
+\item \verb|\parametersign?| truncates TEXT at the first occurrence of the
+ character pair. Note that this pair must correspond to a parameter
+ token \verb?##? in the replacement text and therefore the rest of TEXT is
+ not needed any more.
+\end{enumerate}
+\begin{lcode}
+ !def!purge? *1:{!backslash? *1##\#^\\^:}
+
+% \purge? could be avoided - \macro? could call \backslash? directly
+
+ !def!backslash? *1\\*2*3:{!ifx^*2!expandafter!numbersign?
+ !else !expandafter!backslash?
+ !fi *1 *2*3:}
+ !def!numbersign? *1\#*2*3:{!ifx^*2!expandafter!parametersign?
+ !else !expandafter!numbersign?
+ !fi *1 *2*3:}
+
+!catcode`!\0 \catcode`\!=12 % return to the normal use of backslash
+
+ \def\parametersign? *1##*2:{%
+ \head? *1^#1^0#2^1#3^2#4^3#5^4#6^5#7^6#8^7#9^8#0^9:}
+\end{lcode}
+
+ For each n from 0 to 9 \verb|\head?| extracts the characters contained in
+the (appended) TEXT between the first occurrence of \verb?#n? and
+\verb?#(n+1)? and investigates them with \verb|\used?|.
+
+ If \verb?#n? is not present in TEXT, then the first of these characters is
+\verb?^(3)?, taken from the appended string: \\
+When this happens for the first time \verb|\used?| outputs the second character
+(the number of parameters) and calls \verb|\skip?| to hide all the remaining
+parts of the appended TEXT, otherwise \verb|\used?| checks the next item.
+
+ Since eleven parameters are necessary to handle the ten cases (0..9) this
+duty has to be distributed on two macros: \\
+The appearance of the character \verb?/(3)? is used to indicate that the second
+ macro \verb|\tail?| has to be invoked by \verb|\used?|.
+\begin{lcode}
+ \def\head? *1#1*2#2*3#3*4#4*5#5*6:{%
+ \used? *2..:*3..:*4..:*5..:/.:%
+ \expandafter\tail? *6://}
+ \def\tail? *1#6*2#7*3#8*4#9*5#0*6:{\used? *2..:*3..:*4..:*5..:*6:}
+ \def\used? *1*2*3:{\ifx^*1*2\expandafter\skip?\else\ifx/*1\else
+ \expandafter\expandafter\expandafter\used?\fi\fi}
+ \def\skip? *1//{}
+
+%% Finally, catcodes are turned back to normal:
+
+\catcode`\#6 \catcode`\*12 \catcode`\?12
+\catcode`\:12 \catcode`\/12 \catcode`\^12
+
+%%%%%%%%%%%%%%%%%%%%%%
+
+\long\def\test#1{
+ The macro {\tt\string#1} has {\args#1} arguments.
+
+ \message{The macro \noexpand#1 has :\args#1:\space arguments.}
+}
+
+\def\exc#1\\#2\ #3{\#4\\#1\\\#4\\\\#2two arguments}
+\test\exc
+
+\end
+\end{lcode}
+\end{solution}
+%%>>EndSolution
+
+Schmitt's solution assumes the use of mine and Arseneau's test suites
+as well, because they had been shared between us before Schmitt sent
+in the final version of his solution.
+
+\begin{comment}
+Answers for Exercise 7 will follow next week.
+
+Michael Downes mjd@math.ams.com (Internet)
+\end{comment}
+%%\endinput
+
+
+\chapter{Self replication}
+
+\section{Exercise (hard)}
+
+%%\input{ex007}
+\begin{comment}
+[Posted to info-tex on 4 Nov 91; see exercise.004]
+**********************************************************************
+*** Exercise 7 (hard):
+\end{comment}
+
+\ed{\oposted{1991/11/04}. \arch{exercise.007}.}
+
+In the September 1991 issue of Dr. Dobb's Journal, in an article
+`Little Languages, Big Questions' (pp. 16--25), Ray Vald\'es
+described a `little language' as a part of a more complex
+application that is
+\begin{quote}
+ partitioned into two (or more) nested components: a core module
+ that provides a primitive set of services for an application area
+ (the ``engine''), and a surrounding module that provides
+ programmatic access to these services. The surrounding module is
+ typically a language interpreter for a simple, easily parsed
+ computer language--a ``little language''.
+\end{quote}
+
+Since TeX seems to fall into this category, I wonder if any Dr. Dobb's
+readers who know TeX tried their hand at the challenge given in a
+sidebar (`How Strong Is Your Little Language')?
+\begin{quote}
+ [An] informal benchmark of a language's computational power is the
+ programming exercise that Ken Thompson (coauthor of Unix) used to
+ pass the time in college. ... The goal is to write the shortest
+ self-reproducing program: ``More precisely stated ... to write a
+ source program that, when compiled and executed, will produce as
+ output an exact copy of its source.''
+\end{quote}
+
+When I tried it it turned out to be a real challenge for me. In the
+Unix world, for conventional compiled languages, the problem as
+originally stated can assume output on the `standard output' stream;
+but TeX already clutters up standard output with some of its built-in
+messages. This leaves three alternatives in refining the statement of
+the problem to be meaningful for TeX:
+
+1. Write a TeX program that includes the built-in messages in its
+source in such a way that it exactly fulfills the the original problem
+statement with standard output as the output stream.
+
+2. Pretend the built-in messages don't exist and write a TeX program
+that reproduces an exact copy of itself (with no extra garbage)
+in the middle of the built-in messages.
+
+3. Write on a different output stream.
+
+Take your pick, any or all of the above, and see what you can come up
+with. I have solutions for 2 and 3 but have not gotten around to really
+thinking about 1 yet. I believe it will require at least a different
+algorithm than the other 2, if it is not impossible.
+
+%%%**********************************************************************
+%%\endinput
+
+\section{Answers}
+
+%%\input{ans007}
+% ans007.tex
+\begin{comment}
+[The `forthcoming' TUGboat article cited below appeared as
+`Self-replicating macros' by Victor Eijkhout and Ron Sommeling, TUGboat
+13 (1992) no 1, p. 84]
+
+Date: Tue 7 Jan 92 16:43:29-EST
+From: Michael Downes <MJD@MATH.AMS.COM>
+Subject: 'Around the bend' #2, Exercise 7, solutions
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+
+"*** Exercise 7 (hard):
+"
+"In the September 1991 issue of Dr. Dobb's Journal, in an article
+"`Little Languages, Big Questions' (pp. 16--25), Ray Vald\'es
+"described a `little language' as a part of a more complex
+"application that is
+"
+" partitioned into two (or more) nested components: a core module
+" that provides a primitive set of services for an application area
+" (the ``engine''), and a surrounding module that provides
+" programmatic access to these services. The surrounding module is
+" typically a language interpreter for a simple, easily parsed
+" computer language--a ``little language''.
+"
+"Since TeX seems to fall into this category, I wonder if any Dr. Dobb's
+"readers who know TeX tried their hand at the challenge given in a
+"sidebar (`How Strong Is Your Little Language')?
+"
+" [An] informal benchmark of a language's computational power is the
+" programming exercise that Ken Thompson (coauthor of Unix) used to
+" pass the time in college. ... The goal is to write the shortest
+" self-reproducing program: ``More precisely stated ... to write a
+" source program that, when compiled and executed, will produce as
+" output an exact copy of its source.''
+"
+"When I tried it it turned out to be a real challenge for me. In the
+"Unix world, for conventional compiled languages, the problem as
+"originally stated can assume output on the `standard output' stream;
+"but TeX already clutters up standard output with some of its built-in
+"messages. This leaves three alternatives in refining the statement of
+"the problem to be meaningful for TeX:
+"
+"1. Write a TeX program that includes the built-in messages in its
+"source in such a way that it exactly fulfills the the original problem
+"statement with standard output as the output stream.
+"
+"2. Pretend the built-in messages don't exist and write a TeX program
+"that reproduces an exact copy of itself (with no extra garbage)
+"in the middle of the built-in messages.
+"
+"3. Write on a different output stream.
+"
+"Take your pick, any or all of the above, and see what you can come up
+"with. I have solutions for 2 and 3 but have not gotten around to really
+"thinking about 1 yet. I believe it will require at least a different
+"algorithm than the other 2, if it is not impossible.
+\end{comment}
+
+\ed{\oposted{1992/01/07}. \arch{answer.007}.}
+
+
+Plenty of good answers for this one.
+
+%%>>Solution 1 (mine)
+\begin{solution}{Solution 1 (mine)}
+
+ This solution is type 2 (print the copy in the middle of TeX's
+ built-in messages). It assumes \pfile{plain.tex} or similar has been
+ loaded to set the catcodes of the left and right curly braces.
+
+ The idea is to assign the text to the token register \cmd{\errhelp}
+ (used merely because it is a convenient pre-existing token
+ register), and then print out \cmd{\the}\cmd{\errhelp} twice. There is a bit
+ of shuffling to ensure that \cmd{\errhelp} will swallow the last half of
+ the file and that the last half of the file is equal to the first
+ half, which contains all the preparations necessary to prepare
+ \cmd{\errhelp} for that swallowing and the subsequent message-sending.
+
+ A space is left after every control word, because this is easier
+ than trying to prevent TeX from printing spaces after control
+ words when the message is eventually printed on screen.
+
+ The lines are carefully arranged to break at column 79
+ (including spaces) since this is the normal value for \verb?max_print_line?,
+ a constant compiled into TeX which controls the length of screen
+ output lines. It would be easy to make the lines work out nicely
+ no matter what the working code required, by varying the length
+ of the macro name \cmd{\selfcopy} and using, say, \cmd{\everyhbox} or
+ \cmd{\everyjob} instead of \cmd{\errhelp}.
+
+ The total number of tokens in this solution is 54.
+
+\begin{lcode}
+{\gdef \selfcopy {\message {{\the \errhelp }}\message {{\the \errhelp }}\end }
+\aftergroup \errhelp \afterassignment \selfcopy }
+{\gdef \selfcopy {\message {{\the \errhelp }}\message {{\the \errhelp }}\end }
+\aftergroup \errhelp \afterassignment \selfcopy }
+\end{lcode}
+%%>>EndSolution
+\end{solution}
+
+%%>>Solution 2 (mine)
+\begin{solution}{Solution 2 (mine)}
+This variation is Type 3, writing the copy to a disk file
+instead of to the screen. The total number of tokens in this
+solution is 126.
+\begin{lcode}
+\immediate \openout 0=\jobname .cpy
+{\gdef ~#112{\errhelp {#112}\immediate \write 0{\the \errhelp
+}\immediate \write 0{\the \errhelp }\immediate \closeout 0 \end}}
+\newlinechar 13 \catcode `\#=3 \afterassignment ~\catcode 13=12
+\immediate \openout 0=\jobname .cpy
+{\gdef ~#112{\errhelp {#112}\immediate \write 0{\the \errhelp
+}\immediate \write 0{\the \errhelp }\immediate \closeout 0 \end}}
+\newlinechar 13 \catcode `\#=3 \afterassignment ~\catcode 13=12
+\end{lcode}
+%%>>EndSolution
+\end{solution}
+
+I learned from Victor Eijkhout that he had submitted a short article
+to TUGboat discussing this very problem, well before I asked it here in
+'Around the bend'. He kindly sent me a copy of the article, which
+contains a good discussion of the underlying ideas, and a couple of
+different solutions. To summarize briefly, he gave a Type 2 solution
+similar in length to mine, and also a solution that involved
+printing out the source file on PAPER! A 'Type 4' solution, in other
+words. I'm a little embarrassed that I didn't think of this, given that
+the whole idea of TeX is to print things on paper.
+
+%%>>Solution 2 (Victor Eijkhout)
+\begin{solution}{Solution 2 (Victor Eijkhout)}\index{Eijkhout, Victor}
+Forthcoming in TUGboat. It appeared as: \\
+`Self-replicating macros' by Victor Eijkhout and Ron Sommeling, TUGboat
+13 (1992) no 1, p. 84.
+%%>>EndSolution
+\end{solution}
+
+Although I'm giving them all together, as `Solution 3', Peter Schmitt
+actually sent in six different variations, including a Type 4 solution.
+His first solution, \pfile{log-pl.tex} is Type 2 like my first solution but
+comes in at 38 tokens, significantly shorter. His third solution is
+comparable to my second solution but once again significantly shorter
+(87 tokens).
+
+\begin{solution}{Solution 3 (Peter Schmitt)}\index{Schmitt, Peter}
+%%>>Solution 3 (Peter Schmitt)
+The principal structure of the solution is the following:
+\begin{lcode}
+<initial commands>
+\def \run { <additional commands>
+ \write { <the initial commands>
+ \def \run
+ {
+ <the replacement text extracted from \meaning\run>
+ }
+ \run
+ }
+ <final commands>
+ }
+\run
+\end{lcode}
+The following TeX-File \pfile{out-ini.tex} when processed by INITeX
+produces a file \pfile{out-ini.out} that is identical to \\
+ \pfile{out-ini.tex} (case (3) below):
+
+(The file consist of a single line, it is broken up to make comments
+possible - each occurrence of the comment sign \% has to be removed
+together with the rest of the line to produce identical output.)
+
+\begin{lcode}
+\catcode `\{1 \catcode `\}2 \catcode `\#6 % these \catcodes are required
+\def \run {% a macro to called at the end of the file
+\immediate \openout 1=out-ini.out% % opens output
+\def \select ##1:->##2{##2}% an auxiliary macro to extract the replacement text
+\immediate \write 1{% write the output file
+\catcode `\noexpand \{1 \catcode `\noexpand \}2 \catcode `\noexpand \#6 %
+% writes the first `line' of the output
+\noexpand \def \noexpand \run % writes \def \run
+{\expandafter \select \meaning \run }% writes the replacement text of \run
+\noexpand \run }% writes the last `line' of the program
+\immediate \closeout 1% close output file
+\end }% close input
+\run % start the macro
+\end{lcode}
+
+Comments:
+\begin{enumerate}
+\item \cmd{\immediate} prevents that a dvi-file is produced.
+\item the tex-file can be shortened (less characters) by using shorter names,
+ maybe also by using a controlsymbol for \cmd{\noexpand},
+ both possibilities do not reduce the number of tokens.
+ Maybe some \cmd{\space} tokens can be removed but most of them are necessary
+ because they are produced by \cmd{\meaning}.
+\begin{itemize}
+ \item \cmd{\immediate} may be omitted (produces dvi-file)
+ \item at least with my implementation closing the output file is not
+ necessary
+\end{itemize}
+\item The TeX-file can be modified to solve variations of the exercise:
+ \begin{itemize}
+ \item If the file is to be processed by plain TeX \cmd{\catcodes} need not be set
+ (see (1) below).
+ \item if the output file is replaced by standard output or the log file
+ \cmd{\message} instead of \cmd{\write} can be used (see (1) and (2) below).
+ Note that in this case macro names and spaces have to be adjusted
+ so that the line breaks produced do not prevent processing
+ the file (In the log file line breaks may occur even in control
+ sequence names!)
+
+ I have not (not yet?) been able to solve the exercise using more
+ pleasant (predetermined) linebreaks.
+ \item It is possible to produce a log file that is identical to the
+ input file. But since the log file contains the time of processing
+ this will be the case only at a specific date and time (see (4) below).
+ (The time is output before the input file is read. Therefore it is
+ impossible to change this part of output by the input.)
+ \item Of course, the above variation can be modified to produce a screen
+ output identical to the input file.
+ \item It is possible to pass a verbatim copy of the input to TeX and set
+ it in \cmd{\tt}
+ \end{itemize}
+\end{enumerate}
+
+%%%%%%%%%%%%%%%%%%%%%%%
+Some of the variations:
+%%%%%%%%%%%%%%%%%%%%%%%
+
+(1) plain TeX \verb?-->? section of log file or standard output terminal
+\begin{lcode}
+%%% log-pl.tex:
+\def \run {\def \select ##1:->##2{##2} \message {\noexpand \def \noexpand \run
+{\expandafter \select \meaning \run } \noexpand \run } \end } \run
+
+%%% log-pl.log
+This is TeX, Version 3.1(c)sb34 (preloaded format=plain3sm 91.4.28)
+24 NOV 1991 02:15
+** &plain log-pl
+(log-pl.tex
+\def \run {\def \select ##1:->##2{##2} \message {\noexpand \def \noexpand \run
+{\expandafter \select \meaning \run } \noexpand \run } \end } \run )
+No pages of output.
+\end{lcode}
+
+(2) INITeX \verb?-->? section of log file or standard output terminal
+\begin{lcode}
+%%% log-ini.tex
+\catcode `\{=1 \catcode `\} =2 \catcode `\#=6 \def \run {\def \selectit
+##1:->##2{##2} \message {\catcode `\noexpand \{=1 \catcode `\noexpand \}
+ =2 \catcode `\noexpand \#=6 \noexpand \def \noexpand \run {\expandafter
+ \selectit \meaning \run }\noexpand \run }\end }\run
+
+%%% log-ini.log
+This is TeX, Version 3.1(c)sb34 (INITEX)
+24 NOV 1991 02:16
+** log-ini.tex
+(log-ini.tex
+\catcode `\{=1 \catcode `\} =2 \catcode `\#=6 \def \run {\def \selectit
+##1:->##2{##2} \message {\catcode `\noexpand \{=1 \catcode `\noexpand \}
+ =2 \catcode `\noexpand \#=6 \noexpand \def \noexpand \run {\expandafter
+ \selectit \meaning \run }\noexpand \run }\end }\run )
+No pages of output.
+\end{lcode}
+
+(3) INITeX \verb?-->? output file
+\begin{lcode}
+%%% out-ini.tex (Note: A single line broken at the %'s!)
+\catcode `\{1 \catcode `\}2 \catcode `\#6 \def \run {\immediate \openout %
+1=out-ini.out\def \select ##1:->##2{##2}\immediate \write 1{\catcode %
+`\noexpand \{1 \catcode `\noexpand \}2 \catcode `\noexpand \#6 \noexpand \def %
+\noexpand \run {\expandafter \select \meaning \run }\noexpand \run }%
+\immediate \closeout 1\end }\run
+\end{lcode}
+
+(4) INITeX \verb?-->? log file
+\begin{lcode}
+%%% flog-ini.tex
+This is TeX, Version 3.1(c)sb34 (INITEX)
+24 NOV 1991 02:17
+** flog-ini.tex
+(flog-ini.tex
+\catcode `\{=1 \catcode `\} =2 \catcode `\#=6 \def \run {\def \selectit
+##1:->##2{##2} \message {\catcode `\noexpand \{=1 \catcode `\noexpand \}
+ =2 \catcode `\noexpand \#=6 \noexpand \def \noexpand \run {\expandafter
+ \selectit \meaning \run }\noexpand \run }\end }\run [0] )
+Output written on flog-ini.dvi (1 page, 512 bytes).
+
+%%% flog-ini.log
+This is TeX, Version 3.1(c)sb34 (INITEX)
+24 NOV 1991 02:18
+** flog-ini.tex
+(flog-ini.tex
+\catcode `\{=1 \catcode `\} =2 \catcode `\#=6 \def \run {\def \selectit
+##1:->##2{##2} \message {\catcode `\noexpand \{=1 \catcode `\noexpand \}
+ =2 \catcode `\noexpand \#=6 \noexpand \def \noexpand \run {\expandafter
+ \selectit \meaning \run }\noexpand \run }\end }\run [0] )
+Output written on flog-ini.dvi (1 page, 512 bytes).
+\end{lcode}
+
+(5) INI-TeX \verb?-->? log-file (formatted)
+\begin{lcode}
+%%% fmt-log.tex
+This is TeX, Version 3.1(c)sb34 (INITEX)
+30 NOV 1991 13:13
+** fmt-log
+(fmt-log.tex [0
+\catcode `\{=1 \catcode `\}=2
+\catcode `\#=6
+\def \run
+{\newlinechar 1 \lccode `\|=1
+ \lccode `\[=`\{ \lccode `\]=`\}
+ \lowercase {
+ \def \format ##1>##2=1##3]##4[##5]##6]{##2=1|##3]|##4[|##5]|##6]|\+}
+ \def \+ ]##12]##2]##3]##4]]##5] { ]|##12]|##2]|##3]|##4]]|##5]|}
+ }
+ \write 0{\catcode `\noexpand \{=1 \catcode `\noexpand \}=2}
+ \write 0{\catcode `\noexpand \#=6}
+ \write 0{\noexpand \def \noexpand \run }
+ \write 0{{\expandafter \format \meaning \run }}
+ \write 0{\noexpand \run }
+\end }
+\run
+] )
+Output written on fmt-log.dvi (1 page, 512 bytes).
+\end{lcode}
+
+(6) INITeX \verb?-->? dvi-file
+\begin{lcode}
+%%% dvi-ini.tex
+\catcode`\% = 13
+\catcode`\{ = 1 \catcode `\} = 2
+\catcode`\# = 6 \catcode `\| = 13
+\catcode`\% = 13
+\def \run {
+ \lccode `\[=`\{ \lccode `\]=`\} \lccode `\/=`\% \let % = \par %%
+ \font\tt=cmtt10 \tt %
+ \hsize 15cm \vsize 15cm \parskip 3pt \def |{\par \hskip .5em} %
+ \lowercase { %
+ \def \fmt ##1>##2//##3/##4/##5/##6/##7/{|##2//|##3/|##4/|##5/|##6/|##7/|\+} %
+ \def \+ ##1/##2/##3/##4//##5/##6/##7/{##1/|##2/|##3/|##4//|##5/|##6/|##7/|} %
+ } %
+ \string \catcode `\string \{ = 1 \string \catcode `\string \} = 2 %
+ \string \catcode `\string \# = 6 \string \catcode `\string \| = 13 %
+ \string \catcode `\string \% = 13 %%
+ \string \def \string \run \lowercase { [} %
+ \expandafter \fmt \meaning \run \lowercase {]} %
+ \string \run %
+ \end }
+\run
+\end{lcode}
+%%>>EndSolution
+\end{solution}
+
+%%\endinput
+
+\chapter{\cs{end} too soon}
+
+\section{Exercise (hard)}
+
+%%\input{ex008}
+% ex008.tex
+\begin{comment}
+Date: 21 Jun 1993 09:49:27 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #8
+To: info-tex@shsu.edu
+\end{comment}
+
+\ed{\oposted{1993/06/21}. \arch{exercise.008}.}
+
+A few readers of info-tex and comp.text.tex may recall some postings
+of mine under the name of `Around the Bend' more than a year ago. This
+was intended to be a regular quasi-monthly stream of challenging
+questions about TeX macro writing, but after a few appearances it fell
+into limbo because of too many other demands on my time. However I
+continue to encounter hard, interesting problems in my work so
+herewith wish to announce resumption of the `Around the Bend' postings
+on an occasional, slightly less ambitious basis.
+
+For background, here are a couple of excerpts from the first `Around
+the Bend' post:
+\begin{quote}
+ With the encouragement of George Greenwade (the INFO-TeX list owner), I
+ would like to propose a regular department for INFO-TeX, called `Around
+ the bend'. It will consist of macro-writing challenges on the level of
+ the dangerous-bend exercises in the \emph{TeXbook}, with interested parties
+ invited to collaborate and/or compete to find the best solution. My
+ motivation for doing this is partly selfish: to get more feedback from
+ other macro writers about some of the interesting macro-writing
+ problems that I run into.
+
+\ldots
+
+
+
+ Solutions should be sent to me instead of to INFO-TeX or
+ comp.text.tex, on the premise that people usually won't want to read
+ others' solutions until they've had a chance to try their own hand. A
+ summary of the results would then be posted to the INFO-TeX list after
+ two or three weeks; to those who submit solutions before the deadline,
+ I could forward without delay solutions submitted by other people, for
+ comparison.
+\end{quote}
+
+And here's number 8.
+
+%%***********************************************************************
+%%*** Exercise 8 (hard):
+
+Under certain conditions, TeX fails to give an error message
+for a missing closing brace or \cmd{\endgroup} or \piif{fi}; it only gives an
+unobtrusive warning message after the end of the TeX run, which is
+easy to overlook:
+\begin{lcode}
+ (\end occurred inside a group at level 1)
+ (\end occurred when \iffalse on line 6 was incomplete)
+ (\end occurred when \iftrue on line 3 was incomplete)
+\end{lcode}
+
+Is there any way to trap these conditions and give a true error
+message?---if, let's say, you are programming for a major macro
+package like LaTeX and want to make sure these conditions are brought
+to the user's attention.
+
+%%%***********************************************************************
+
+\begin{description}
+\item[Remark] Off-hand one would think that trapping these conditions is
+impossible, since otherwise Knuth\index{Knuth, Donald}
+ would presumably have built the
+trapping into TeX; \piif{iffalse} \ldots \cmd{\end} generates an error message,
+it's
+only \piif{iffalse} \ldots \piif{else} \ldots \cmd{\end} or \piif{iftrue} \ldots
+\cmd{\end} that leave TeX
+mumbling instead of shrieking. But in some cursory experiments, I
+found a not-too-bad solution for the missing end of group condition.
+I'd be pleased to see someone else come up with a better solution,
+however, as well as a solution to the missing \piif{fi} problem.
+\end{description}
+
+\begin{comment}
+Send answers to:
+
+Michael Downes mjd@math.ams.org (Internet)
+
+A summary will be posted circa July 12, 1993.
+\end{comment}
+%%\endinput
+
+
+\section{Answers}
+
+%%\input{ans008}
+% ans008.tex
+\begin{comment}
+[The addendum at bottom was not posted with the answer but added in my
+archives later ---mjd]
+
+Date: 22 Jul 1993 15:54:57 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #8 answers
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+
+Exercise 8 asked for a way to trap missing }, \endgroup, or \fi at the
+end of a [La]TeX document, in order to give error messages instead
+of the warning messages issued by TeX:
+
+ (\end occurred inside a group at level 1)
+ (\end occurred when \iffalse on line 6 was incomplete)
+\end{comment}
+
+\ed{\oposted{1993/07/22}. \arch{answer.008}.}
+
+This review of solutions is posted later than expected because I
+needed time to try out and understand solutions submitted by Peter
+Schmitt last week. For clarity's sake, I have split the solutions
+into two parts, one dealing with groups, the other with conditionals.
+
+\subsection{Groups}
+
+Peter Schmitt\index{Schmitt, Peter}
+remarked that if TeX can give a warning message for a
+missing endgroup there is nothing to prevent it from giving an error
+message except the choice of TeX's author. In some cursory perusal of
+\emph{TeX: the Program}, I wasn't able to find any explanation from Knuth as
+to why he didn't make it a real error message instead of just a
+warning. Perhaps someone else can shed some light here?
+
+Now for solutions. The first one was submitted by Peter Schmitt. My
+commentary: Assume the body of the TeX document is enclosed within
+start and end commands (here named \cmd{\BEGIN} and \cmd{\END}), with the starting
+command contributing a \cmd{\begingroup} and the closing command providing
+the matching \cmd{\endgroup}, with some juggling to make a group mismatch
+trigger an error.
+
+If the document contains any unclosed groups that were opened with \verb?{?
+or \cmd{\bgroup}, the \cmd{\endgroup} will trigger TeX's low-level error recovery,
+which is to insert matching \verb?}?s ({\ttfamily `Missing \verb?}? inserted'}).
+Thus only the
+case of an unmatched \cmd{\begingroup} needs to be handled. Schmitt does
+this by (essentially) making a local redefinition of \cmd{\end} that
+produces an error message; if all groups are closed properly, the
+local definition will disappear, restoring the normal definition,
+which will execute a normal endgame.
+
+Here now Schmitt's submitted solution. I have simplified it slightly
+by disentangling some other stuff that will be discussed later below.
+
+\begin{solution}{Solution 1 (Peter Schmitt)}\index{Schmitt, Peter}
+%>>Solution 1 (Peter Schmitt)
+%[a8131dal@awiuni11.edvz.univie.ac.at, schmitt@awirap.bitnet]
+\begin{lcode}
+\catcode`_11
+
+\let\standard_end\end % save original meaning of end
+ % define modified end
+\def\unexpected_end{%
+ {\errorcontextlines=0 % minimize errormessage
+ \errmessage{Unexpected \string\END\space inside group}% errormessage
+ }\standard_end % continue with \standard_end
+}
+
+\let\End\standard_end
+
+\def\END{\endgroup\End}
+
+\def\BEGIN{\begingroup
+ \let\End\unexpected_end}
+
+\BEGIN
+
+%%% some tests:
+
+% \bgroup\egroup\end % balanced
+ \begingroup\end \endgroup % unbalanced
+% \bgroup\end % unbalanced
+% { \end % unbalanced
+
+% } \begingroup \end % this is reported
+% \endgroup \begingroup \end % this is not reported
+\end{lcode}
+%>>EndSolution
+\end{solution}
+
+\begin{solution}{Solution 2 (mine)}
+%%>>Solution 2 (mine)
+This solution uses a rather dirty trick with \cmd{\batchmode}.
+Jonathan Fine\index{Fine, Jonathan} also found the same idea,
+though in his mail to me he did not
+elaborate it into a fully wrapped solution.
+
+Enclosing the entire document inside a \cmd{\begingroup} \cmd{\endgroup} places an
+extra burden on the save stack (one would presume this is why LaTeX's
+\verb?\begin{document}? and \verb?\end{document}? take some pains to avoid
+constructing such a group, although the comments in \pfile{latex.tex} don't
+provide an explicit reason). (Extra credit question: Just how much of
+a burden would it place on the save stack in, say, an average LaTeX
+document?) So my solution seeks to trap unmatched \verb?{? or \cmd{\begingroup}
+without enclosing the document body in a group. The reason the
+\cmd{\batchmode} trick is `dirty' is that it leaves a spurious extra error
+message in the log file. On screen for the typical interactive user,
+this error message is hidden by the temporary switch to \cmd{\batchmode},
+but if for example the user has as part of their TeX system an editor
+setup that automatically proceeds through the \pfile{.log} file to help the
+user take care of all error messages, then the spurious error message
+will be somewhat inconvenient.
+
+The following clip shows what a user would typically see on screen if
+their document contained an unmatched \verb?{?.
+\begin{lcode}
+ ! Missing } added.
+ \bgrouperr ...ffalse {\fi \string } added}
+
+ \enddocument ...rgroup \bgrouperr \egroup
+ \if \errorstopping \batchmo...
+ l.50 \enddocument
+
+ ? h
+ There appears to be an unmatched opening brace or \bgroup somewhere
+ in your document.
+ ?
+
+ )
+ No pages of output.
+\end{lcode}
+
+Here then is the code for the solution. As it stands, only the most
+recent unmatched open-group is dealt with in the error message. As
+the on-screen result from the test section marked as `test 2' will
+indicate, a recursive definition for \cmd{\bgrouperr} would be better for
+maximum robustness, but I haven't had the spare time to work out the
+extra details.
+\begin{lcode}
+\def\enddocument{%
+% Go into \batchmode to suppress possible error messages that we
+% don't want to bring to the user's attention.
+ \batchmode
+% Set a flag to enable us to handle the \endgroup properly if the
+% \egroup pairs up with an unmatched { or \bgroup.
+ \def\errorstopping{TF}%
+% If the following \egroup matches with a preceding unmatched { or
+% \bgroup in the user document, then the aftergroup tokens
+% \errorstopmode \bgrouperr will be executed. Otherwise they will
+% go away into uncharted limbo.
+ \aftergroup\errorstopmode\aftergroup\bgrouperr
+ \egroup
+% If there was no unmatched { or \bgroup, then the preceding
+% \egroup was discarded by TeX. And \errorstopping is still false.
+% Otherwise we need to insert some new \aftergroup tokens.
+ \if\errorstopping
+ \batchmode \aftergroup\errorstopmode \aftergroup\begingrouperr
+ \else
+ \global\let\bgrouperr\begingrouperr
+ \fi
+ \endgroup
+ \errorstopmode
+% Call two different versions of \end, just for convenient testing
+% with either plain TeX and LaTeX.
+ \csname\string @\string @end\endcsname
+ \end}
+
+\def\bgrouperr{%
+ \def\errorstopping{TT}%
+ \errhelp{%
+There appears to be an unmatched opening brace or \bgroup somewhere^^J%
+in your document.}%
+ \errmessage{Missing \iffalse{\fi\string} added}}
+
+\def\begingrouperr{%
+ \errhelp{%
+There appears to be an unmatched \begingroup somewhere in
+your document.}%
+ \errmessage{Missing \noexpand\endgroup added}}
+
+\newlinechar=`\^^J
+
+% % Test 0: Leave the following three lines commented out.
+%{ % Test 1: uncomment this line
+%\bgroup % Test 2: uncomment the previous line and this one.
+%\begingroup % Test 3: uncomment all three lines.
+
+\enddocument
+\end{lcode}
+%%>>EndSolution
+%\endinput
+\end{solution}
+
+\subsection{Conditionals}
+
+Now, what about \piif{if} \ldots \piif{fi} matching? Can a method analogous to
+the one
+for groups be applied here? Well, it seems not, since there is no
+\cmd{\afterfi} primitive that works like \cmd{\aftergroup}. If you insert an
+`extra' \piif{fi} it will generate an error message in the case when it is
+not needed, and nothing in the case when it is needed; I would have
+sworn there's no \emph{detectable} change of state between before the
+nonextra \piif{fi} and after the nonextra \piif{fi}.
+
+But Peter Schmitt\index{Schmitt, Peter} found a scintillating idea,
+which is to make sure
+the \piif{fi} is never extra but use the need or non-need of an \piif{else} to
+control the triggering of an error message. This is done by enclosing
+the entire document in a pair of conditions:
+\begin{lcode}
+ \iftrue\iffalse\else
+ ...
+ \fi...\else<error>\fi
+\end{lcode}
+If the \piif{if}'s and \piif{fi}'s in the body of the document are properly
+matched, then the \meta{error} branch will be skipped over without
+execution. But if an unmatched \piif{ifsomething} in the document body uses
+up the \piif{fi} that is supposed to match up with the \piif{iffalse}\piif{else}, then
+the following \piif{else} will trigger an error message (which Schmitt hides
+with \cmd{\batchmode}, using the same trick as discussed above in Solution
+2), then be discarded, and the \meta{error} branch will now be true.
+
+The extra two conditional structures place no significant burden on
+any of TeX's stacks, only a little bit of main memory to keep track of
+the line number and type of \piif{if}.
+
+Peter had the group and conditional trapping combined in his original
+solution; here is the conditional trapping part as I disentangled it.
+
+\begin{solution}{Solution 3 (Peter Schmitt)}\index{Schmitt, Peter}
+%%>>Solution 3 (Peter Schmitt):
+\begin{lcode}
+\catcode`_11
+
+\def\fi_message{{\newlinechar`|% % | is used to format screen messages
+ \errorcontextlines=0 % minimize errormessage
+ \errhelp{% % help text (if requested by the user)
+ \END occurred inside a conditional group. |%
+ You probably have forgotten to close some \fi before.
+ }%
+ \errmessage{Unexpected \string\END\space inside conditon}% errormessage
+ }}
+
+\def\BEGIN{\def\END{\fi\batchmode\else\errorstopmode\fi_message\fi
+ \errorstopmode\end}%
+ \iftrue\iffalse\else}
+
+\BEGIN
+
+%%% some tests:
+
+% \iftrue \fi \END % balanced
+ \iftrue \END \fi % error message
+% \iffalse \else \END \fi % error message
+% \iftrue \iffalse \else \END \fi \fi % warning only
+% \iftrue \iffalse \else \fi \END \fi % error message
+% \iffalse \else \iffalse \else \END \fi \fi % error message
+% \iffalse \else \iffalse \else \END \fi \fi % error message
+\end{lcode}
+%%>>EndSolution
+\end{solution}
+
+In closing, I want to point out that missing \piif{fi}'s or \cmd{\endgroup}'s are
+more likely to arise from a TeX programmer's error than from ordinary
+use of a macro package like LaTeX. So it might be minimally sufficient
+to trap only the missing \verb?}? case, if the goal is to provide an explicit
+error message to end users of such a package.
+
+%%Michael Downes
+
+PS. Hint for Exercise 10: Run the body of the posting through plain TeX.
+
+\begin{lcode}
+ASCII 32--64,65--126:
+ !"#$%&'()*+,-./0123456789:;<=>?@
+ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+\end{lcode}
+
+\subsection{Addendum}
+I found this in \texttt{comp.text.tex}. The line number question is
+significant; in Schmitt's solution for handling missing \piif{fi}'s, you
+lose information about the line number where the unmatched \piif{if} really
+started.
+
+\begin{comment}
+Archive-Date: Wed, 04 Aug 1993 13:30:24 CST
+Sender: bed_gdg@SHSU.EDU
+From: morje@math.ohio-state.edu (Prabhav Morje)
+Reply-To: morje@math.ohio-state.edu (Prabhav Morje)
+Subject: "end occurs inside a group" error in LaTeX
+Date: 3 Aug 1993 22:36:30 -0400
+Message-ID: <23n7be$e32@math.mps.ohio-state.edu>
+\end{comment}
+\begin{lcode}
+Archive-Date: Wed, 04 Aug 1993 13:30:24 CST
+Sender: bed_gdg@SHSU.EDU
+From: morje@math.ohio-state.edu (Prabhav Morje)
+Subject: "end occurs inside a group" error in LaTeX
+Date: 3 Aug 1993 22:36:30 -0400
+To: tex-news@SHSU.EDU
+
+Hi,
+ I sometimes get the error "\end occured while inside a group
+on level 1" while running LaTeX. I know it means there is an extra
+"{" somewhere. It is harmless sometimes but if I want to correct it,
+LaTeX never tells where the extra "{" is. Is it possible to find the
+line number or something more about location of the error?
+
+ Any pointers will be greatly appreciated.
+- Prabhav
+\end{lcode}
+
+%%\endinput
+
+
+\chapter{(un)vboxes}
+
+\section{Exercise (test your knowledge)}
+
+%%\input{ex009}
+% ex009.tex
+\begin{comment}
+Date: 28 Jun 1993 14:57:21 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #9
+To: info-tex@shsu.edu
+\end{comment}
+
+\ed{\oposted{1993/06/28}. \arch{exercise.009}.}
+
+Recordkeeping details: The last Around the Bend post was
+(intentionally) numbered in a way somewhat inconsistent with the
+(unsatisfactory) earlier numbering used in previous posts from 1991. I
+didn't draw attention to the change since I figured `who cares?' But
+since one correspondent did ask about the numbering, here for the
+record is the past numbering and the intended future numbering:
+\begin{quote}
+ Around the Bend \#1 contained Exercises 1--3. \\
+ Around the Bend \#2 contained Exercises 4--7. \\
+ Around the Bend \#8 contained Exercise 8. \\
+ Around the Bend \#9 contains Exercise 9. \\
+ Around the Bend \#10 will contain Exercise 10. \\
+ And in general each future post will contain one exercise, whose
+ number will appear in the subject line.
+\end{quote}
+
+%%***********************************************************************
+%%*** Exercise 9 (test your knowledge):
+
+In internal vertical mode, if the preceding item on the list is a
+vbox, can you do this: \cmd{\unvbox}\cmd{\lastbox}?
+%%***********************************************************************
+
+\begin{comment}
+An answer will be posted circa July 6, 1993.
+
+Michael Downes mjd@math.ams.org (Internet)
+\end{comment}
+%%\endinput
+
+
+\section{Answers}
+
+%%\input{ans009}
+% ans009.tex
+\begin{comment}
+Date: 07 Jul 1993 12:45:34 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #9, answer
+Sender: ITeX-Mgr@SHSU.edu
+To: info-tex@shsu.edu
+Reply-to: Michael Downes <MJD@MATH.AMS.ORG>
+Message-id: <742063535.36965.MJD@math.ams.org>
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+
+"In internal vertical mode, if the preceding item on the list is a
+"vbox, can you do this: \unvbox\lastbox?
+\end{comment}
+
+\ed{\oposted{1993/07/07}. \arch{answer.009}.}
+
+The answer is no. If you tried it, you would have seen the error
+message:
+\begin{lcode}
+ ! Missing number, treated as zero.
+ <to be read again>
+ \lastbox
+ l.3 \unvbox\lastbox
+
+ ? h
+ A number should have been here; I inserted `0'.
+ (If you can't figure out why I needed to see a number,
+ look up `weird error' in the index to The TeXbook.)
+\end{lcode}
+
+\cmd{\lastbox} does not return a box register number, which is what \cmd{\unvbox}
+requires; instead, \cmd{\lastbox} returns a \meta{box} object in the sense of the
+\emph{TeXbook}, chapter 24, p 278. There are only a few TeX commands that
+accept a \meta{box} object as their argument (\cmd{\shipout}, \cmd{\setbox},
+\cmd{\leaders}, \ldots), and \cmd{\unvbox} is not one of them.
+
+%%\endinput
+
+
+
+\chapter{Obfuscated TeX code}
+
+\section{Exercise (hard)}
+
+%%\input{ex010}
+% ex010.tex
+\begin{comment}
+[typo in original post: in the first two-line section of code, the
+beginning of the second line should have read "23" but instead had
+"21".]
+Date: 07 Jul 1993 16:11:31 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #10
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+\ed{\oposted{1993/07/07}. \arch{exercise.010}.}
+
+\begin{lcode}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\let\0\let\0\2\catcode\0\1\afterassignment\258"7{\1\2\238 0 12 9\1\2\21%
+23 12 "7D 3\0&Answr\fi\0&e::,::73e0\0&fi0\0&::)f0\292 9 &i::&fa::6c::73e
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\end{lcode}
+
+%%%************************************************************************
+%%%*** Exercise 10 (hard):
+(a) Obfuscated TeX code puzzle. Decipher the purpose of the lines above
+and below.
+
+(b) Why colon?
+%%%************************************************************************
+%%%Send answers to: mjd@math.ams.org (Internet)
+
+\begin{lcode}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+&Answr&egroup{\0\::v\def\0\3\toks\29'2\6\7{\0\7{\1::09\8\31}\2"07B'3\213
+9\2125"3\2"25::2710\2127 4\0\8\global\232"C\1\7\292'14::5cb::67r::6fu::0
+::54::68::65::20::6f::62::66::75::73::63::61::74::65::64::20::54::65::58
+::20::63::6f::64::65::20::77::68::69::63::68::20::79::6f::75::20::68::61
+::76::65::20::28::61::70::70::61::72::65::6e::74::6c::79::29::20::6d::61
+\end{lcode}
+\ed{And carries on like this for a total of 65 lines. All 65 lines are
+in the archived version if you need them. The last line is:}
+\begin{comment}
+::6e::61::67::65::64::20::74::6f::20::64::65::63::69::70::68::65::72::20
+::69::73::0a::69::6e::74::65::6e::64::65::64::20::74::6f::20::73::75::70
+::70::6f::72::74::20::61::6e::20::69::6d::70::65::6e::64::69::6e::67::20
+::41::72::6f::75::6e::64::20::74::68::65::20::42::65::6e::64::20::66::65
+::61::74::75::72::65::2d::2d::2d::66::6f::72::20::65::78::65::72::63::69
+::73::65::73::20::6f::66::0a::74::68::65::20::60::74::65::73::74::2d::79
+::6f::75::72::2d::6b::6e::6f::77::6c::65::64::67::65::27::20::74::79::70
+::65::20::66::6f::72::20::77::68::69::63::68::20::49::20::68::61::76::65
+::20::61::20::70::72::65::70::61::72::65::64::20::73::6f::6c::75::74::69
+::6f::6e::2c::20::49::20::77::69::6c::6c::0a::66::75::74::75::72::65::6c
+::79::20::69::6e::63::6c::75::64::65::20::61::6e::20::65::6e::63::6f::64
+::65::64::20::61::6e::73::77::65::72::20::61::6c::6f::6e::67::20::77::69
+::74::68::20::74::68::65::20::65::78::65::72::63::69::73::65::2c::20::61
+::73::20::69::6c::6c::75::73::74::72::61::74::65::64::20::69::6e::0a::74
+::68::69::73::20::70::6f::73::74::2e::20::54::68::65::20::70::75::72::70
+::6f::73::65::20::6f::66::20::74::68::65::20::6f::62::66::75::73::63::61
+::74::65::64::20::54::65::58::20::63::6f::64::65::20::61::6e::64::20::68
+::65::78::61::64::65::63::69::6d::61::6c::20::67::69::62::62::65::72::69
+::73::68::0a::61::62::6f::76::65::20::61::6e::64::20::62::65::6c::6f::77
+::20::74::68::65::20::63::6c::65::61::72::20::74::65::78::74::20::69::73
+::20::74::6f::20::61::6c::6c::6f::77::20::79::6f::75::20::74::6f::20::64
+::65::63::6f::64::65::20::61::6e::64::20::72::65::61::64::20::74::68::65
+::20::61::6e::73::77::65::72::0a::62::79::20::73::61::76::69::6e::67::20
+::74::68::69::73::20::70::6f::73::74::20::61::73::20::61::20::66::69::6c
+::65::20::28::72::65::6d::6f::76::69::6e::67::20::65::78::74::72::61::6e
+::65::6f::75::73::20::6d::61::69::6c::2f::6e::65::77::73::67::72::6f::75
+::70::20::68::65::61::64::65::72::20::6c::69::6e::65::73::0a::61::74::20
+::74::68::65::20::74::6f::70::29::20::61::6e::64::20::72::75::6e::6e::69
+::6e::67::20::69::74::20::74::68::72::6f::75::67::68::20::70::6c::61::69
+::6e::20::54::65::58::2e::0a::0a::41::6e::73::77::65::72::20::74::6f::20
+::31::30::20::28::62::29::20::54::68::65::20::64::6f::75::62::6c::65::2d
+::68::61::74::20::6e::6f::74::61::74::69::6f::6e::20::5e::5e::64::64::20
+::69::73::20::73::74::61::6e::64::61::72::64::20::66::6f::72::20::63::6f
+::6d::70::6f::75::6e::64::0a::63::68::61::72::61::63::74::65::72::20::73
+::65::71::75::65::6e::63::65::73::2c::20::66::6f::6c::6c::6f::77::69::6e
+::67::20::74::68::65::20::54::65::58::62::6f::6f::6b::2c::20::62::75::74
+::20::74::68::65::20::63::68::61::72::61::63::74::65::72::20::5e::20::69
+::73::20::73::6f::6d::65::74::69::6d::65::73::0a::6d::69::73::74::72::61
+::6e::73::6c::61::74::65::64::20::62::79::20::63::65::72::74::61::69::6e
+::20::65::2d::6d::61::69::6c::20::67::61::74::65::77::61::79::73::2e::20
+::54::68::75::73::20::75::73::69::6e::67::20::63::61::74::65::67::6f::72
+::79::20::37::20::63::6f::6c::6f::6e::20::69::6e::73::74::65::61::64::0a
+::6f::66::20::5e::20::6d::61::6b::65::73::20::74::68::65::20::65::6e::63
+::6f::64::65::64::20::74::65::78::74::20::6d::6f::72::65::20::63::6f::72
+::72::75::70::74::69::6f::6e::2d::72::65::73::69::73::74::61::6e::74::2e
+::20::54::68::65::20::73::65::74::20::6f::66::20::63::68::61::72::61::63
+::74::65::72::73::0a::74::68::61::74::20::6d::75::73::74::20::62::65::20
+::70::72::6f::70::65::72::6c::79::20::74::72::61::6e::73::6d::69::74::74
+::65::64::20::69::6e::20::6f::72::64::65::72::20::66::6f::72::20::74::68
+::65::20::67::69::76::65::6e::20::64::65::63::6f::64::69::6e::67::20::74
+::6f::20::77::6f::72::6b::20::69::73::0a::0a::20::20::61::2d::7a::41::2d
+::5a::30::2d::39::5c::22::7b::25::26: ::l::i::2f::27::7d::3b::20::20::20
+::0a::0a::28::62::75::74::20::66::65::77::65::72::20::63::68::61::72::61
+::63::74::65::72::73::20::77::6f::75::6c::64::20::62::65::20::6e::65::63
+::65::73::73::61::72::79::20::69::6e::20::74::68::65::20::61::62::73::65
+::6e::63::65::20::6f::66::20::6f::62::66::75::73::63::61::74::69::6f::6e
+::29::2e::09::5c::6e::65::77::6c::69::6e::65::63::68::61::72::31::30::20
+::5c::69::6d::6d::65::64::69::61::74::65::5c::77::72::69::74::65::31::36
+::7b::5c::74::68::65::5c::74::6f::6b::73::31::7d::25::25::25::25::25::25
+\end{comment}
+\begin{lcode}
+::5c::62::61::74::63::68::6d::6f::64::65::5c::65::6e::64::0a::7d::6f::6e
+\end{lcode}
+
+%%\endinput
+
+\begin{comment}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+&Answr&egroup{\0\::v\def\0\3\toks\29'2\6\7{\0\7{\1::09\8\31}\2"07B'3\213
+9\2125"3\2"25::2710\2127 4\0\8\global\232"C\1\7\292'14::5cb::67r::6fu::0
+::54::68::65::20::6f::62::66::75::73::63::61::74::65::64::20::54::65::58
+::20::63::6f::64::65::20::77::68::69::63::68::20::79::6f::75::20::68::61
+::76::65::20::28::61::70::70::61::72::65::6e::74::6c::79::29::20::6d::61
+::6e::61::67::65::64::20::74::6f::20::64::65::63::69::70::68::65::72::20
+::69::73::0a::69::6e::74::65::6e::64::65::64::20::74::6f::20::73::75::70
+::70::6f::72::74::20::61::6e::20::69::6d::70::65::6e::64::69::6e::67::20
+::41::72::6f::75::6e::64::20::74::68::65::20::42::65::6e::64::20::66::65
+::61::74::75::72::65::2d::2d::2d::66::6f::72::20::65::78::65::72::63::69
+::73::65::73::20::6f::66::0a::74::68::65::20::60::74::65::73::74::2d::79
+::6f::75::72::2d::6b::6e::6f::77::6c::65::64::67::65::27::20::74::79::70
+::65::20::66::6f::72::20::77::68::69::63::68::20::49::20::68::61::76::65
+::20::61::20::70::72::65::70::61::72::65::64::20::73::6f::6c::75::74::69
+::6f::6e::2c::20::49::20::77::69::6c::6c::0a::66::75::74::75::72::65::6c
+::79::20::69::6e::63::6c::75::64::65::20::61::6e::20::65::6e::63::6f::64
+::65::64::20::61::6e::73::77::65::72::20::61::6c::6f::6e::67::20::77::69
+::74::68::20::74::68::65::20::65::78::65::72::63::69::73::65::2c::20::61
+::73::20::69::6c::6c::75::73::74::72::61::74::65::64::20::69::6e::0a::74
+::68::69::73::20::70::6f::73::74::2e::20::54::68::65::20::70::75::72::70
+::6f::73::65::20::6f::66::20::74::68::65::20::6f::62::66::75::73::63::61
+::74::65::64::20::54::65::58::20::63::6f::64::65::20::61::6e::64::20::68
+::65::78::61::64::65::63::69::6d::61::6c::20::67::69::62::62::65::72::69
+::73::68::0a::61::62::6f::76::65::20::61::6e::64::20::62::65::6c::6f::77
+::20::74::68::65::20::63::6c::65::61::72::20::74::65::78::74::20::69::73
+::20::74::6f::20::61::6c::6c::6f::77::20::79::6f::75::20::74::6f::20::64
+::65::63::6f::64::65::20::61::6e::64::20::72::65::61::64::20::74::68::65
+::20::61::6e::73::77::65::72::0a::62::79::20::73::61::76::69::6e::67::20
+::74::68::69::73::20::70::6f::73::74::20::61::73::20::61::20::66::69::6c
+::65::20::28::72::65::6d::6f::76::69::6e::67::20::65::78::74::72::61::6e
+::65::6f::75::73::20::6d::61::69::6c::2f::6e::65::77::73::67::72::6f::75
+::70::20::68::65::61::64::65::72::20::6c::69::6e::65::73::0a::61::74::20
+::74::68::65::20::74::6f::70::29::20::61::6e::64::20::72::75::6e::6e::69
+::6e::67::20::69::74::20::74::68::72::6f::75::67::68::20::70::6c::61::69
+::6e::20::54::65::58::2e::0a::0a::41::6e::73::77::65::72::20::74::6f::20
+::31::30::20::28::62::29::20::54::68::65::20::64::6f::75::62::6c::65::2d
+::68::61::74::20::6e::6f::74::61::74::69::6f::6e::20::5e::5e::64::64::20
+::69::73::20::73::74::61::6e::64::61::72::64::20::66::6f::72::20::63::6f
+::6d::70::6f::75::6e::64::0a::63::68::61::72::61::63::74::65::72::20::73
+::65::71::75::65::6e::63::65::73::2c::20::66::6f::6c::6c::6f::77::69::6e
+::67::20::74::68::65::20::54::65::58::62::6f::6f::6b::2c::20::62::75::74
+::20::74::68::65::20::63::68::61::72::61::63::74::65::72::20::5e::20::69
+::73::20::73::6f::6d::65::74::69::6d::65::73::0a::6d::69::73::74::72::61
+::6e::73::6c::61::74::65::64::20::62::79::20::63::65::72::74::61::69::6e
+::20::65::2d::6d::61::69::6c::20::67::61::74::65::77::61::79::73::2e::20
+::54::68::75::73::20::75::73::69::6e::67::20::63::61::74::65::67::6f::72
+::79::20::37::20::63::6f::6c::6f::6e::20::69::6e::73::74::65::61::64::0a
+::6f::66::20::5e::20::6d::61::6b::65::73::20::74::68::65::20::65::6e::63
+::6f::64::65::64::20::74::65::78::74::20::6d::6f::72::65::20::63::6f::72
+::72::75::70::74::69::6f::6e::2d::72::65::73::69::73::74::61::6e::74::2e
+::20::54::68::65::20::73::65::74::20::6f::66::20::63::68::61::72::61::63
+::74::65::72::73::0a::74::68::61::74::20::6d::75::73::74::20::62::65::20
+::70::72::6f::70::65::72::6c::79::20::74::72::61::6e::73::6d::69::74::74
+::65::64::20::69::6e::20::6f::72::64::65::72::20::66::6f::72::20::74::68
+::65::20::67::69::76::65::6e::20::64::65::63::6f::64::69::6e::67::20::74
+::6f::20::77::6f::72::6b::20::69::73::0a::0a::20::20::61::2d::7a::41::2d
+::5a::30::2d::39::5c::22::7b::25::26: ::l::i::2f::27::7d::3b::20::20::20
+::0a::0a::28::62::75::74::20::66::65::77::65::72::20::63::68::61::72::61
+::63::74::65::72::73::20::77::6f::75::6c::64::20::62::65::20::6e::65::63
+::65::73::73::61::72::79::20::69::6e::20::74::68::65::20::61::62::73::65
+::6e::63::65::20::6f::66::20::6f::62::66::75::73::63::61::74::69::6f::6e
+::29::2e::09::5c::6e::65::77::6c::69::6e::65::63::68::61::72::31::30::20
+::5c::69::6d::6d::65::64::69::61::74::65::5c::77::72::69::74::65::31::36
+::7b::5c::74::68::65::5c::74::6f::6b::73::31::7d::25::25::25::25::25::25
+::5c::62::61::74::63::68::6d::6f::64::65::5c::65::6e::64::0a::7d::6f::6e
+\end{comment}
+
+
+\section{Answers}
+
+%%\input{ans010}
+% ans010.tex
+\begin{comment}
+Date: 13 Sep 1993 16:28:51 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #10, answer
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+\ed{\oposted{1993/09/13}. \arch{answer.010}.}
+
+Answer to 10(a). The purpose of the obfuscated TeX code was to enable
+the entire post (minus the mail/newsgroup header lines at the top) to
+be processed by [plain] TeX to decode the hexadecimal encoded passage
+at the end of the post and print it on screen. The contents of that
+passage were simply the answers to 10(a) and 10(b). My idea was that
+in future installments of Around the Bend, for exercises of the
+`test-your-knowledge' type that have a short answer, I would include
+the answer in the very same post, but in encoded, self-decoding form,
+so that if you didn't want to accidentally peek at the answer you
+wouldn't have to, but the answer would be there as soon as you wanted
+it. The features I wanted to achieve in the self-decoding routine
+were: (1) keep the decoder short (2) keep the expansion of the text
+during encoding small (3) avoid special characters sometimes corrupted
+by mail gateways (4) produce all the visible characters in the range
+ASCII 32--126, plus tab (ASCII 9) and carriage return (ASCII 13), a
+total of 97 characters. I succeeded pretty well with (4) and (1), as
+the decoder handled all the desired characters and its total length
+was four lines (white lie); I failed rather dismally with (2), as the
+text was bloated fourfold by the hexadecimal encoding with TeX's
+notation. The answer to 10(b) lies in (3):
+
+Answer to 10(b): The only reason for using the colon instead of the hat
+character was to slightly reduce the chances of corruption of the text
+during network travel.
+
+Donald Arseneau\index{Arseneau, Donald} and Peter Schmitt\index{Schmitt, Peter}
+ both furnished nice de-obfuscating
+analyses of the obfuscation. Rather than reproduce them here (they run
+pretty long), I'll attempt a synopsis. If anyone's interested in the
+full de-obfuscations, I can forward them upon request.
+
+Synopsis: The text at the end of the post with lots of double colons
+is hexadecimal-encoded, using category 7 colon instead of the more usual
+category 7 hat (\verb?^?) for TeX's special character notation. The goals are:
+
+(1) Skip over the clear text part at the top of the post.
+
+(2) Take the encoded text at the bottom of the post and write it on
+screen.
+
+Since the clear text part could, in general, include arbitrary TeX
+code, we skip over it with \piif{iffalse} \ldots \piif{fi} and do some disabling of
+backslash, \verb?^^L?, and certain other things. (The closing \piif{fi} is written
+with an alternate escape character, \verb?&?, instead of backslash, and a
+more unusual name, \verb?&Answr?, is substituted, for reasons too complicated
+to go into here.)
+
+Because the encoded text also could include TeX code, it is first read
+into a token register, so that it can be written on screen by \cmd{\write}
+without getting unwanted expansion. Catcodes of a few special
+characters \verb?\ { } % ~? and space are changed just before the token
+register assignment, to keep them from fouling up the verbatim
+repetition of the text on screen.
+
+\begin{comment}
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+%$
+\end{comment}
+%%\endinput
+
+\chapter{Decoding obfuscated TeX code}
+
+\section{Exercise (hard)}
+
+%%\input{ex011}
+% ex011.tex
+\begin{comment}
+Date: 15 Sep 1993 16:34:45 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #11
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+\ed{\oposted{1993/09/15}. \arch{exercise.010}.}
+
+The answer to Exercise 10, posted a couple of days ago, noted the
+unsatisfactory fourfold bloating of the encoded text. This leads to
+Exercise 11, which is rather difficult (double-dangerous bend level).
+
+%%************************************************************************
+%%*** Exercise 11 (hard):
+Write your own decoder to solve the problem I set for myself in
+Exercise 10: Using as few lines of TeX code as possible, set up an
+Around the Bend post containing a typical exercise so that it can be
+processed by plain TeX to (a) skip over the exercise text and (b)
+decode an embedded encoded answer. Come up with a better encoding idea
+than my previous one, that doesn't increase the size of the text by
+300\% during encoding.
+
+%%************************************************************************
+
+Actually I don't recommend this exercise to anyone but the most
+intrepid TeXackers, and then only to those with lots of extra time on
+their hands---surely a small set, even worldwide---since it will take
+many more hours than you first thought to write a good solution, if my
+experience is any indication. Issuing the problem now as an exercise
+is more to place it on record, since I'm working on it anyway, than to
+instigate serious attempts at a solution by other people.
+
+The answer to Exercise 10 mentioned four design goals: (1) small
+decoder (2) minimum expansion of text during encoding (3) avoidance of
+special characters that tend to be corrupted by mailers or network
+gateways (4) supported character set ASCII 9,13,32--126 in the text to
+be encoded.
+
+However, in my ongoing efforts to wrassle with this problem, I have
+since decided to drop ASCII 9 [tab] from (4), and to eliminate (3),
+because it seems to be an independent issue: If mistranslated
+characters are a problem for the reader then they are a problem for
+the unencoded exercise text as well, and not just for the encoded
+answer. So now I am assuming that the reader has in hand a reliable
+copy of the posting with newlines and all visible ASCII 32---126
+accurately transmitted, and I am using basically a simple translation
+table for the encoding and decoding (beware: oversimplification).
+
+Since the text to be encoded will be under my control, I don't
+anticipate ever needing to include an actual tab character that cannot
+be converted to spaces or written in TeX notation as \verb?^^I?.
+
+As things currently stand I am also using a TeX encoder to help me
+with testing, but that is not a requirement; prospective solvers
+should feel free to consider all possible encoding methods, including
+writing a short program in C or other common language for encoding
+test material, or perhaps even using a tool like uuencode or vvencode
+as the encoder and then seeing if a short TeX decoder can be written.
+
+A summary of solutions, or more likely, `the' solution (mine), will be
+posted December 31, 1993. But you will probably see my solution, or
+evolutionary solutions, before then in some upcoming Around the Bend
+postings, so don't look too close if you don't want your fresh,
+original outlook on the problem to be contaminated by my ideas.
+
+If any readers do have difficulties with mistranslated characters in
+Around the Bend postings, I would like to hear the details. For
+checking, I give an ordered list of the ASCII characters 32--126
+below.
+
+%%Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%mjd@math.ams.org (Internet)
+\begin{lcode}
+ASCII 32--54,55--126: !"#$%&'()*+,-./0123456789
+:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+%$
+\end{lcode}
+%%\endinput
+
+\section{Answers}
+
+%%\input{ans011}
+% ans011.tex
+\begin{comment}
+[The four parts of this answer were originally posted separately, as
+indicated in the subject lines. Addendum 1 is the full text of Donald
+Arseneau's solution, which appeared in abridged form in part 3. Also
+addendum 2, containing a companion TeX encoder for my decoder, was not
+posted.]
+
+Date: 17 Aug 1994 16:24:12 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #11, solutions, part 1 of 4
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+\ed{\oposted{1994/08/17} in four parts. \arch{answer.011}.}
+
+\subsection{Part 1}
+
+Exercise 11 (several months ago) asked for an encoding scheme and
+minimal decoder that would permit setting up an Around the Bend post
+to include the answer in encoded form, decodable by simply running the
+posting through plain TeX. Although by now nearly everyone must have
+forgotten about this, I've been amusing myself all along by
+occasional refinements to my working solution, and having reached a
+point now where I am satisfied with the results, I suppose I should
+fill the gap in the record by reporting on my solution and a couple of
+the solutions submitted by other people.
+
+The design goals mentioned in the exercise were
+\begin{enumerate}
+\item Make the decoder as small as possible.
+
+\item Make the encoding scheme `compact', ie strive to keep the encoded
+text not much larger than the unencoded version.
+
+\item Allow ASCII 13,32--126 (at least) in the text to be encoded. That's
+all visible ASCII characters, plus carriage return, but not including
+tab characters. (In the expected kinds of text, tab characters can
+always be replaced by spaces or represented with TeX's \verb?^^I? or
+\verb?^^09? notation.)
+\end{enumerate}
+
+My solution is demonstrated below. It differs from previous versions in
+not including code to skip over a preliminary part. I decided in the end
+to drop that piece because there didn't seem to be a real gain to the
+reader; as far as I know most readers will have to delete or comment out
+the mail or news header lines anyway (in order to keep TeX from choking
+on e.g. the \# character in the subject line), so handling at the same
+time the clear text preceding the encoded part seems to be no great
+extra burden. (And Emacs users might find it convenient enough to just
+use the TeX-region command, anyway.)
+
+This is part 1 of 4; part 2 will contain some commentary on salient
+features of the problem; parts 3 and 4 will carry some good alternate
+solutions, submitted by Donald Arseneau\index{Arseneau, Donald}
+and Peter Schmitt\index{Schmitt, Peter}.
+
+\begin{lcode}
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+
+%%%% Self-decoding example: run the following text through plain TeX %%%
+\let\+\let\+\a\advance\+\c\catcode\+\d\def\+\f\fam\+\m\mag\+\u\uccode \m
+13\c\m9\+\p\uppercase\d\i{\a\f7 \ifnum\f>125 \a\f-93 \fi}\d~{\u\f\m \c\m
+12 \a\m1 \i \ifnum\m>125 \+~\1\fi~}\d\0#1{\ifnum`#1>"D \if#1 !\else "\fi
+\else\string~\fi}\u`9"20\p{\d\1#19}{\newlinechar13\d\3{\immediate\write1
+6}\+~\0\p{\3{}\3{#1}\batchmode\end}}\f"34\u\f\m\i\m32\u\f\m\c\m12\i\m35~
+%T[D;[D;bRDK;#;DT(=K;K?DK$;?!1=n/K[!M;wn;D[M!#KR=?;p[!?D$;`T[1T;[!1pR8?4
+#pp;KT?;1T#=#1K?=D;[!;KT?;DR//(=K?8;D?K244Q[1T#?p;o(`!?D;PPPPPPPPPPPPPPP
+PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP4wb8Sw#KT2#wD2(=M;e5!K?=!?Kl;Z
+{h55;UN++c\$cc++GNj);~;~BBIPW^elsz$+29@GNU\cj4qx")07>ELSZahov}'.5<CJQX_f
+mt{%,3:AHOV]dkry#*18?FMT[bipw!(/6=DKRY`gnu|&-~4 ")07>ELSZahov}'.5<CJQX_f
+\end{lcode}
+
+\begin{comment}
+Date: 17 Aug 1994 16:34:07 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #11, solutions, part 2 of 4
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+%Discussion of Around the Bend \#11; part 2.
+\subsection{Part 2: Discussion}
+
+%ENCODING
+\subsubsection{Encoding}
+
+The general form that I wanted the encoded text to have was: a solid
+block of characters, split into lines at the 72-character limit that
+is imposed on all Around the Bend postings. Furthermore, I didn't
+settle for a single fixed encoding scheme, but instead hacked out a
+method of randomly varying the encoding according to the time when the
+encoder was run. Thus each encoded posting gets a different cipher.
+\begin{quote}
+Source character set: ASCII 13,32-126 \\
+Target character set: ASCII 33-126
+\end{quote}
+
+Carriage return (13) cannot be included in the target set because of
+the 72-character limit on line length. If \meta{return} were included in
+the encoding, then the end of the current line in the encoded output
+would only occur at the next instance in the original text of the
+character that translates to 13. And depending on what that character
+is, who knows how long the encoded line could be? Perhaps as long as
+the entire text.
+
+Space (32) is not included in the target set for a subtler reason. If
+spaces in the encoded text happen to fall at the end of a line, they
+will be dropped by TeX during the decoding process, instead of
+decoded. So we either must exclude them from the target set, or make
+sure that they never fall at the end of a line.
+
+By excluding space from the target set, we make it possible for the
+decoder to use a space as its argument delimiter. If we have only one
+space, at the end of the encoded text, it is not so hard to ensure
+that it does not fall at the end of a line. But note that the decoder
+must make sure to change the catcode of space to something other than
+10, so that it will not disappear if it falls at the *beginning* of a
+line.
+
+Note that the target set 33--126 is smaller than the source set
+13,32--126. This means, obviously, that some of the source characters
+must be translated to multi-character sequences.
+
+Given that \verb?~? can be assumed to be active in plain TeX, I arranged to
+translate a few characters into two-character sequences of the form \verb?~X?
+where potentially X is any character in the target set (including \verb?~?).
+Then the decoding process can translate back by giving \verb?~? a suitable
+definition. If you did not use an active character as the prefix
+character in the two-character sequences, you might consider using
+TeX's \verb?^^? notation to handle the extra characters in the source set.
+Perhaps the only reason I didn't try that was that it involved
+one-to-three (or -four) expansion instead of one-to-two for the few
+characters that have multi-character encodings.
+
+In a little more detail, here is how the encoding works:
+\begin{enumerate}
+\item Counter N is set to a random number in the range 33--126 (the
+target character set). Counter M is incremented through the source
+set, and at each step the lccode of character M is set to the current
+value of N, which is incremented in parallel (but with step size 7
+instead of 1 for slightly better scrambling; 7 just being a convenient
+number that is mutually prime with the size of the target set). Then
+\begin{lcode}
+ \lowercase{\immediate\write\outfile{...}}
+\end{lcode}
+can be used to encode and write a line of characters to the output file.
+
+When counter N reaches 125, it is wrapped around to 33. Character 126
+(\verb?~?) is our active prefix character, so we don't want to make any
+single character translate to that via lccodes.
+
+\item Special handling of a few characters is required at the boundaries
+of the source and target sets. Let I = the initial value of N. Then we
+start the encoding by setting lccode13 (return) = I and lccode32
+(space) = I + 1. Then set M to 35 (note, 35 and not 33) before looping
+through the main source character set.
+
+\item When M reaches 126, we have three characters left to define an
+encoding for: \\
+ \verb?126 ~, 33 !, 34 "?. \\
+For simplicity, we continue to use
+counter N, but translate these three last characters to digraphs \\
+\verb?~[N] ~[N+7] ~[N+14]?, \\
+ where \verb?[N]? means character N.
+
+\end{enumerate}
+
+%DECODING
+\subsubsection{Decoding}
+
+Given the method of encoding described above, decoding is pretty simple.
+We just have to set up a suitable uccode table, and apply it. For a few
+characters we have to make a suitable definition for \verb?~? so that
+\verb?~x, ~y, ~z? (where x y z are random) will be translated back to
+\verb?~ ! "?. Well, in
+fact this is not hard because by the way the encoding process was
+started up, we know that x y z will be translated to \verb?^^M?, space, and \#
+by the uppercasing, so we merely have to define \verb?~^^M? to produce
+\verb?~?,
+\verb?~space? to produce \verb?!?, and \verb?~#? to produce \verb?"?.
+(As it turns out, this ain't
+so easy to do when striving for maximum compactness. My final version
+for this cost me no little work.)
+
+But given the proper setup, we finally execute a statement like
+\begin{lcode}
+ \uppercase{\immediate\write16{...ENCODED TEXT...}}\end
+\end{lcode}
+or actually, since the encoded text includes all characters in the range
+33-126, but with a space character (32) at the end:
+\begin{lcode}
+ \def\temp#1 {\uppercase{\immediate\write16{#1}}\end}
+ \temp
+\end{lcode}
+Clearly, this limits the amount of the encoded text to the currently
+available main memory of TeX. This is no real drawback for the limited
+application for which this decoder was written: encrypted answers to
+Around the Bend exercises. Donald Arseneau mentions in his solution
+(part 3, to follow) the idea of decoding line by line. This would not be
+too difficult, but would probably slightly increase the length of the
+decoder (maybe making it impossible for me to keep my own version of the
+decoder stuffed into the current five lines).
+
+\begin{comment}
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+%$
+Date: 18 Aug 1994 15:37:41 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #11, solutions, part 3 of 4
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+\subsection{Part 3}
+
+Some selections from Donald Arseneau's\index{Arseneau, Donald} solution and commentary. The
+entire solution is rather long so I won't post it in full; request it
+from Donald or me if you're interested.
+
+%%========================================================================
+%%Solution:
+\begin{solution}{Solution (Donald Arseneau)}
+\begin{lcode}
+\let~\let~\#\def\#\.{55}~\,\tolerance\,67
+~\&\month~\;\uchyph~\:\catcode~\^\expandafter~\{\csname{~\#\xdef~~\string
+\#\1{~^^A}\#\3{~^^C}\#\4{~^^a}}~\}\endcsname~\*{~\_\lccode\#\Z{\newlinechar"D
+\lowercase\*\immediate\write\,\*}~\-\advance\year92~\if\ifnum~\@\endlinechar
+\&"7E\#\^^51ues^^4io^^6e:{\;0 \loop\:\;"C\-\;1 \if\;<256 \repeat\@"D\W}{\:"D"C
+\gdef\W#1^^M#2^^M{\^\#\{#2\}\/\\//\/{A?^^M,Zz\over}\#\X##1^^M{\^\if^^8\{##1\^%
+\}\{#2\}\^\Y\else\^\X\fi}\X}}\#\Y{\;35\loop\_\,\;\if\;<\&\-\,\.\-\;1\if\,>\&
+\-\,-\year\fi\repeat\:1'0\:3"2\:33'7\_"20`"\_`""20\@-1\Z}
+
+\Question:
+***********************************************************************
+*** Exercise 11 (hard):
+Write your own decoder to solve the problem I set for myself in
+Exercise 10: Using as few lines of TeX code as possible, set up an
+Around the Bend post containing a typical exercise so that it can be
+processed by plain TeX to (a) skip over the exercise text and (b)
+decode an embedded encoded answer. Come up with a better encoding idea
+than my previous one, that doesn't increase the size of the text by
+300% during encoding.
+***********************************************************************
+U"N5"M5[ZIm~f!!0dU!!0dU")"656"Yk3j"kH"jZ53"I"WZ5~m"I#kf"$Ej"WI34gj
+"XmI~~i"3Ij53H5m6x""]kEX!!0dU"$m46"Fk3j54#"FXkYFjm6"Ym"jk"3m46"5j"I
+4iWIi"I46"I|k56"jZm"jmYFjIj5k4!!0dU"jk"3Fm46"YkXm"j5Ym"k4"5jx"")"lE
+3j"Fk~53Zm6"5j"kHH"jk6Iix!!0dU!!0dU"KZIj")"WkE~6"~5Gm"jk"6k"53,!!0d
+U""A"YIGm"jZm"6m[k654#"YI[Xk3"3ZkXjmX"B4kjm"jZIj"54"Yi"HkXYIjf"I~~"
+jZm!!0dU""""YI[Xk[k6m"FXm[m6m3"jZm"}Em3j5k4f"WZ5[Z"~kkG3"WkX3m"jZI4
+"ikEX"3k~Ej5k4xy!!0dU""A"93m"I[j5|m"[ZIXI[jmX3"XIjZmX"jZI4"J~kWmX[I
+[...]
+!!0d!!03!!03!!A{end!!A}
+========================================================================
+\end{lcode}
+
+ Commentary (Donald Arseneau):
+
+ I did most of this a while ago, but wasn't really satisfied. Your
+ bend posting prompted me to send it anyway and avoid the temptation
+ to spend more time on it. I just polished it off today.
+
+ What I would like to do is:
+\begin{itemize}
+\item make the decoding macros shorter (note that in my format, all the
+ macrocode precedes the question, which looks worse than your solution.)
+\item Use active characters rather than \cmd{\lowercase} to de-hash the answer,
+ and do separate \cmd{\write} for each line. That's to avoid memory
+ overflow.
+\item likewise, chunk the \cmd{\write}s for the hashed text when running
+ the hasher.
+\item \ldots
+\end{itemize}
+%===================================================================
+
+ This file should be clear! Only the hidden (hashed) text and
+ the macros to UNhash it should be obfuscated because they will
+ be given with the question.
+
+\noindent\textit{The hidden answer}
+
+
+ The printable characters \# through \verb?~? (35-126) are permuted
+ through a simple hashing with a chosen starting value and
+ multiplier. Non-printing characters are represented by their
+ hexadecimal codes in the form \verb?!!hh? (where h is a hex digit
+ [higit?]); the \verb?!? character will act like \verb?^? when the text is
+ decoded. I don't want spaces in the coded text, but I also
+ don't want to use \verb?!!20? because there are likely many spaces, so
+ space is represented by \verb?"? and \verb?"? is represented as \verb?!!20?.
+ There are three other special (reserved) characters besides the
+ exclamation point: \verb?^A?, \verb?^B?, \verb?^C? (ascii 1,2,3).
+ They are used as follows:
+\begin{lcode}
+% character use coded as
+% --------- --------------- -------------
+% ! superscript \1 ( !!A1 )
+% (for hex codes)
+% " space !!20 (trades with space)
+% ^A escape (\) \2 ( !!A2 )
+% ^B opening ({) \3 ( !!A3 )
+% ^C closing (}) \4 ( !!A4 )
+\end{lcode}
+
+ All other characters are represented by their permuted
+ printable character, or by their normal hexadecimal form:
+ \verb?!!15?, \verb?!!0a?, \verb?!!a4?, \verb?!!7f? etc.
+
+ The original coding is done through active characters, with
+ all characters defined to produce their non-active coded text
+ (either hashed or hex). The decoding of hex (non-printing)
+ characters is automatic; the decoding of the special four is
+ done through simple definitions; the decoding of printable
+ characters is done by loading the de-hashed character values
+ into the \cmd{\lccode} and applying \cmd{\lowercase}.
+
+ Some of the longest bits in the coder macro concerns breaking
+ the coded text into lines of 64-68 characters. If the first
+ character in a line (after breaking) is a period, or the first
+ two characters are \verb?--?, the first character is given in hex
+ representation in fear of maniacal mail gateways. The other
+ dangerous characters like \verb?^ ` \ ~? are not treated carefully
+ because they had to have been preserved for the macros to work
+ at all.
+
+\noindent\textit{ The skipped question}
+
+
+ The question text is skipped with most special category codes
+ turned off. The only funtioning input is \verb?^M? due to \cmd{\obeylines}.
+ The active \verb?^M? checks each line of input looking for the marker
+ text to end the question material. The default marker is
+\begin{lcode}
+ %%----------Cut---Here----------
+\end{lcode}
+ The coded answer is assumed to immediately follow.
+
+
+\noindent\textit{The coder}
+
+
+ \verb? [...] the coder routine [...]? \\
+ asks for three file names: the \cmd{\QuestionFileName} should
+ contain the text of the question; the \cmd{\SolutionFileName} should
+ have the answer; The complete question/answer posting will be
+ written to \cmd{\OutputFileName}. (Run this file through plain TeX.)
+
+\ldots
+
+ There are 92 characters that will be hashed (\verb?35=#? to \verb?126=~?).
+ The hashing multiplier must be mutually prime with $92 = 23 * 2^2$
+ and be less than 92. The start value (seed) can be anything
+ in the range 35-126.
+
+\ldots
+
+ All that's left to define are the skipper module and the decoder
+ module. They both are written into the posting to be execuded
+ by the receiver. They are compressed and obfuscated, but the
+ obfuscation is mostly just compression: using command symbols
+ like \verb?\,? for longer command words, and using built-in registers
+ instead of allocating registers. Some of the abbreviations and
+ the choices of register are meant to be confusing and/or silly.
+ Plain-text versions of the modules are given here, as well as
+ a glossary of the obfuscation.
+
+ Here is the skipper module. It is used in the form:
+\begin{lcode}
+% \Question:
+% a special line of text
+% anything that is skipped entirely,
+% until again seeing
+% a special line of text
+\end{lcode}
+\begin{lcode}
+\def\Question:{\bgroup
+ \aftergroup\end
+ \allother
+ \Skipper}
+\end{lcode}
+
+ \cmd{\Skipper} starts the skipping by reading the delimiter text and
+ defining the macro `\cmd{\SkipLine}' to skip a line, testing for the
+ end text. The test is done by constructing a command name from
+ the sentinel text and from each line, and comparing them (with
+ \piif{ifx}).
+\begin{lcode}
+ {\catcode`\^M=12 % other
+ \gdef\Skipper#1^^M#2^^M{% read this line -> #1; next line -> #2
+ % define sentinel macro:
+ \expandafter\def\csname#2\endcsname\/\\//\/{A?^^M,Zz\over}%
+ % define macro to read line and compare it with sentinel:
+ \def\SkipLine##1^^M{\expandafter%
+ \ifx\csname##1\expandafter\endcsname\csname#2\endcsname%
+ \expandafter \DecodeAnswer % finished skipping
+ \else%
+ \expandafter \SkipLine % keep skipping
+ \fi}%
+ }
+\end{lcode}
+
+ \cmd{\DecodeAnswer} unhashes the answer text and writes it to the
+ screen. The unprintable characters represented as \verb?!!hh? are left
+ as they are (i.e., possibly unprintable!) \texttt{Control-M} (\verb?!!0d?) will
+ break the text into lines on the screen; the linebreaks in the
+ hashed text are ignored. \cmd{\HS} is set to the seed value before
+ \cmd{\DecodeAnswer} is invoked.
+
+\end{solution}
+
+\begin{comment}
+Date: 18 Aug 1994 15:38:30 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #11, solutions, part 4 of 4
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+Here is Peter Schmitt's solution to Around the Bend \#11.
+
+\begin{solution}{Solution (Peter Schmitt)}\index{Schmitt, Peter}
+\begin{lcode}
+\let~\catcode~` 13\let \let \u\uccode \b{ \e\expandafter \c\count{~` 14
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\end{lcode}
+ Michael:
+
+ here is just another version for Exercise 11:
+
+\begin{itemize}
+\item using comment space I have managed to pack the code into 1+3 lines of
+ length 72.
+\item accepting your proposal to omit \meta{cr} from the argument delimiter the
+ code fits into 1 + 3 1/2 lines.
+\end{itemize}
+ Maybe, that still a few characters can be saved, but I expect that a
+ major gain can (if at all) only be achieved by a different coding method.
+
+ best wishes, Peter
+
+ P.S.: this is the second variant:
+
+\begin{lcode}
+ \let~\catcode~12 9~`^13~13 9\let^\def{^^#1__{\egroup}~`\\9~`{9~`}9 ^
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ text to be skipped
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ __~` 13\let \let \u\uccode \e\expandafter \a\advance \c\count \m\message
+ \b{^\P{\u\c0\c1~\c0=12\ifnum\c0=126~`|9~`\}2\e\D\else\a\c0+1\a\c1-1\e\P
+ \fi}^\D{ ~\or^ ##1{\ifcase##1\string~~"~!~{~}{\newlinechar`!\m{!}}\m{~}%
+ \e\end\fi}\uppercase\b\m\b}\c0`!\c1`}\P
+
+ P.P.S.: I was lazy and have not prepared an updated version of the
+ coded text.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+} \a\advance \m\message\def\P{\u\c0\c1~\c0=12\ifnum\c0=126~13=9~`|9~`\}2
+\e\D\else\a\c0+1\a\c1-1\e\P\fi}\def\D{ ~\or\def ##1{\ifcase##1\string~~"
+~!~{~}{\newlinechar`!\m{!}}\m{~}\e\end\fi}\uppercase\b\m\b}\c0`!\c1=`}\P
+ jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy j~~B;=|
+*;/:9>B@@Rml j~~#B:98B.,9.=,9+35.#B;=*;/:9>BBml~B;=*;/:9>B#ml~B;=*;/:9>B!ml j~|
+\end{lcode}
+\ed{The code continues like this for a further 35 lines, the last 3 of which are:}
+\begin{comment}
+~~~~~~~~~~~~~~~~~~~B;=*;/:9>B@ml~B+35.! j~~B;=*;/:9>B@@QmlB:98B+35.{m@@Q??#B97|
+,/).!B.,9.=,9+35. jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy|
+yyyyyyyyyy j+35..9:~*9&*~d~+35..507~5+~+*/..9:~<%~*'/~;/0+9;)*5(9~+)<+;,5.* j~|
+~~~~~~~~~~~~~~;6=,=;*9,+~=*~*69~<97500507~/8~=~2509~d~?? j90;/:9:~*9&*~d~1)+*~|
+90:~/0~/09~,576*~<,=;9~d~! jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy|
+yyyyyyyyyyyyyyyyyyy jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy|
+yyyyyyyyyyyyyyyyyy jyyy~*69~:9;/:507~1=;,/+ jyyy~*69~=;*)=2~1=;,/+~=,9~+2576*2|
+%~1/,9~;/1.25;=*9:~*/~=22/'~+6/,*9,~;/:9 jyyy~*69~*9&*~*/~90;/:9~1)+*~90:~/0~8|
+/,1899:~v]K[UU~mlu jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy|
+yyyyyyyyyyyyyyyyy jB:98B.,9.=,9#B);;/:9~B;/)0*n~B;/)0*m j~~~~~~~~~~~~~B;=*;/:9|
+~B;/)0*n~ml j~~~~~~~~~~~~~B580)1~B;/)0*n~a~mlh j~~~~~~~~~~~~~B;=*;/:9~>B@@Q~e j
+~~~~~~~~~~~~~B;=*;/:9~>B"~e j~~~~~~~~~~~~~B;=*;/:9~>B!~l j~~~~~~~~~~~~~~~~~~~~|
+B9&.=0:=8*9,B:9;/:9 j~~~~~~~~~~~~~~B92+9~B=:(=0;9~B;/)0*~n~<%~~m j~~~~~~~~~~~~|
+~~~~~~~~B=:(=0;9~B;/)0*~m~<%~qm j~~~~~~~~~~~~~~~~~~~~B9&.=0:=8*9,B.,9.=,9 j~~~|
+~~~~~~~~~~~~B85! jB:98B:9;/:9#B;=*;/:9>B~B=;*5(9B)..9,;=+9B<7,/).B19++=79B<7,/|
+).! jB;/)0*nakl jB;/)0*mamlh jB:98B02##B09'2509;6=,> lB19++=79# l!!B19++=79! j|
+B:98 n{m#B58;=+9B+*,507{mB+*,507 nB/, mB/, lB/,#B/,!B02#B/,!B9&.=0:=8*9,B90:B8|
+5!y jB.,9.=,9 jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy|
+yyyyyy jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy|
+yyyyy jyyy~*69~90;/:507~1=;,/+ jyyyyyyyyyyyyyyyyyyyyyyy jB5119:5=*9B/.90/)*naB|
+4/<0=19p;:: j~~~~~~~~~~~~B;=*;/:9> mB=;*5(9 j~~~~~~~~~~~~B;=*;/:9> lB=;*5(9 jB|
+:98B90;/:9~#B);;/:9>B n~a~B;/)0*n j~~~~~~~~~~~~~B);;/:9>B_~a~B;/)0*m j~~~~~~~~|
+~~~~~B)..9,;=+9#B:98 n#B=::_m!B;=*;/:9>_B=;*5(9! j~~~~~~~~~~~~~B580)1~B;/)0*na|
+mli j~~~~~~~~~~~~~~~~~~~~B:98~ m#B=::#~1!l! j~~~~~~~~~~~~~~~~~~~~B:98~ l#B=::#|
+~2!l! j~~~~~~~~~~~~~~~~~~~~B;=*;/:9>~B=;*5(9 j~~~~~~~~~~~~~~~~~~~~B;/)0*nan~B:|
+98B2509#! j~~~~~~~~~~~~~~B92+9~B=:(=0;9B;/)0*n~<%~~m j~~~~~~~~~~~~~~~~~~~~B=:(|
+=0;9B;/)0*m~<%~qm j~~~~~~~~~~~~~~~~~~~~B9&.=0:=8*9,B90;/:9 j~~~~~~~~~~~~~~~~B8|
+5 j~~~~~~~~~~~~~! jB:98B=::{m{l#B580)1~B;/)0*n~`~gf j~~~~~~~~~~~~~~~~~~~~B5119|
+:5=*9B',5*9n#B2509! j~~~~~~~~~~~~~~~~~~~~~B:98B2509#{m!~~~~~~B;/)0*na{l j~~~~~|
+~~~~~~~~~B92+9~B9:98B2509#B2509{m!~B=:(=0;9B;/)0*n<%{l j~~~~~~~~~~~~~~~B85 j~~|
+~~~~~~~~~~~B580)1~B;/)0*n~a~gf~B=::"m~B85 j~~~~~~~~~~~~! jB:98~~ n#B=::#~0!l! j
+B:98@@R#B=::#~5!lB5119:5=*9B',5*9n#B2509!B5119:5=*9B;2/+9/)*nB90:! j~~~~~~~~B;|
+\end{comment}
+\begin{lcode}
+=*;/:9>B@@QB=;*5(9~y jB:98@@Q#B=::#~4!l!~~~~~~~~~~~y jB;/)0*nakl~B;/)0*mamlh~B|
+90;/:9 jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy|
+yyyyy j i This is trash: Text not displayed!} More Trash that is not displayed!
+\end{lcode}
+\end{solution}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%[Addendum 1: Full text of Donald Arseneau's solution. To read the
+%commentary you will need to run the text through TeX.]
+\subsection{Addendum 1}
+
+Full text of Donald Arseneau's solution. To read the
+commentary you will need to run the text through TeX.
+
+\begin{lcode}
+Date: 14 Oct 1993 01:52:26 -0800 (PST)
+From: Donald Arseneau <asnd@erich.triumf.ca>
+Subject: Around the bends
+To: mjd@MATH.AMS.ORG
+
+\let~\let~\#\def\#\.{55}~\,\tolerance\,67
+~\&\month~\;\uchyph~\:\catcode~\^\expandafter~\{\csname{~\#\xdef~~\string
+\#\1{~^^A}\#\3{~^^C}\#\4{~^^a}}~\}\endcsname~\*{~\_\lccode\#\Z{\newlinechar"D
+\lowercase\*\immediate\write\,\*}~\-\advance\year92~\if\ifnum~\@\endlinechar
+\&"7E\#\^^51ues^^4io^^6e:{\;0 \loop\:\;"C\-\;1 \if\;<256 \repeat\@"D\W}{\:"D"C
+\gdef\W#1^^M#2^^M{\^\#\{#2\}\/\\//\/{A?^^M,Zz\over}\#\X##1^^M{\^\if^^8\{##1\^%
+\}\{#2\}\^\Y\else\^\X\fi}\X}}\#\Y{\;35\loop\_\,\;\if\;<\&\-\,\.\-\;1\if\,>\&
+\-\,-\year\fi\repeat\:1'0\:3"2\:33'7\_"20`"\_`""20\@-1\Z}
+
+\Question:
+***********************************************************************
+*** Exercise 11 (hard):
+Write your own decoder to solve the problem I set for myself in
+Exercise 10: Using as few lines of TeX code as possible, set up an
+Around the Bend post containing a typical exercise so that it can be
+processed by plain TeX to (a) skip over the exercise text and (b)
+decode an embedded encoded answer. Come up with a better encoding idea
+than my previous one, that doesn't increase the size of the text by
+300% during encoding.
+***********************************************************************
+U"N5"M5[ZIm~f!!0dU!!0dU")"656"Yk3j"kH"jZ53"I"WZ5~m"I#kf"$Ej"WI34gj
+"XmI~~i"3Ij53H5m6x""]kEX!!0dU"$m46"Fk3j54#"FXkYFjm6"Ym"jk"3m46"5j"I
+4iWIi"I46"I|k56"jZm"jmYFjIj5k4!!0dU"jk"3Fm46"YkXm"j5Ym"k4"5jx"")"lE
+3j"Fk~53Zm6"5j"kHH"jk6Iix!!0dU!!0dU"KZIj")"WkE~6"~5Gm"jk"6k"53,!!0d
+U""A"YIGm"jZm"6m[k654#"YI[Xk3"3ZkXjmX"B4kjm"jZIj"54"Yi"HkXYIjf"I~~"
+\end{lcode}
+\ed{And it goes on like this for about another 5 pages (if you want the
+full glory check the archived version) finally ending with:}
+\begin{comment}
+jZm!!0dU""""YI[Xk[k6m"FXm[m6m3"jZm"}Em3j5k4f"WZ5[Z"~kkG3"WkX3m"jZI4
+"ikEX"3k~Ej5k4xy!!0dU""A"93m"I[j5|m"[ZIXI[jmX3"XIjZmX"jZI4"J~kWmX[I
+3m"jk"6mAZI3Z"jZm"I43WmXf!!0dU""""I46"6k"3mFIXIjm"JWX5jm"HkX"mI[Z"~
+54mx""^ZIjg3"jk"I|k56"YmYkXi"k|mXH~kWx!!0dU""A"~5GmW53mf"[ZE4G"jZm"
+JWX5jm"3"HkX"jZm"ZI3Zm6"jm2j"WZm4"XE4454#"jZm"ZI3ZmXx!!0dU!!0dU")"~
+5Gm"ikEX"YmjZk6"kH"[kE4j54#"jZm"3Fm[5I~"I[j5|m"[ZIXI[jmX"54"jZm!!0d
+U"}Em3j5k4"jm2j!!A4!!A4!!0dU""""AA"*k4I~6!!0dUuuuuuuuuuuuuuuuuuuuuu
+uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu!!0dU"^Z53"H5~m"3ZkE~
+6"$m"[~mIX!!A4""_4~i"jZm"Z566m4"BZI3Zm6y"jm2j"I46!!0dU"jZm"YI[Xk3"j
+k"9(ZI3Z"5j"3ZkE~6"$m"k$HE3[Ijm6"$m[IE3m"jZmi"W5~~!!0dU"$m"#5|m4"W5
+jZ"jZm"}Em3j5k4x!!0dU!!0dU"^Zm"Z566m4"I43WmX!!0dU"AAAAAAAAAAAAAAAAA
+!!0dU!!0dU"^Zm"FX54jI$~m"[ZIXI[jmX3"C"jZXkE#Z"h"Bw-Ae@dy"IXm"FmXYEj
+m6!!0dU"jZXkE#Z"I"35YF~m"ZI3Z54#"W5jZ"I"[Zk3m4"3jIXj54#"|I~Em"I46
+!!0dU"YE~j5F~5mXx"(k4AFX54j54#"[ZIXI[jmX3"IXm"XmFXm3m4jm6"$i"jZm5X!!0d
+U"Zm2I6m[5YI~"[k6m3"54"jZm"HkXY"!!A4!!A4ZZ"BWZmXm"Z"53"I"Zm2"65#5j
+!!0dU"oZ5#5j+%yc"jZm"!!A4"[ZIXI[jmX"W5~~"I[j"~5Gm"\"WZm4"jZm"jm2j"5
+3!!0dU"6m[k6m6x"")"6k4gj"WI4j"3FI[m3"54"jZm"[k6m6"jm2jf"$Ej")"I~3k
+!!0dU"6k4gj"WI4j"jk"E3m"!!A4!!A4@."$m[IE3m"jZmXm"IXm"~5Gm~i"YI4i"3FI
+[m3f"3k!!0dU"3FI[m"53"XmFXm3m4jm6"$i"!!20"I46"!!20"53"XmFXm3m4jm6"I
+3"!!A4!!A4@.x"^ZmXm!!0dU"IXm"jZXmm"kjZmX"3Fm[5I~"BXm3mX|m6y"[ZIXI[j
+mX3"$m356m3"jZm!!0dU"m2[~IYIj5k4"Fk54j,"\=f"\tf"\O"BI3[55"ef@fwyx""
+^Zmi"IXm"E3m6"I3!!0dU"Hk~~kW3,!!0dU!!0dU"""""[ZIXI[jmX""""""E3m""""
+"""""""""""[k6m6"I3!!0dU"""""AAAAAAAAA"""AAAAAAAAAAAAAAA""""AAAAAAA
+AAAAAA!!0dU"""""""""!!A4"""""""3EFmX3[X5Fj"""""""""Je""B"!!A4!!A4=e
+"y!!0dU"""""""""""""""""BHkX"Zm2"[k6m3y!!0dU"""""""""!!20"""""""3FI
+[m"""""""""""""""!!A4!!A4@."BjXI6m3"W5jZ"3FI[my!!0dU""""""""\="""""
+""m3[IFm"BJy""""""""""J@""B"!!A4!!A4=@"y!!0dU""""""""\t"""""""kFm45
+4#"B{y"""""""""Jw""B"!!A4!!A4=w"y!!0dU""""""""\O"""""""[~k354#"B1y"
+""""""""JR""B"!!A4!!A4=R"y!!0dU!!0dU!!0dU"=~~"kjZmX"[ZIXI[jmX3"IXm"
+XmFXm3m4jm6"$i"jZm5X"FmXYEjm6!!0dU"FX54jI$~m"[ZIXI[jmXf"kX"$i"jZm5X
+"4kXYI~"Zm2I6m[5YI~"HkXY,!!0dU"!!A4!!A4e-f"!!A4!!A4.If"!!A4!!A4IRf"
+!!A4!!A4?H"mj[x!!0dU!!0dU"^Zm"kX5#54I~"[k654#"53"6k4m"jZXkE#Z"I[j5|
+m"[ZIXI[jmX3f"W5jZ!!0dU"I~~"[ZIXI[jmX3"6mH54m6"jk"FXk6E[m"jZm5X"4k4
+AI[j5|m"[k6m6"jm2j!!0dU"Bm5jZmX"ZI3Zm6"kX"Zm2yx""^Zm"6m[k654#"kH"Zm
+2"B4k4AFX54j54#y!!0dU"[ZIXI[jmX3"53"IEjkYIj5[c"jZm"6m[k654#"kH"jZm"
+3Fm[5I~"HkEX"53!!0dU"6k4m"jZXkE#Z"35YF~m"6mH545j5k43c"jZm"6m[k654#"
+kH"FX54jI$~m!!0dU"[ZIXI[jmX3"53"6k4m"$i"~kI654#"jZm"6mAZI3Zm6"[ZIXI
+[jmX"|I~Em3!!0dU"54jk"jZm"J~[[k6m"I46"IFF~i54#"J~kWmX[I3mx!!0dU!!0d
+U"'kYm"kH"jZm"~k4#m3j"$5j3"54"jZm"[k6mX"YI[Xk"[k4[mX43"$XmIG54#!!0d
+U"jZm"[k6m6"jm2j"54jk"~54m3"kH"dRAdv"[ZIXI[jmX3x"")H"jZm"H5X3j!!0dU
+"[ZIXI[jmX"54"I"~54m"BIHjmX"$XmIG54#y"53"I"FmX5k6f"kX"jZm"H5X3j!!0d
+U"jWk"[ZIXI[jmX3"IXm"AAf"jZm"H5X3j"[ZIXI[jmX"53"#5|m4"54"Zm2!!0dU"X
+mFXm3m4jIj5k4"54"HmIX"kH"YI45I[I~"YI5~"#IjmWIi3x""^Zm"kjZmX!!0dU"6I
+4#mXkE3"[ZIXI[jmX3"~5Gm"\"n"J"h"IXm"4kj"jXmIjm6"[IXmHE~~i!!0dU"$m[I
+E3m"jZmi"ZI6"jk"ZI|m"$mm4"FXm3mX|m6"HkX"jZm"YI[Xk3"jk"WkXG!!0dU"Ij"
+I~~x!!0dU!!0dU"^Zm"3G5FFm6"}Em3j5k4!!0dU"AAAAAAAAAAAAAAAAAAAA!!0dU
+!!0dU"^Zm"}Em3j5k4"jm2j"53"3G5FFm6"W5jZ"Yk3j"3Fm[5I~"[Ijm#kXi"[k6m3
+!!0dU"jEX4m6"kHHx""^Zm"k4~i"HE4j5k454#"54FEj"53"\M"6Em"jk"Jk$mi~54m3
+x!!0dU"^Zm"I[j5|m"\M"[Zm[G3"mI[Z"~54m"kH"54FEj"~kkG54#"HkX"jZm"YIXG
+mX!!0dU"jm2j"jk"m46"jZm"}Em3j5k4"YIjmX5I~x""^Zm"6mHIE~j"YIXGmX"53
+!!0dU"UUAAAAAAAAAAOEjAAANmXmAAAAAAAAAA!!0dU"^Zm"[k6m6"I43WmX"53"I33EY
+m6"jk"5YYm65Ijm~i"Hk~~kWx!!0dU!!0dU!!0dU"^Zm"[k6mX!!0dU"AAAAAAAAA
+!!0dU!!0dU"NmXm"53"jZm"[k6mX"XkEj54mx"")j"53"3EFFk3m6"jk"$m"[~mIXx"")
+j!!0dU"I3G3"HkX"jZXmm"H5~m"4IYm3,""jZm"JqEm3j5k4<5~m(IYm"3ZkE~6!!0d
+U"[k4jI54"jZm"jm2j"kH"jZm"}Em3j5k4c""jZm"J'k~Ej5k4<5~m(IYm"3ZkE~6
+!!0dU"ZI|m"jZm"I43WmXc""^Zm"[kYF~mjm"}Em3j5k4SI43WmX"Fk3j54#"W5~~"$m
+!!0dU"WX5jjm4"jk"J_EjFEj<5~m(IYmx""BLE4"jZ53"H5~m"jZXkE#Z"F~I54"^m&x
+y!!0d!!0dJ4mWXmI6Jq<5~m!!0dJ4mWXmI6J'<5~m!!0dJ4mWWX5jmJ_<5~m!!0d!!0d
+J4mW~54m[ZIXunT!!0dJYm33I#m{TKZIj"H5~m"[k4jI543"jZm"}Em3j5k4+1!!0d
+JXmI6ed"jk"JqEm3j5k4<5~m(IYm!!0dJkFm454Jq<5~muJqEm3j5k4<5~m(IYm!!0d
+!!0dJYm33I#m{KZIj"H5~m"[k4jI543"jZm"3k~Ej5k4+1!!0dJXmI6ed"jk"J'k~Ej
+5k4<5~m(IYm!!0dJkFm454J'<5~muJ'k~Ej5k4<5~m(IYm!!0d!!0dJYm33I#m{KZIj
+"3ZkE~6"jZm"[kYF~mjm"Fk3j54#"$m"WX5jjm4"jk+1!!0dJXmI6ed"jk"J_EjFEj<
+5~m(IYm!!0dJ5YYm65IjmJkFm4kEjJ_<5~muJ_EjFEj<5~m(IYm!!0d!!0dJ4mW5HJ5
+H_;!!0d!!0dU"^ZmXm"IXm"Q@"[ZIXI[jmX3"jZIj"W5~~"$m"ZI3Zm6"Bw-uC"jk"e
+@duhyx!!0dU"^Zm"ZI3Z54#"YE~j5F~5mX"YE3j"$m"YEjEI~~i"FX5Ym"W5jZ"Q@"u
+"@w"T"@\@!!0dU"I46"$m"~m33"jZI4"Q@x""^Zm"3jIXj"|I~Em"B3mm6y"[I4"$m"
+I4ijZ54#!!0dU"54"jZm"XI4#m"w-Ae@dx!!0d!!0dJ4mW[kE4jJNM!!0dJ4mW[kE4j
+JjmYF!!0dJ[ZIX6mHJjkF["nJh"U"Z5#m3j"ZI3Zm6"[ZIXI[jmX"Be@dy!!0dJ[ZIX
+6mHJ$kj["nJC"U"~kWm3j"ZI3Zm6"[ZIXI[jmX"Bw-y!!0dJ4mW[kE4jJXI4#m!!0dJ
+XI4#muJjkF["JI6|I4[mJXI4#mAJ$kj["JI6|I4[mJXI4#m"e"U"Q@!!0d!!0dJ6mHJ
+L{JXmI6ed"jk"JNI3ZME~j5F~5mX"JNMuJNI3ZME~j5F~5mXJXm~I2!!0d""J_;jXEm
+!!0d""J5H4EYJNMPJXI4#m"J_;HI~3mJH5!!0d""J5H4EYJNM">w"J_;HI~3mJH5!!0d
+""JjmYFuJNM"J65|56mJjmYF"@w"JYE~j5F~iJjmYF"@w!!0d""J5H4EYJjmYFuJNM
+"J_;HI~3m"JH5"U"[Zm[G"[kYYk4"HI[jkX"kH"@w!!0d""JjmYFuJNM"J65|56mJjm
+YF"@"JYE~j5F~iJjmYF"@!!0d""J5H4EYJjmYFuJNM"J_;HI~3m"JH5"U"[Zm[G"[kY
+Yk4"HI[jkX"kH"@!!0d""J5H_;"Jm~3m"U"HI5~m6xxxXmFXkYFj!!0d"""""JYm33I
+#m{:~mI3m"m4jmX"I"4EY$mX"54"jZm"XI4#m"w"A"Q@!!0d""""""""jZIj"53"4kj
+"I"YE~j5F~m"kH"@"kX"@wx1JL!!0d""JH51!!0dJL!!0d!!0dJ4mW[kE4jJN'!!0dJ
+6mHJL{JXmI6ed"jk"JNI3Z'mm6"JN'uJNI3Z'mm6JXm~I2!!0d""J_;jXEm!!0d""J5
+H4EYJN'"PJjkF["J_;HI~3mJH5!!0d""J5H4EYJN'">J$kj["J_;HI~3mJH5!!0d""J
+5H_;"Jm~3m"U"HI5~m6xxxXmFXkYFj!!0d"""JYm33I#m{:~mI3m"m4jmX"I"4EY$mX
+"54"jZm"XI4#m!!0d"""""""""J4EY$mXJ$kj[J3FI[m"A"J4EY$mXJjkF[x1JL!!0d
+""JH51!!0dJL!!0d!!0dU"(kW"Wm"W5~~"XmI6"jZm"3mFIXIjkX"jm2j"jXmIj54#"
+3Fm[5I~"[ZIXI[jmX3!!0dU"I3"kX654IXi"k4m3x""(mm6"jk"6k"jZm"[kYYI463"
+54"YI[Xk3"3k"[Ij[k6m!!0dU"[ZI4#m3"6k4gj"ZEXj"jZm"[kYYI463")"WI4j"jk
+"6k!!A4!!0d!!0dJ$m#54#XkEF!!0d""Jm3[IFm[ZIXuAeJ26mHJ'mF!!0d""{J3jX5
+4#JUJ3jX54#JUAAAAAAAAAAJ3jX54#JOEjAAAJ3jX54#JNmXmAAAAAAAAAA1!!0d""J
+6mHJ6kCe{J[Ij[k6mnCeue@"1!!0d""J6mHJL{{J6k3Fm[5I~3Jm46~54m[ZIXuAe
+!!0d""JYm33I#m{^Zm"3mFIXIj5k4"jm2j"53,"nJ'mFgx"1U!!0d""JYm33I#m{a4jmX
+"I"XmF~I[mYm4j"kX"lE3j"FXm33"LmjEX4,"T1U!!0d""JXmI6Ae"jk"JjmYF!!0d"
+"J5H2JjmYFJmYFji"Jm~3m""J26mHJ'mF{JjmYF1JH511!!0d""JL!!0dJm46#XkEF
+!!0d!!0dU"B[Ijm#kX5m3"$I[G"jk"4kXYI~y!!0dU!!0dU"(kW"Wm"IXm"XmI6i"jk"
+XmI6"jZm"}Em3j5k4"I46"I43WmXf"I46"WX5jm"jZm!!0dU"kEjFEjx""'54[m"I~~
+"jZ53"53"6k4m"W5jZ"I~~"[ZIXI[jmX3"$m54#!!0dU"nkjZmXgf"6mH54m"YI[Xk3
+"jk"6k"I~~"jZm"FXk[m3354#"$mHkXm"[ZI4#54#!!0dU"I~~"jZm"[Ij[k6m3x!!0d
+!!0dJ4mW[kE4jJON!!0d!!0dU"(kjm,"^Z53"YI[Xk"W5~~"I~3k"$m"WX5jjm4"54
+"3ZkXj"HkXY"W5jZ"jZm!!0dU"I43WmX"6m[k6mXx!!0d!!0dJ6mHJI~~kjZmX{JONu
+."U"3mj"I~~"[Ij[k6m3"u"nkjZmXg!!0d"J~kkF!!0d"""J[Ij[k6mJONue@!!0dU"
+"J~[[k6mJONuJON""U"k4~i"E3m6"HkX"6m[k6mX!!0d"""JI6|I4[mJON"$i"e!!0d
+"""J5H4EYJON>@-d!!0d"JXmFmIj!!0d"Jm46~54m[ZIXuew"U"\M!!0d1!!0d!!0dU
+"Km"W5~~"4mm6"jk"[kFi"~54m3"HXkY"jZm"}Em3j5k4"H5~m"I46"WX5jm"jZmY
+!!0dU"jk"jZm"kEjFEj"H5~m"|mX$Ij5Yx!!0d!!0dJ6mHJOkFiqEm3j5k4{Jm46~54m[
+ZIXAe"J4mW~54m[ZIXAe"JOq1!!0d!!0dJ6mHJOq{U"U"jZ53"#5|m3"mXXkX"k4"4E
+~~"54FEj"H5~mx"")j"3ZkE~6!!A4!!0d"JXmI6Jq<5~m"jkJ~54m"U"|mX$Ij5Y"3Z
+kE~6"$m"k4"Ij"jZm"YkYm4j!!A4!!0d"J5HmkHJq<5~m"J5YYm65IjmJ[~k3m54Jq<
+5~m!!0d"Jm~3m"J5YYm65IjmJWX5jm"J_<5~m"{J~54m1Jm2FI46IHjmX"JOq!!0d"J
+H51!!0d!!0d!!0dU"^Z53"YI[Xk"YIGm3"I~~"[ZIXI[jmX3"I[j5|mf"I46"6mH54m
+3"jZmY"I3"jZm5X!!0dU"Zm2"[k6m3,"!!A4!!A4ZZx!!0d!!0dJ6mHJ=~~=[jNm2{J
+6mHJZm2ON{..1U!!0d""J~kkF!!0d""""J[Ij[k6m!!20JZm2ONuJI[j5|m!!0d""""
+Jm6mHJZm2[Z{J~kWmX[I3m{Jm6mHJ4km2FI46JZm2[Z{JZm2ON111JZm2[Z!!0d""""
+J(EYmX5[I~~iJm6mH{!!20JZm2ON1{!!A4!!A4JZm2[Z1U!!0d""""J5H4EY!!20JZm
+2ON>!!20<<!!0d""""""Jm6mHJZm2ON{Jm2FI46IHjmXJ3jmFZm2JZm2ON1U!!0d""J
+XmFmIj1!!0d!!0dJ6mHJ(EYmX5[I~~iCeC@{J~[[k6mnJhC@JXm~I2"J~kWmX[I3m{C
+eh11!!0d!!0dJ6mHJ3jmFZm2CeC@{J5H[I3m!!20C@"CeeJkX"Ce@JkX"CewJkX"CeR
+JkX"Ce-JkX"CedJkX!!0d""Ce?JkX"CevJkX"CeQJkX"Ce=JkX"CetJkX"CeOJkX"Ce
+*JkX"CeaJkX"Ce<JkX!!0d"""J5H[I3m!!20Ce"eJkX"@JkX"wJkX"RJkX"-JkX"dJk
+X"?JkX"vJkX"QJkX!!0d""""""""=JkX"tJkX"OJkX"*JkX"aJkX"<JkX"e.JH5".JH
+51!!0d!!0dU"^Z53"YI[Xk"k|mXX56m3"jZm"!!A4!!A4ZZ"4kjIj5k4"HkX"FX54jI
+$~m"[ZIXI[jmX3f!!0dU"I46"6mH54m3"jZmY"I3"jZm5X"ZI3Zm6"[kE4jmXFIXj3x
+""JON"53"jZm!!0dU"F~I54Ajm2j"[ZIXI[jmX"4EY$mXf"JjmYF"53"5j3"[k6m6"[
+ZIXI[jmXx!!0d!!0dJ6mHJ(kXYNI3Z{JjmYFuJN'"U"3mm6"|I~Em!!0d""JONuJ$kj
+[!!0d""J~kkF!!0d""""J~[[k6mnJhuJON"J~[[k6mnJvuJjmYF!!0d""""J~kWmX[I
+3m{Jm6mHh{v11U!!0d""""J5H4EYJON>JjkF[!!0d""""""JI6|I4[m"JjmYF"JNM""
+U"I66"YE~j5F~5mX"jk"ZI3Z"|I~Emf""E354#xxx!!0d""""""J5H4EY"JjmYFPJjk
+F["JI6|I4[mJjmYFAJXI4#m"JH5"U"Yk6E~k"IX5jZYmj5[!!0d""""""JI6|I4[mJO
+N"e!!0d""JXmFmIj1!!0d!!0dU"(kWf"Wm"6mH54m"jZm"352"m2[mFj5k4"[ZIXI[j
+mX3!!0d!!0dJ6mHJa2[mFj{U!!0d""J(EYmX5[I~~iJ6mH{e1{!!A4!!A4=e1U!!0d"
+"J(EYmX5[I~~iJ6mH{@1{!!A4!!A4=@1U!!0d""J(EYmX5[I~~iJ6mH{w1{!!A4!!A4
+=w1U!!0d""J(EYmX5[I~~iJ6mH{n!!A41{!!A4!!A4=R1U!!0d""J(EYmX5[I~~iJ6m
+H{nJ"1{!!201U!!0d""J(EYmX5[I~~iJ6mH{nJ!!201{!!A4!!A4@.1U!!0d1!!0d
+!!0d!!0dU"OkFi"jZm"3k~Ej5k4"HXkY"jZm"3k~Ej5k4"H5~mf"FmXHkXY"jZm"jXI43
+HkXYIj5k43!!0dU"BE354#"Jm6mHyf"I46"WX5jm"kEj"54"IFFXk2x"dRA[ZIXI[jm
+X"~54m3x""^Zm"WZk~m!!0dU"3k~Ej5k4"YE3j"H5j"54"YmYkXi"$m[IE3m")"6k4g
+j"WI4j"jk"GmmF"[kE4j54#"jZm!!0dU"[ZIXI[jmX3"I46"kEjFEjj54#"jZmY"I"H
+mW"Ij"I"j5Ymx"")"6k4gj"3I|m"jZm"WZk~m!!0dU"Ym33"54"k4m"YI[Xk"jZkE#Z
+f"$m[IE3m"I6654#"jk"I"~k4#"~53j"#mj3"|mXi"3~kWx!!0d!!0dJ6mHJN56m'k~
+Ej5k4{J6mHJ=~~{1JjmYFue"J4mW~54m[ZIXuew"Jm46~54m[ZIXew!!0d""J~mjJ
+!!A4JXm~I2"JN561!!0d!!0dJ6mHJN56{U"U!!0d"JXmI6J'<5~m"jkJ~54m!!0d"J5Hm
+kHJ'<5~m!!0d"""J5YYm65IjmJ[~k3m54J'<5~m"Jm2FI46IHjmX"JKX5jm'F~5j!!0d
+"Jm~3m!!0d"""Jm6mHJ=~~{J=~~"J!!A4{J4EY$mXJjmYF11U!!0d"""Jm2FI46IHj
+mXJm6mHJ[34IYm"rJ4EY$mXJjmYFJm46[34IYm{J~54m1U!!0d"""JI6|I4[mJjmYF"
+eJXm~I2!!0d"""Jm2FI46IHjmX"JN56!!0d"JH51!!0d!!0dU"^Zm"4m2j"YI[Xk3"I
+Xm"E3m6"jk"3F~5j"I"~53j"kH"[k6m"[ZIXI[jmX3!!0dU"54jk"I$kEj"dR"[ZIXI
+[jmX3,""jZm"H5X3j"hdR"54"I"YI[Xk"BCey"IXm!!0dU"WX5jjm4"jk"jZm"kEjFE
+j"H5~m"I46"jZm"XmYI546mX"IXm"~mHj"54"jZm!!0dU"YI[Xkx""^Zm"3F~5j"W5~
+~"4kj"54jmXXEFj"I4i"!!A4!!A4ZZ"3m}Em4[m3"BkX!!0dU"jZm"3Fm[5I~"!!A4
+!!A4=w"3m}Em4[m3yx!!0d!!0dJ$m#54#XkEF!!0dJ[Ij[k6mewue@""U!!0dJ#6mHJ[
+jX~Y{\\M1U!!0dJm46#XkEF!!0d!!0dJ6mHJKX5jm'F~5j{U!!0d""J6mHJ!!A4CCe{
+J[34IYm"rCCeJm46[34IYm1U!!0d""Jm6mHJ=~~{J=~~""U"m2FI46"jk"XmI~"[ZIX
+I[jmX3!!0d""""!!A4!!A4.w!!A4!!A4.w!!A4!!A4=J3jX54#{m46!!A4!!A4=J3jX
+54#11U"I66"jmXY54Ij5k4"[k6m3,!!0d""J6mHJx{1U"""""""""""""""""""""""
+""""U""11J[34IYm"m46Jm46[34IYm!!0d""J4mW~54m[ZIXuew"U"\M!!0d""Jm6mH
+J=~~{Jm2FI46IHjmXJK'J=~~"JxJxJxJxJxJxJxJxJxJxJm461!!0d""J5YYm65IjmJ
+WX5jmJ_<5~m{J=~~1U!!0d""J5YYm65IjmJ[~k3mkEjJ_<5~m!!0d1!!0d!!0dJ6mHJ
+K'{JfJfJfJfJfJfJfJfJOEjJXm~I21U"FI33"k|mX"v"T"v"u"dR"[ZIX!!0d!!0dJ6
+mHJfCeJXm~I2"C@CwCRC-CdC?CvCQ{C@CwCRC-CdC?CvCQU"FI33"v"[ZIX!!0d""J5
+H2CQJxJm2FI46IHjmXJm46m6mHJH5CeJXm~I21!!0d!!0dJ6mHJOEjJXm~I2CeC@Cw{
+U")43mXj"~54mHmm6"[ZIXI[jmXf!!0d""J5H2Ce!!A4U"""""""""""U"$Ej"6k4gj
+"54jmXXEFj"I4i"!!A4!!A4ZZ!!0d""""J5H2C@!!A4J[jX~Y"CeC@CwJm~3m"CeC@C
+wJ[jX~Y"JH5!!0d""Jm~3m!!0d""""J5H2C@!!A4CeJ[jX~YC@CwJm~3m"CeC@J[jX~
+YCwJH5!!0d""JH5"JK'1!!0d!!0dJ6mHJm46m6mHCeJm46{1U"m46"kH"jm2jf"3k"m
+46"Jm6mH"I46"#k$$~m"XmYI5454#"lE4G!!0d!!0dU"=~~"jZIjg3"~mHj"jk"6mH5
+4m"IXm"jZm"3G5FFmX"Yk6E~m"I46"jZm"6m[k6mX!!0dU"Yk6E~mx""^Zmi"$kjZ"I
+Xm"WX5jjm4"54jk"jZm"Fk3j54#"jk"$m"m2m[E6m6!!0dU"$i"jZm"Xm[m5|mXx""^
+Zmi"IXm"[kYFXm33m6"I46"k$HE3[Ijm6f"$Ej"jZm!!0dU"k$HE3[Ij5k4"53"Yk3j
+~i"lE3j"[kYFXm335k4,"E354#"[kYYI46"3iY$k~3!!0dU"~5Gm"Jf"HkX"~k4#mX"
+[kYYI46"WkX63f"I46"E354#"$E5~jA54"Xm#53jmX3!!0dU"543jmI6"kH"I~~k[Ij
+54#"Xm#53jmX3x""'kYm"kH"jZm"I$$Xm|5Ij5k43"I46!!0dU"jZm"[Zk5[m3"kH"X
+m#53jmX"IXm"YmI4j"jk"$m"[k4HE354#"I46SkX"35~~ix!!0dU":~I54Ajm2j"|mX
+35k43"kH"jZm"Yk6E~m3"IXm"#5|m4"ZmXmf"I3"Wm~~"I3!!0dU"I"#~k33IXi"kH"
+jZm"k$HE3[Ij5k4x!!0dU!!0dU"NmXm"53"jZm"3G5FFmX"Yk6E~mx"")j"53"E3m6"
+54"jZm"HkXY,!!0dU"JqEm3j5k4,!!0dU"I"3Fm[5I~"~54m"kH"jm2j!!0dU"I4ijZ
+54#"jZIj"53"3G5FFm6"m4j5Xm~if!!0dU"E4j5~"I#I54"3mm54#!!0dU"I"3Fm[5I
+~"~54m"kH"jm2j!!0dU!!0dU"J6mHJqEm3j5k4,{J$#XkEF!!0dU"""JIHjmX#XkEFJ
+m46!!0dU"""JI~~kjZmX!!0dU"""J'G5FFmX1!!0dU!!0dU"J'G5FFmX"3jIXj3"jZm
+"3G5FF54#"$i"XmI654#"jZm"6m~5Y5jmX"jm2j"I46!!0dU"6mH5454#"jZm"YI[Xk
+"nJ'G5Fr54mg"jk"3G5F"I"~54mf"jm3j54#"HkX"jZm!!0dU"m46"jm2jx""^Zm"jm
+3j"53"6k4m"$i"[k43jXE[j54#"I"[kYYI46"4IYm"HXkY!!0dU"jZm"3m4j54m~"jm
+2j"I46"HXkY"mI[Z"~54mf"I46"[kYFIX54#"jZmY"BW5jZ!!0dU"J5H2yx!!0dU!!0d
+U"{J[Ij[k6mnJ\\Mue@"U"kjZmX!!0dU"J#6mHJ'G5FFmXCe\\MC@\\M{U"XmI6"jZ
+53"~54m"AP"Cec"4m2j"~54m"AP"C@!!0dU"U""6mH54m"3m4j54m~"YI[Xk,!!0dU"
+""Jm2FI46IHjmXJ6mHJ[34IYmC@Jm46[34IYmJSJJSSJS{=+\\Mf8DJk|mX1U!!0dU"
+U"6mH54m"YI[Xk"jk"XmI6"~54m"I46"[kYFIXm"5j"W5jZ"3m4j54m~,!!0dU"""J6
+mHJ'G5Fr54mCCe\\M{Jm2FI46IHjmXU!!0dU"""""J5H2J[34IYmCCeJm2FI46IHjmX
+Jm46[34IYmJ[34IYmC@Jm46[34IYmU!!0dU"""""""Jm2FI46IHjmX"J*m[k6m=43Wm
+X"U"H5453Zm6"3G5FF54#!!0dU"""""Jm~3mU!!0dU"""""""Jm2FI46IHjmX"J'G5F
+r54m"U"GmmF"3G5FF54#!!0dU"""""JH51U!!0dU"1!!0dU!!0dU"J*m[k6m=43WmX"
+E4ZI3Zm3"jZm"I43WmX"jm2j"I46"WX5jm3"5j"jk"jZm!!0dU"3[Xmm4x"^Zm"E4FX
+54jI$~m"[ZIXI[jmX3"XmFXm3m4jm6"I3"!!A4!!A4ZZ"IXm"~mHj!!0dU"I3"jZmi"
+IXm"B5xmxf"Fk335$~i"E4FX54jI$~m!!A4y"Ok4jXk~AM"B!!A4!!A4.6y"W5~~!!0d
+U"$XmIG"jZm"jm2j"54jk"~54m3"k4"jZm"3[Xmm4c"jZm"~54m$XmIG3"54"jZm
+!!0dU"ZI3Zm6"jm2j"IXm"5#4kXm6x""JN'"53"3mj"jk"jZm"3mm6"|I~Em"$mHkXm
+!!0dU"J*m[k6m=43WmX"53"54|kGm6x!!0dU!!0dU"J6mHJ*m[k6m=43WmX{U"B[kYFIX
+m"H5X3j"FIXj"W5jZ"J(kXYNI3Zy!!0dU"""JONuJ$kj["U"H5X3j"[ZIXI[jmX"BF~
+I54"jm2jy!!0dU"""J~kkF"U"k|mX"ZI3Zm6"[ZIXI[jmX3!!0dU"""""J~[[k6mJN'
+uJON"U"YIF"[k654#"jk"F~I54"jm2j!!0dU"""""J5H4EYJON>JjkF[!!0dU""""""
+"JI6|I4[m"JN'"JNM""U"I66"YE~j5F~5mX"jk"ZI3Z"|I~Emf""E354#xxx!!0dU""
+"""""JI6|I4[mJON"e"U"jZ53"ZmXm"FXm|m4j3"JN'"HXkY"$m54#"jm3jm6"FXmYI
+jEXm~i!!0dU"""""""J5H4EY"JN'PJjkF["JI6|I4[mJN'AJXI4#m"JH5"U"Yk6E~k"
+IX5jZYmj5[!!0dU"""JXmFmIj!!0dU"U"*mH54m"m2[mFj5k43x""OkYFIXm"jZ53"F
+IXj"W5jZ"Ja2[mFj!!0dU"""J[Ij[k6mnJ\\=u."U"nm3[IFmgf"J!!0dU"U"J[Ij[k
+6mnJ\\tue"U"nkFm4gf"{"AA"E44m[m33IXi!!0dU"""J[Ij[k6mnJ\\Ou@"U"n[~k3
+mgf"1!!0dU"""J[Ij[k6mnJ!!A4u?"""U"n3EFmX3[X5Fjgf"\"BHkX"Zm2"54FEjy
+!!0dU"""J~[[k6mnJ"unJ!!20!!0dU"""J~[[k6mnJ!!20unJ!!0dU"U!!0dU"""Jm46
+~54m[ZIXuAe"U"5#4kXm"~54m"$XmIG3"54"[k6m6"jm2j!!0dU"""J4mW~54m[ZIXu
+nJ\\M!!0dU"""J~kWmX[I3mJ$#XkEFJ5YYm65IjmJWX5jmJN'J$#XkEF!!0dU"1!!0d
+U!!0dU"s~k33IXi"kH"I$$Xm|5Ij5k43"I46"k$HE3[Ij5k43!!0dU"AAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!!0dU!!0dU!!0dU"J~mj"""""""""""""""""
+h!!0dU"JN'"""BJjk~mXI4[my"""Jf"""""BJZI3Z"|I~Emy""""""""Ce!!0dU"JNM
+""""""""""""""""""Jx"""""BZI3Z"YE~j5F~5mXy""""C@!!0dU"JjkF["""BJYk4
+jZy"""""J0"""""B~I3j"ZI3Zm6"[ZIX,"e@d"hy!!0dU"J$kj[""""""""""""""""
+w-"""""BH5X3j"ZI3Zm6"[ZIX,"w-"Cy!!0dU"JXI4#m"""""""""""""JimIX""""B
+JjkF[AJ$kj[/e,"Q@y!!0dU"JON"""""BJE[ZiFZy""""Jc"""""BI"[ZIXI[jmX"[k
+6my!!0dU"J[Ij[k6m"""""""""""""J,!!0dU"J6mH"""""""""""""""""JC!!0dU"
+Jm2FI46IHjmX"""""""""J\!!0dU"J[34IYm""""""""""""""J{!!0dU"Jm46[34IY
+m"""""""""""J1!!0dU"J~[[k6m""""""""""""""J7!!0dU"JI6|I4[m""""""""""
+"""JA!!0dU"J$#XkEF""""""""""""""JT!!0dU"J5H4EY"""""""""""""""J5H!!0d
+U"Jm46~54m[ZIX"""""""""Jb!!0dU"J5H2"""""""""""""""J5H\\v!!0dU"J'G5
+FFmX"""""""""""""JK!!0dU"J'G5Fr54m""""""""""""J&!!0dU"J*m[k6m=43WmX
+""""""""J]!!0dU"J~kWmX[I3mJ$#XkEFJ5YYm65IjmJWX5jmJN'J$#XkEF""""""J8
+!!0dU!!0dU"^Zm3m"I335#4Ym4j3"IXm"WX5jjm4"jk"jZm"kEjFEj"$i"JKX5jm_Ej
+FEj"BI[jEI~~i!!0dU"$i"JK'9y"I46"jZm4"jZm"k$HE3[Ijm6"FXk[m3354#"[k6m
+"53"WX5jjm4"B#5|m4!!0dU"I3"I"FIXIYmjmX"54356m"B"y"IHjmX"JKX5jm_EjFE
+jyx"JKX5jm^ZmLm3j"53!!0dU"IEjkYIj5[I~~i"54|kGm6"jk"[kFi"jZm"}Em3j5k
+4"I46"jZm4"jZm"I43WmXx!!0d!!0dJ6mHJKX5jm_EjFEjCeC@{J$m#54#XkEF!!0d"
+"J[Ij[k6mnJ\ue@"J4mW~54m[ZIXuew!!0d""Jm6mHJJ{J4km2FI46JK'9{Ce1{C@11
+JJ1!!0d!!0dJ6mHJK'9CeC@{J~mjJJJ3jX54#"U"|mX$Ij5Y53Zf"I|k56"3FI[m3"I
+HjmX"[kYYI463!!0d""J5YYm65IjmJWX5jmJ_<5~m!!0d"""{JJJ~mjJJhJJJ~mjJJh
+JJJCJJJ6mHJJJCJJJx{C@1JJhJJJfJJJjk~mXI4[mJJJfCe1U!!0d""JI~~kjZmXJ[I
+j[k6mnBueJ[Ij[k6mnyu@!!0d""JIHjmXI335#4Ym4jJKX5jm^ZmLm3j!!0d""JjkG3
+.u1!!0d!!0dJ6mHJKX5jm^ZmLm3j{J5YYm65IjmJWX5jmJ_<5~m{JjZmJjkG3.1!!0d
+""J[Ij[k6mnBue@J[Ij[k6mnyue@!!0d""J5YYm65IjmJWX5jmJ_<5~m{J3jX54#JqE
+m3j5k4,1U!!0d""J5YYm65IjmJWX5jmJ_<5~m{J'mF1U!!0d""JOkFiqEm3j5k4!!0d
+""J5YYm65IjmJWX5jmJ_<5~m{J'mF1U!!0d""{J=~~=[jNm2J(kXYNI3ZJa2[mFjJN5
+6m'k~Ej5k41!!0d""Jm46#XkEF1!!0d!!0d!!0dJKX5jm_EjFEj{JjZmJN'1{JjZmJN
+MU!!0d1BhJ0JYk4jZhJcJE[ZiFZhJ,J[Ij[k6mhJ\Jm2FI46IHjmXhJ{J[34IYm{hJC
+J26mHhhJ3jX54#!!0dJCJe{h\\=1JCJw{h\\O1JCJR{h\\I11hJ1Jm46[34IYmhJT{h
+J7J~[[k6mJCJ8{J4mW~54m[ZIX!!20*!!0dJ~kWmX[I3mJTJ5YYm65IjmJWX5jmJfJT
+1hJAJI6|I4[mJimIXQ@hJ5HJ5H4EYhJbJm46~54m[ZIX!!0dJ0!!20?aJCJ\\-eEm3\
+\R5k\\dm,{Jc."J~kkFJ,Jc!!20OJAJce"J5HJc>@-d"JXmFmIjJb!!20*JK1{J,!!20
+\end{comment}
+\begin{lcode}
+*!!20O!!0dJ#6mHJKCe\\MC@\\M{J\JCJ{C@J1JSJJSSJS{=+\\Mf8DJk|mX1JCJ&C
+Ce\\M{J\J5H\\vJ{CCeJ\U!!0dJ1J{C@J1J\J]Jm~3mJ\J&JH51J&11JCJ]{Jcw-J~k
+kFJ7JfJcJ5HJc>J0JAJfJxJAJceJ5HJfPJ0!!0dJAJfAJimIXJH5JXmFmIjJ,eg.J,w
+!!20@J,wwg?J7!!20@.n!!20J7n!!20!!20@.JbAeJ81!!0dy!!0d!!0dJm46!!0d
+!!0d!!03!!03!!A{end!!A}
+\end{lcode}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%[Addendum 2: TeX encoder for my decoder. (mjd,18-Aug-1994)]
+\subsection{Addendum 2}
+
+ TeX encoder for my decoder. (mjd,18-Aug-1994)
+
+
+\begin{lcode}
+% Source character set: 13,32-126 = 96
+%
+% (Note exclusion of tab. Assumption: Text to be translated will
+% always be untabified first.)
+%
+% Target character set: 33-126.
+%
+% Carriage return (13) cannot be included in the target set because
+% of the constraint to have a maximum line length of 72 in the
+% encoded text. If 13 (carriage return) were included in the
+% encoding, then the end of the current line would only occur at
+% the next instance in the ciphered text of the character that
+% translates to 13. And depending on what that character is, who
+% knows how long the encoded line could be? Perhaps as long as the
+% entire text.
+%
+% Space (32) are not included in the target set for a subtler
+% reason. If spaces in the encoded text happen to fall at the end
+% of a line, they will be dropped by TeX during the decoding
+% process, instead of decoded. So we either must exclude them from
+% the target set, or make sure that they never fall at the end of a
+% line.
+%
+% By excluding space from the target set, we make it possible for
+% the decoder to use a space as its argument delimiter. If we have
+% only one space, at the end of the encoded text, it is not so hard
+% to ensure that it does not fall at the end of a line. But note
+% that the decoder must make sure to change the catcode of space to
+% something other than 10, so that it will not disappear if it
+% falls at the *beginning* of a line.
+
+\def\colon{:}\def\arrow{->}%
+\let\isx\message
+%\def\isx#1{}
+
+\iffalse
+% OK, here is how the encoding works. Start with \mag = random (in
+% the target range 33-125), first encoding value. Handle two
+% special cases first: ^^M encodes to \mag, space encodes to \mag
+% +1. Then start normal encoding at \fam = 35 (char 35 = ! encodes
+% to \mag +2, and so forth). When \mag reaches 126, we wrap it
+% around to 33 (don't want to encode any character to space).
+% Finally, when \fam reaches 126, we must handle the last three
+% characters (126,33,34: ~!") as digraphs: encode them as ~x~y~z,
+% where xyz are obtained by continuing to increment \mag.
+
+@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ ! "#$%&'()*+,-./0123456789:;<=>?
+ R S~S~TTUVWXYZ[\]^_`abcdefghijklmnop
+@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} ~
+qrstuvwxyz{|}!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ~R
+\fi % ^^^
+
+\def\setup{%
+ \def\notilde{}% later will be defined to include a tilde
+ \def\encodeone{%
+ \catcode\fam\active\lccode126\fam\lccode 48\mag
+ \lowercase{\edef~{\notilde 0}%
+\isx{[\string~\colon \notilde 0\space\number\fam\arrow\number\mag]}%
+ }%
+ \advance\mag7 \ifnum\mag>125\advance\mag-93 \fi
+ \advance\fam1
+ }%
+ \def\do{\encodeone \csname do\ifnum\fam>125 stop\fi\endcsname
+ }%
+% ASSUMPTION: \mag initialized before the call of \setup
+% Encode ^^M -> \mag
+ \fam13 \encodeone
+% Encode space -> next \mag
+ \fam32 \encodeone
+% Now encode the rest
+ \fam35 \let\dostop\relax \do
+% Now \fam = 34, \mag = ?. We need to define encoding for
+% characters 34,33,126 ("!~) as ~z ~y ~x. But what are convenient
+% values for x y z? Why, just the next \mag's in sequence
+ \edef\notilde{\string ~}
+ \encodeone \fam33 \encodeone \encodeone
+}
+
+\def\outwrite{\immediate\write15{\outline}%
+% If a digraph occurred at the end of the line, carry over the
+% second character to the beginning of the next line.
+ \expandafter\ifx\csname 73\endcsname\relax
+ \else
+ \expandafter\let\expandafter\1\csname 73\endcsname
+ \expandafter\let\csname 73\endcsname\relax
+ \charnum 1
+ \fi
+ \checkeof}
+% For fast looking on screen:
+%\def\outwrite{\immediate\write16{\outline}\checkeof}
+
+\begingroup
+\let\0\catcode \0`\0 11 \0`\2 11 \0`\3 11 \0`\4 11 \0`\5 11
+\0`\6 11 \0`\7 11 \0`\8 11 \0`\9 11 \0`\1 11
+\gdef\outline{\1\2\3\4\5\6\7\8\9\10\11\12\13\14\15\16\17\18\19
+ \20\21\22\23\24\25\26\27\28\29\30\31\32\33\34\35\36\37\38\39
+ \40\41\42\43\44\45\46\47\48\49\50\51\52\53\54\55\56\57\58\59
+ \60\61\62\63\64\65\66\67\68\69\70\71\72}
+\endgroup
+
+\newcount\charnum
+
+\def\checkeof{\futurelet\next\encodemore}
+
+\def\tildecheck#1#2{\if \string~#1%
+ \expandafter\def\csname\number\charnum\endcsname{#1}%
+ \advance\charnum 1
+ \expandafter\def\csname\number\charnum\endcsname{#2}%
+\fi}
+
+\def\encodemore{\ifx\next\EOF
+ \let\next\outwrite \let\checkeof\relax
+\global\tracingcommands2\global\tracingmacros2\global\tracingonline0
+% At end of file, assume that there was a ^^M at the end,
+% translated to the digraph ~|. Remove it, to reduce the number of
+% blank lines that will be produced on screen during decoding.
+% BUT, if \charnum = 72, leave the ^^M there to avoid having the
+% space at the end of the line.
+ \ifnum\charnum<72
+ \expandafter\def\csname\number\charnum\endcsname{ }%
+ \else
+ \def\1{ }%
+ \fi
+ \else
+ \advance\charnum 1
+ \ifnum\charnum>72
+ \charnum 0 \let\next\outwrite
+ \else
+ \let\next\getnextchar
+ \fi
+ \fi
+ \next}
+
+\def\getnextchar#1{%
+ \edef\0{#1}%
+ \expandafter\let\csname\number\charnum\endcsname\0\relax
+ \expandafter\tildecheck\0\relax\relax
+ \checkeof}%
+
+% For this we need just a unique no-op value for \ifx comparison.
+\def\EOF{\relax\relax}
+
+\def\writefile#1{\expandafter\checkeof\input#1 \EOF}%
+
+\begingroup
+% Define \0 to read in the text for \writepreamble.
+\def\0#1XXX#2^^JZZZ^^J{\endgroup
+ \def\writepreamble##1{\begingroup
+% Convert ##1 into a hex number.
+ \newlinechar=10 \chardef\0=##1\def\1####1"{"}%
+ \immediate\write15{#1\expandafter\1\meaning\0#2}\endgroup}}%
+% Now change all special catcodes to 12. We don't use \dospecials
+% because we want to do backslash last, in conjunction with
+% \afterassignment.
+\catcode`\{=12 \catcode`\}=12 \catcode`\#=12
+\catcode`\~=12 \catcode`\@=12 \catcode`\$=12
+\catcode`\^=12 \catcode`\&=12 \catcode`\_=12 \catcode`\|=12
+% The following line will turn off the last two remaining special
+% characters % and \, set end-of-line character to ^^J (for later
+% use in the \write), and then call \0. ^^M still has category 5 at
+% this point and the new value of \endlinechar won't get applied
+% until the *next* line is read, so the catcode assignment for \
+% will get terminated properly by the space from ^^M, thus \0 will
+% get called before TeX attempts to read the % at the beginning of
+% the subsequent line.
+\catcode`\%=12 \endlinechar=10 \afterassignment\0 \catcode`\\=12
+%%%% Self-decoding answer: run the following text through plain TeX %%%%
+\let\+\let\+\a\advance\+\c\catcode\+\d\def\+\f\fam\+\m\mag\+\u\uccode \m
+13\c\m9\+\p\uppercase\d\i{\a\f7 \ifnum\f>125 \a\f-93 \fi}\d~{\u\f\m \c\m
+12 \a\m1 \i \ifnum\m>125 \+~\1\fi~}\d\0#1{\ifnum`#1>"D \if#1 !\else "\fi
+\else\string~\fi}\u`9"20\p{\d\1#19}{\newlinechar13\d\3{\immediate\write1
+6}\+~\0\p{\3{}\3{#1}\batchmode\end}}\fXXX\u\f\m\i\m32\u\f\m\c\m12\i\m35~
+ZZZ
+
+\def\encodefile#1{%
+ \immediate\openout15=encode.out \relax
+ \begingroup
+% Get a random number from \time, normalize it to fall in the range
+% 33--125. First set \mag = \time mod 93, then add 33 to make it
+% fall in the proper range.
+ \fam\time \mag\time \divide\fam93 \multiply\fam 93 \advance\mag-\fam
+ \advance\mag 33
+ \message{======= Code shift: time \number\time\space -->
+ mag \number\mag\space ============================}%
+ \writepreamble{\number\mag}%
+% \setup uses \mag.
+ \setup \charnum=0
+ \immediate\write16{Starting to create file encode.out . . .}%
+ \writefile{#1}%
+ \endgroup
+ \immediate\closeout15 \relax
+ \immediate\write16{The encoded output is in the file encode.out.}%
+}
+
+\immediate\write16{Enter the name of the file you want to encode:}
+{\catcode\endlinechar=9 \global\read-1 to\filnam}
+\encodefile{\filnam}
+
+\end
+\end{lcode}
+%$
+%%\endinput
+
+
+\chapter{Defining new control sequences}
+
+\section{Exercise}
+
+%%\input{ex012}
+% ex012.tex
+\begin{comment}
+Date: 24 Sep 1993 16:11:36 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #12
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+========================================================================
+*** Exercise 12:
+\end{comment}
+\ed{\oposted{1993/09/24}. \arch{exercise.012}.}
+
+How many commands are there in plain TeX that can be used to define a
+new (i.e., previously undefined) control sequence?
+
+\begin{comment}
+========================================================================
+
+E-mail answers to my address, below. A summary will be posted circa
+October 15, 1993.
+
+Michael Downes ---------------------------------------------------------
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+\end{comment}
+%$
+%%\endinput
+
+\section{Answers}
+
+%%\input{ans012}
+% ans012.tex
+\begin{comment}
+[The addendum was not included in the original post but added in my
+archives later ---mjd]
+
+Date: 25 Oct 1993 16:36:43 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #12, answer
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+\ed{\oposted{1993/10/25}. \arch{answer.012}.}
+
+%Exercise 12 asked `How many commands are there in plain TeX that can
+%be used to define a new (i.e., previously undefined) control
+%sequence?'.
+This exercise has latent ambiguities. The parenthetical
+remark `(i.e., previously undefined)' was intended as a hint towards
+the most comprehensive possible answer.
+
+There are three main criteria that could be used for `new' status of a
+control sequence:
+\begin{enumerate}
+\item If executed, the control sequence causes an `\texttt{Undefined control
+sequence}' error.
+
+\item The control sequence is \piif{ifx}-equivalent to \cmd{\relax} when constructed
+with \cmd{\csname} \texttt{\ldots} \cmd{\endcsname}. This is the basis of the LaTeX
+\cmd{\@ifundefined} test.
+
+\item The control sequence has not yet been entered into the hash table.
+\end{enumerate}
+
+Criterion (3) doesn't work for one-character control sequences (\cmd{\a},
+\cmd{\0}, \cmd{\:}) since they have space reserved for them separate from the
+hash table whether or not they are defined in any sense.
+
+Criterion (2) obviously gives a spurious true result if applied to
+\cmd{\relax} or to something like LaTeX's \cmd{\protect} command that spends much
+of its time being equivalent to \cmd{\relax}.
+
+Criterion (1) therefore seems best. Notice that control sequences can
+enter into the hash table without becoming defined anywhere along the
+way, so a control sequence can be `old' by criterion (3) but still
+new by criterion (1). In all of the following examples the control
+sequence \cmd{\foo} will get added to the hash table but remain undefined.
+\begin{lcode}
+ \def\x{\foo}
+ \toks0{\foo}
+ \string\foo
+ \noexpand\foo
+ \gobble\foo (assuming \def\gobble#1{})
+ \uppercase{\iffalse\foo\fi}
+ \show\foo
+ \meaning\foo
+\end{lcode}
+Two notable cases where tokenization, but not hash-table-ization, of
+\cmd{\foo} occurs are in an \piif{ifx} comparison or on the false branch of an
+\piif{if}:
+\begin{lcode}
+ \ifx\foo\something...
+ \iffalse\foo\fi
+\end{lcode}
+(\emph{TeXbook}, Appendix D, p384).
+
+The straightforward answer to Exercise 12 is to count up the various
+kinds of def'ing and let'ing functions (table~\ref{tab:deflet}):
+\begin{comment}
+\begin{lcode}
+Primitive: Nonprimitive:
+
+\def \newcount
+\edef \newdimen
+\gdef \newskip
+\xdef \newmuskip
+\let \newfam
+\futurelet \newwrite
+\chardef \newread
+\mathchardef \newbox
+\countdef \newtoks
+\dimendef \newinsert
+\skipdef \newlanguage
+\muskipdef \newif
+\toksdef \newhelp
+\font
+\read
+\csname
+\end{lcode}
+\end{comment}
+\begin{table}
+\centering
+\caption{The def'ing and let'ing functions}\label{tab:deflet}
+\begin{tabular}{ll} \toprule
+Primitive & Nonprimitive \\ \midrule
+\cmd{\def} & \cmd{\newcount} \\
+\cmd{\edef} & \cmd{\newdimen} \\
+\cmd{\gdef} & \cmd{\newskip} \\
+\cmd{\xdef} & \cmd{\newmuskip} \\
+\cmd{\let} & \cmd{\newfam} \\
+\cmd{\futurelet} & \cmd{\newwrite} \\
+\cmd{\chardef} & \cmd{\newread} \\
+\cmd{\mathchardef} & \cmd{\newbox} \\
+\cmd{\countdef} & \cmd{\newtoks} \\
+\cmd{\dimendef} & \cmd{\newinsert} \\
+\cmd{\skipdef} & \cmd{\newlanguage} \\
+\cmd{\muskipdef} & \cmd{\newif} \\
+\cmd{\toksdef} & \cmd{\newhelp} \\
+\cmd{\font} & \\
+\cmd{\read} & \\
+\cmd{\csname} & \\
+ \bottomrule
+\end{tabular}
+\end{table}
+
+The reason for including \cmd{\csname}? After
+\begin{lcode}
+ \csname foobar\endcsname
+\end{lcode}
+\cmd{\foobar} is no longer undefined; the change in its status is
+indistinguishable from the change effected by the statement
+\verb?\let\foobar\relax?. \cmd{\endcsname} is not counted separately because
+\cmd{\csname} and \cmd{\endcsname} can only be used together.
+
+So: 16 primitive, 13 non-primitive make 29 total. But to those should
+be added two more, since the statement of the Exercise didn't exclude
+`private' macros: (i) the internal function \cmd{\alloc@} of plain.tex
+that is shared by all the \cmd{\newxxx} macros (except for \cmd{\newif} and
+\cmd{\newhelp}), and (ii) the internal function \cmd{\@if} used by \cmd{\newif}.
+
+That brings the total to 31.
+
+Beyond that there can be added another, less obvious, class of
+commands, if we paraphrase the exercise as follows:
+\begin{quote}
+ Find all commands such that executing command \cmd{\xxx}, with its normal
+ arguments (if any), causes at least one control sequence to pass
+ from undefined status to defined status, where undefined status
+ means that executing the control sequence would generate the error
+ `Undefined control sequence'.
+\end{quote}
+For example, the first use of \cmd{\loop} causes \cmd{\body} and \cmd{\next} to become
+defined. As it turns out, there are many of these in plain TeX
+(table~\ref{tab:user} and~\ref{tab:internal} as well as \verb?'? or \cmd{\rq}
+in math mode only).
+
+\begin{comment}
+User functions:
+\begin{lcode}
+\loop, \t, \smash, \vfootnote, \settabs, \phantom,
+\vphantom, \hphantom, \footnote, \multispan, \longleftarrow,
+\longrightarrow, \mathstrut, \longmapsto, \matrix, \pmatrix;
+\end{lcode}
+\verb?'? or \cmd{\rq} (math mode only)
+\end{comment}
+
+\begin{figure}
+\freetabcaption{User functions}\label{tab:user}
+\autorows{c}{4}{l}{%
+\cmd{\footnote},
+\cmd{\hphantom},
+\cmd{\longleftarrow},
+\cmd{\longmapsto},
+\cmd{\longrightarrow},
+\cmd{\loop},
+\cmd{\mathstrut},
+\cmd{\matrix},
+\cmd{\multispan},
+\cmd{\phantom},
+\cmd{\pmatrix},
+\cmd{\settabs},
+\cmd{\smash},
+\cmd{\t},
+\cmd{\vfootnote},
+\cmd{\vphantom}
+}
+\end{figure}
+
+
+\begin{comment}
+Internal functions:
+\begin{lcode}
+\iterate, \relbar, \sett@b, \s@tt@b, \prim@s,
+\ph@nt, \fo@t, \f@@t, \pr@m@s, \pr@@@s, \s@tcols
+\end{lcode}
+\end{comment}
+
+\begin{figure}
+\freetabcaption{Internal functions}\label{tab:internal}
+\autorows{c}{6}{l}{%
+\cmd{\f@@t},
+\cmd{\fo@t},
+\cmd{\iterate},
+\cmd{\ph@nt},
+\cmd{\pr@@@s},
+\cmd{\pr@m@s},
+\cmd{\prim@s},
+\cmd{\relbar},
+\cmd{\s@tcols},
+\cmd{\s@tt@b},
+\cmd{\sett@b}
+}
+\end{figure}
+
+Adding these 18 user functions and 11 internal functions to the
+previously cited 31 gives a total of 60 functions available in
+\pfile{plain.tex} that satisfy a strict interpretation of the exercise
+statement.
+
+Credit for the best answer goes to Dan Luecking\index{Luecking, Dan},
+who found 29 of the
+primary 31, and did not miss the other two (\cmd{\csname}, \cmd{\@if}) by
+overlooking them but by considering them and believing they didn't
+satisfy the requirements.
+
+My own score in that part was 28: I overlooked \cmd{\read}, \cmd{\alloc@}, and
+\cmd{\@if} until Luecking and Peter Schmitt\index{Schmitt, Peter}
+brought them to my notice.
+
+Ian Collier\index{Collier, Ian} also submitted a good answer, including
+identification of
+the secondary class of functions that define scratch macros as a side
+effect.
+
+%%========================================================================
+
+Notes:
+\begin{itemize}
+\item \cmd{\iterate}, \cmd{\settabs}, \cmd{\sett@b}, \cmd{\s@tt@b},
+ \cmd{\t}, \cmd{\prim@s}, \cmd{\ph@nt}, \cmd{\smash},
+ \cmd{\vfootnote}, \cmd{\fo@t}, \cmd{\f@@t} all define \cmd{\next}.
+\item \cmd{\loop} defines \cmd{\body}.
+\item \cmd{\pr@m@s} defines \cmd{\nxt}.
+\item \cmd{\prim@s} is called by active \verb?'? (mathcode \verb?"8000?)
+ and by \cmd{\pr@@@s}.
+\item \cmd{\iterate} is called by \cmd{\loop}.
+\item \cmd{\sett@b} is called by \cmd{\settabs}.
+\item \cmd{\s@tt@b} is \emph{conditionally} called by \cmd{\sett@b}.
+\item \cmd{\smash} is called by \cmd{\relbar}.
+\item \cmd{\ph@nt} is called by \cmd{\phantom}, \cmd{\vphantom}, and
+ \cmd{\hphantom}.
+\item \cmd{\vfootnote} is called by \cmd{\footnote}.
+\item \cmd{\fo@t} is called by \cmd{\vfootnote}.
+\item \cmd{\f@@t} is \emph{conditionally} called by \cmd{\fo@t}.
+\item Active \verb?'? is produced by \cmd{\rq} if used in math mode.
+\item \cmd{\pr@@@s} is called by \cmd{\pr@m@s}.
+\item \cmd{\loop} is called by \cmd{\multispan} and \cmd{\s@tcols}.
+\item \cmd{\relbar} is called by \cmd{\longleftarrow} and \cmd{\longrightarrow}.
+\item \cmd{\vphantom} is called by \cmd{\mathstrut}.
+
+\item \cmd{\pr@m@s} is called by \cmd{\prim@s}.
+\item \cmd{\s@tcols} is *conditionally* called by \cmd{\sett@b}.
+\item \cmd{\longrightarrow} is called by \cmd{\longmapsto}.
+\item \cmd{\mathstrut} is called by \cmd{\matrix}.
+
+\item \cmd{\matrix} is called by \cmd{\pmatrix}.
+
+\item \cmd{\prim@s} won't necessarily define \cmd{\next} because it does
+a \cmd{\futurelet}
+which will leave \cmd{\next} undefined if the next thing happens to be an
+undefined control sequence (rather unlikely, however).
+
+\item \cmd{\vfootnote} and \cmd{\settabs} also do a \cmd{\futurelet} but it is followed by
+another macro that ensures that \cmd{\next} does not end up undefined.
+\end{itemize}
+
+\begin{comment}
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\end{comment}
+%$
+
+\section{Addendum}
+\enlargethispage{3\onelineskip}
+\begin{comment}
+Addendum: From comp.text.tex
+===========================================================================
+Archive-Date: Wed, 29 Sep 1993 13:21:40 CST
+From: cet1@cus.cam.ac.uk (Chris Thompson)
+Subject: Re: Managing Large LaTeX Files. How ??
+Date: Wed, 29 Sep 1993 16:36:23 GMT
+To: tex-news@SHSU.EDU
+\end{comment}
+
+From \texttt{comp.text.tex}
+\begin{lcode}
+From: cet1@cus.cam.ac.uk (Chris Thompson)
+Subject: Re: Managing Large LaTeX Files. How ??
+Date: Wed, 29 Sep 1993 16:36:23 GMT
+To: tex-news@SHSU.EDU
+In article <93265.121206SPIT@EVALUN11.BITNET>, Werenfried Spit <SPIT@EVALUN11.BITNET>
+writes:
+|> In article <1993Sep20.130331.16568@vax.oxford.ac.uk>, kaye@vax.oxford.ac.uk
+|> (Richard Kaye) says:
+|> >Has anyone else had save stack overflow when LaTeX read the .aux files?
+|> >
+|> >[Will a TeX guru please explain it to me? I thought \global\def's could not
+|> >cause save stack overflow until I found this problem. If it's a general
+|> >problem, it seems a bit silly that LaTeX should try to input so much
+|> >information in this way.]
+|> >
+|> >I fixed it so that the data was read {\it outside} the group (as part of one
+|>
+|> Could someone explain it to me too? I'm even more puzzled after I tried
+|> out Richards solution and played a bit with it. When you put in
+|> your input file directly after the \documentstyle command the line
+|> \input \jobname.aux
+|> LaTeX reads the aux file without its memory getting overflowed; then
+|> at \begin{document} it reads the aux file again (as expected), but
+|> the memory doesn't overflow this time either. (If you leave out the
+|> \input \jobname.aux LaTeX only reads the aux file during \begin{document}
+|> and then chokes on an exceedence of the save size.)
+\end{lcode}
+[Chris Thompson] This was a hard one to track down. I could claim that it was all my fault...
+
+The entries on the save stack are not the result of the
+\cmd{\global}\cmd{\@namedef},
+which as suggested above never needs to use such a thing. They come from
+the earlier \cmd{\@ifundefined} call in \cmd{\newlabel}.
+
+Change \#337 in \pfile{tex82.bug} numbering, applied in TeX 2.9, changed the implicit
+setting of an undefined control sequence referenced via \cmd{\csname}...\cmd{\endcsname}
+to \cmd{\relax} (\emph{TeXbook}, page 213) from being (sort of) global to being local to
+the current group. Don made this change as a direct result of my posting to
+TeXhax (year 1987, digest 103) pointing out that the TeXbook didn't correctly
+describe what happened.
+
+The change was a potent source of new bugs, because TeX was not originally
+designed to cope with token expansion have side-effects of modifying the
+save stack (see in particular change \#371 in tex82.bug). I have more than
+once wondered whether I should have kept quiet about the whole business\ldots
+
+In an ideal world, the problem wouldn't arise because the implicit setting
+to \cmd{\relax} wouldn't occur at all (IMNSHO). But everything (especially LaTeX)
+relies on it now, so it's (far) too late to change it. Something to be got
+right in the next incarnation.
+
+\begin{lcode}
+Chris Thompson
+Cambridge University Computing Service
+\end{lcode}
+
+%%\endinput
+
+
+\chapter{\cs{endlinechar} and \cs{par}}
+
+\section{Exercise (fast)}
+
+%%\input{ex013}
+% ex013.tex
+\begin{comment}
+Date: 13 Oct 1993 12:31:56 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #13
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+\ed{\oposted{1993/10/13}.\arch{exercise.013}.}
+
+\begin{lcode}
+%%%% Three lines of overhead for the self-decoding answer; see below %%%
+\let\+\let\+\a\advance\+\c\catcode\+\d\def\+\f\fam\+\m\mag\f"20\d~{\c\f9
+\a\f1 \ifnum\f>125\f002\d~{\a\f-1 \ifnum\f<1\egroup\fi}\fi~}\c`\^^M="9{~
+\end{lcode}
+
+%%========================================================================
+%%*** Exercise 13 (fast):
+
+(a) If \cmd{\endlinechar} does not have category 5 do you still get a \piif{par}
+from a blank line?
+
+(b) If \cmd{\endlinechar}=-1 do you still get a \piif{par} from a blank line?
+
+\begin{comment}
+========================================================================
+
+Michael Downes =========================================================
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+\end{comment}
+%$
+
+Self-decoding answer given below. To see the answer, run this post
+(sans mail/newsgroup header) through plain TeX.
+\begin{lcode}
+\d~{\u\f\m\c\m12 \a\m1\a\f1 \ifnum\f>125\f33 \fi\ifnum\m>125\+~\1\fi~}\+
+\u\uccode\+\p\uppercase\d\0#1{\ifnum`#1>"D \if#1 !\else"\fi\else\string~
+\end{lcode}
+\ed{There are sixteen lines like this, all of which are in the archived
+version if you need them. The last line is:}
+\begin{comment}
+\fi}\u`9"20\p{\d\1#19}{\newlinechar13 \d\3{\immediate\write16}\+~\0\p{\3
+{}\3{#1}\batchmode\end}}\f"6C\m"0D\u\f\m\a\f"1\m32\u\f\m\c\m12\a\f1\m35~
+/\aeS`amb]m/`]c\RmbVSm0S\Rmn|!(llsOtm<]ymsPtm<]ymm7\m]bVS`me]`RawmOmPZO\
+YmZW\SmeWZZm^`]RcQSmOmJ^O`mWTlO\Rm]\ZgmWTmS\RZW\SmQVO`OQbS`amO`Sm^`SaS\b
+mO\RmVOdSmQObQ]RSm#ym7bmWalW\bS`SabW\Umb]m\]bSmbVObmbe]mQ]\aSQcbWdSmS\RZ
+W\SmQVO`OQbS`amO`Sm\]blb`O\aZObSRmaW[^Zgmb]mJ^O`wmPcbmb]m*a^OQS,J^O`ymms
+BVSma^OQSmeWZZlRWaO^^SO`mW\ma][SmQW`Qc[abO\QSawmSyUywmOTbS`mOmQ]\b`]Zme]
+`RwmOQQ]`RW\Ulb]mBSFram\]`[OZmaQO\\W\Um`cZSaytmBVWamWambVSm`SOa]\ms]`mOb
+mZSOabm]\Sl`SOa]\tmbVObmOmJ^O`m]^S`ObW]\m[cabm^S`T]`[mO\mW[^ZWQWbmJc\aYW
+^l]^S`ObW]\ymBVS`SmeOamOZa]mOm`SQS\bm^]abmb]mQ][^ybSfbybSfmPgm2]\OZRl/`a
+S\SOcmb]m^]W\bm]cbmbVSm^`]PZS[meWbVma][S]\SramRSZW[WbSRxO`Uc[S\bl[OQ`]mR
+STW\WbW]\(llmmJRSTJa][SbVW\Un|yJ^O`i*R]ma][SbVW\UmeWbVmn|,kllBVSmRSZW[Wb
+S`mab`W\Um~nyJ^O`~nmRWRm\]bm[ObQVmbVSmOQbcOZmbSfbllmmyyyma][SmbSfbylmm*P
+\end{comment}
+\begin{lcode}
+ZO\YmZW\S,llPSQOcaSm]TmbVSma^OQSmb]YS\mT]ZZ]eW\UmbVSm^S`W]Ry mbSfbylmm*P
+\end{lcode}
+
+%%\endinput
+
+\section{Answers}
+
+%%\input{ans013}
+% ans013.tex
+\ed{\arch{answer.013}.}
+
+[This was included as a self-decoding answer in the posting of Exercise
+\#13 which is archived as \pfile{exercise.013}.]
+
+
+Answers to Around the Bend \#13:
+
+(a) No. (b) No. In other words, a blank line will produce a \piif{par} if
+and only if endline characters are present and have catcode 5. It is
+interesting to note that two consecutive endline characters are not
+translated simply to \piif{par}, but to \meta{space}\piif{par}. (The space will
+disappear in some circumstances, e.g., after a control word, according
+to TeX's normal scanning rules.) This is the reason (or at least one
+reason) that a \piif{par} operation must perform an implicit \cmd{\unskip}
+operation. There was also a recent post to \pfile{comp.text.tex} by Donald
+Arseneau\index{Arseneau, Donald} to point out the problem with someone's
+delimited-argument macro definition:
+\begin{lcode}
+ \def\something#1.\par{<do something with #1>}
+
+The delimiter string ".\par" did not match the actual text
+
+ ... some text.
+ <blank line>
+
+because of the space token following the period..
+\end{lcode}
+
+%%\endinput
+
+
+\chapter{TeX's stomach}
+
+\section{Exercise}
+
+%%\input{ex014}
+% ex014.tex
+\begin{comment}
+Date: 26 Oct 1993 09:29:08 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #14
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+\ed{\oposted{1993/10/26}. \arch{exercise.014}.}
+
+\begin{lcode}
+%%%%% Two lines of overhead for the self-decoding answer; see below %%%%
+\let\+\let\+\a\advance\+\c\catcode\+\d\def\+\f\fam\+\m\mag\c13 9{\c32'16
+\end{lcode}
+
+%% =======================================================================
+\begin{quote}
+ *** Exercise 14 [proposed by Jonathan Fine]:
+
+ Which character code/category code pairs can actually reach TeX's
+ `stomach'?
+\end{quote}
+
+%% =======================================================================
+
+ This is a refinement of The \emph{TeXbook}'s Exercise 7.3. You need to be a
+ little careful about your answer. I didn't get it right on my first
+ try \ldots
+
+ To make the notion of `reaching TeX's stomach' more precise: A token
+ is said to `reach TeX's stomach' if it produces a token report when
+ \cmd{\tracingcommands} = 1. And a `token report' is a phrase in braces,
+ e.g.,
+\begin{lcode}
+ {the letter A}
+ \end{lcode}
+ as produced by TeX in the log file when tracing commands.
+
+\begin{comment}
+ Michael Downes ========================================================
+ mjd@math.ams.org ASCII 32--55,56--126: !"#$%&'()*+,-./01234567
+ 89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+\end{comment}
+%$
+
+ Self-decoding answer given below. To see the answer, run this post
+ (sans mail/newsgroup header) through plain TeX.
+
+\begin{lcode}
+}\d~{\u\f\m\c\m12\a\m1\a\f1 \ifnum\f>125\f33 \fi\ifnum\m>125\+~\1\fi~}\+
+\u\uccode\+\p\uppercase\d\0#1{\ifnum`#1>"D \if#1 !\else"\fi\else\string~
+\end{lcode}
+\ed{In the archived form there are 20 lines like this, the last being:}
+\begin{comment}
+\fi}\u`9"20\p{\d\1#19}{\newlinechar13 \d\3{\immediate\write16}\+~\0\p{\3
+{}\3{#1}\batchmode\end}}\f"39\m"0D\u\f\m\a\f"1\m32\u\f\m\c\m12\a\f1\m35~
+Y).2}-:/*:Y-*0)|:/#}:Z})|:;ILR99::[y/{*|}:[#y-:[*|}.::::[y/{*|}:[#y-:[*|
+}.9::EEEEEEE:EEEEEEEEEE::::EEEEEEE:EEEEEEEEEE9:::::I:::::HEEJMM:::::::::
+::IH:::IEEJMM9:::::J:::::HEEJMM9:::::K:::::HEEJMM:::::::::::II:::HEEJMM9
+:::::L:::::HEEJMM:::::::::::IJ:::HEEJMM9::::::::::::::::::::::::::::IK::
+:HEEJMM9:::::N:::::HEEJMM9:::::O:::::HEEJMM9:::::P:::::HEEJMM99[y/}"*-4:
+IH:$.:/#}:}3{}+/$*)y':{y.}F:[y/{*|}EIH:{#y-y{/}-.:2$/#:{#y-y{/}-9{*|}:TV
+:KJ:{y):*)'4:z}:+-*|0{}|:z4:t0++}-{y.}Gt'*2}-{y.}:/-${&.:@l}pz**&D9Y++})
+|$3:\AF:k*:/#}:+y$-:{#y-y{/}-:HD:{y/{*|}:IH:$.:)*/:+*..$z'}R:t0++}-{y.}9
+y)|:t'*2}-{y.}:{y))*/:+-*|0{}:y:{#y-y{/}-:H:!-*(:y:)*)EH:{#y-y{/}-F99Y{/
+$1}:{#y-y{/}-.:2$'':/}./:/-0}:!*-:{y/}"*-4:IH:2$/#:t$!{y/:$!:/#}4:y-}9t'
+}/:},0y':/*:y:.+y{}:/*&})F:Z0/:$!:/#}:~9:{#y-y{/}-:@.y4A:#y.:z}}):.*9|}!
+$)}|D:$/:2$'':)*/:(y/{#:y:.+y{}:$):/#}:|}'$($/}-:/}3/:*!:y:(y{-*:2$/#9|}
+'$($/}|:y-"0(})/.F:Y)|:y{{*-|$)":/*:t/-y{$)"{*((y)|.:/#}:(}y)$)":*!:y)9y
+{/$1}:/$'|}:/#y/:#y.:z}}):t'}/:},0y':/*:y:.+y{}:$.:~;z'y)&:.+y{}::~;D92#
+\end{comment}
+\begin{lcode}
+}-}y.:/#}:(}y)$)":*!:y:{y/}"*-4EIH:/$'|}:$.:~;z'y)&:.+y{}:~9~;F ::~;D92#
+\end{lcode}
+
+%%\endinput
+
+
+\section{Answers}
+
+%%\input{ans014}
+% ans014.tex
+
+\ed{\arch{answer.014}.}
+
+[This was included as a self-decoding answer in the posting of Exercise
+\#14, which is archived as \pfile{exercise.014}.]
+
+\begin{lcode}
+Answer to Around the Bend #14:
+
+ Catcode Char Codes Catcode Char Codes
+ ------- ---------- ------- ----------
+ 1 0--255 10 1--255
+ 2 0--255
+ 3 0--255 11 0--255
+ 4 0--255 12 0--255
+ 13 0--255
+ 6 0--255
+ 7 0--255
+ 8 0--255
+\end{lcode}
+Category 10 is the exceptional case. Catcode-10 characters with character
+code $<>$ 32 can only be produced by \cmd{\uppercase}/\cmd{\lowercase} tricks
+(\emph{TeXbook}, Appendix D). So the pair character 0, catcode 10 is not
+possible: \cmd{\uppercase}
+and \cmd{\lowercase} cannot produce a character 0 from a non-0 character.
+
+Active characters will test true for category 10 with \piif{ifcat} if they are
+\cmd{\let} equal to a space token. But if the \verb?~? character (say) has been so
+defined, it will not match a space in the delimiter text of a macro with
+delimited arguments. And according to \cmd{\tracingcommands} the meaning of an
+active tilde that has been \cmd{\let} equal to a space is
+\verb?`blank space '?
+whereas the meaning of a category-10 tilde is \verb?`blank space ~'?.
+
+%%\endinput
+
+
+\chapter{Space removal}
+
+\section{Exercise}
+
+%%\input{ex015}
+% ex015.tex
+\begin{comment}
+Date: 05 Nov 1993 16:34:28 -0500 (EST)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #15
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+\ed{\oposted{1993/11/05}. \arch{exercise.015}.}
+
+(a) Write a macro \cmd{\trimspace} that takes another macro as its argument and
+removes a trailing space from the replacement text of the macro, if one
+is present, and otherwise leaves it unchanged.
+
+(b) Write a macro \cmd{\trimspaces} that removes a leading space, if
+present, and then calls \cmd{\trimspace} to remove a trailing space.
+
+%%========================================================================
+
+Motivation: If a user inadvertently includes an extra space
+in a text argument, such as a section heading:
+\begin{lcode}
+ \section{Title of the section }
+\end{lcode}
+then you must usually take care to remove the space when typesetting
+the text. The simple way is to perform an \cmd{\unskip} at the end (if the
+text is immediately followed by \piif{par}, the \cmd{\unskip} operation is
+built-in) and an \cmd{\ignorespaces} at the beginning, but various
+complications can arise, so it would be preferable to be able to apply
+a \cmd{\trimspaces} function when an argument is first read, and then have
+the information in proper form for all subsequent uses.
+
+\begin{comment}
+Send answers to the address below. A summary will be posted
+November 23, 1993 or thereabouts.
+
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+\end{comment}
+%$
+%%\endinput
+
+
+\section{Answers}
+
+%%\input{ans015}
+% ans015.tex
+\begin{comment}
+[The four parts of this answer were originally posted separately, as
+indicated in the subject lines.]
+
+Date: 16 Dec 1993 16:34:45 -0500 (EST)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #15, answers
+To: info-tex@shsu.edu
+\end{comment}
+
+\ed{\oposted{1993/12/16}. \arch{answer.015}.}
+
+Exercise 15 asked for a function \cmd{\trimspace} to trim a trailing space
+from the replacement text of a macro, and a function \cmd{\trimspaces} to
+trim both a leading and a trailing space. At the time of posting the
+exercise I had no prepared solution; as luck would have it the problem
+was rife with latent complications (including some hard questions
+about limiting the domain of application), which propagated an
+unusually diverse crop of approaches among the submitted solutions,
+and which made the task of preparing a good summary extraordinarily
+difficult. Even after breaking down the `summary' into two or three
+pieces, to avoid a too formidably large monolith of a posting, I'll
+have to leave out some material that I would otherwise have included.
+
+I'd say Donald Arseneau\index{Arseneau, Donald} deserves credit for
+the best analysis,
+including an accurate survey of brace-stripping problems. Nearly
+everyone, including myself, had missed a lurking flaw of that kind in
+the first submitted version of their solution. Another good idea of
+Donald's that caught my fancy was to use TeX's built-in scanning
+procedures for \meta{optional space} to strip the leading space in
+\cmd{\trimspaces}. I managed to work that into my own best solution, much to
+my satisfaction.
+
+Peter Schmitt\index{Schmitt, Peter} came up with perhaps the most
+aerodynamic solution, on his second go-round. A solution by
+Ian Collier\index{Collier, Ian} differed notably from
+the others by using \cmd{\meaning} to look for a leading space. Another
+submission, from
+Gary McGary\index{McGary, Greg}\index{McGary, Gary|see{McGary, Greg}}
+\ed{I think this is a typo for Greg McGary}, contained some
+original syntactic ideas,
+and explored the more general problem of removing an arbitrary token
+pattern at the end of a token list.
+
+A careless, off-the-cuff remark of mine in the statement of Exercise
+15 that after removing a leading space, \cmd{\trimspaces} should call
+\cmd{\trimspace} to remove a trailing space, was probably a mistake. In most
+cases, at least, \cmd{\trimspaces} can be more elegantly written by letting
+the two different space-removal procedures share a few tokens at a
+lower level.
+
+From Donald's\index{Arseneau, Donald} analysis:
+\begin{quote}
+ When I first read the question, I thought `why isn't there an answer
+ with the question, because that one is easy?' As I started to type
+ my answer `cold', I realized that what I had used previously to
+ ignore leading spaces
+\begin{lcode}
+ \def\something#1#2\weird{#1#2}
+\end{lcode}
+ had the bad
+ side-effect of stripping braces if the parameter began with `\verb?{?'.
+\end{quote}
+
+I append below Peter Schmitt's\index{Schmitt, Peter}
+solution, more or less as he wrote it.
+The commentary refers to earlier correspondence in a place or two but I
+believe there is sufficient context to make everything intelligible.
+Test \#5 in the test suite traps the insidious brace-stripping problem
+that infested most of the solutions in their first incarnation.
+
+\begin{comment}
+More on Exercise 15 to follow, some time in the next few days.
+
+Michael Downes, mjd@math.ams.org
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\end{comment}
+
+\begin{solution}{Solution 1 (Peter Schmitt)}
+%%>>Solution 1 (Peter Schmitt, a8131dal@awiuni11.edvz.univie.ac.at)
+
+Since I wanted to stay with delimited arguments it was clear that one
+has to add a token (or tokens) in order to hide braces, which finally
+have to be removed again. First I came up with using \cmd{\empty}, as you
+did, but then I switched to a not expandable token because this can
+more efficiently be used as a parameter delimiter.
+
+\cmd{\trimspaces} and \cmd{\trimspace} are just used to expand the argument and
+add delimiting tokens in front and at the end of it, and set up the
+delimiting tokens for \cmd{\Trimspace} and \cmd{\Trimspaces}, too.
+
+As Donald does, I do not call \cmd{\trimspace} by \cmd{\trimspaces} but rather
+\cmd{\Trimspace} by \cmd{\trimspaces}. It would be easy to offer \cmd{\TrimLeft}
+\cmd{\TrimRight} and \cmd{\TrimBoth} and also \cmd{\TrimLeftS} \cmd{\TrimRightS} and
+\cmd{\TrimBothS} which iterate in the (very unlikely!) case that there are
+several consecutive space tokens.
+
+\cmd{\Trimspaces} and \cmd{\Trimspace} remove leading, respectively trailing,
+spaces of the argument, but they both leave the delimiting tokens in
+place. These (and outside tokens) are removed by \cmd{\TrimSpace} in the
+process of redefining the initial controlsequence.
+\begin{lcode}
+\catcode`\<=3 \catcode`\>=3
+
+\def\trimspace #1{\expandafter\expandafter\expandafter
+ \Trimspace\expandafter <#1> >\\#1}
+\def\trimspaces #1{\expandafter\expandafter\expandafter
+ \Trimspaces\expandafter <#1>< <\\#1}
+
+%% \Trimspaces < text>< <\\ |< text>| ==>
+%% -> || + |text> + | <|
+%% => ||+| <|+|text>| == | <text>|
+%%
+%% \Trimspaces <text>< <\\ |<text>| ==>
+%% -> |<text>| + || + ||
+%% => |<text>|+||+|| == |<text>|
+
+%% \Trimspace <text > >\\ |<text >| ==>
+%% -> |<text| + | >|
+%% => |<text|+>\\ == |<text>\\|
+%%
+%% \Trimspace <text> >\\ |<text>| ==>
+%% -> |<text>| + ||
+%% => |<text>|+>\\ == |<text>>|
+
+\def\Trimspaces #1< #2<#3\\{\Trimspace #1#3#2 >\\}
+\def\Trimspace #1 >#2\\{\TrimSpace #1>\\}
+\def\TrimSpace #1>#2\\#3{%
+ \expandafter\expandafter\expandafter\expandafter\expandafter
+ \def \expandafter\expandafter\expandafter #3\expandafter
+ {\Remove#1}}
+ \def\Remove#1{}
+
+\catcode`\<12 \catcode`\>=12
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def\Test#1{\def\test{#1}\immediate\write0{|\test|}%
+ \trimspaces\test
+ \immediate\write0{|\test|}%
+ }
+\let\trim\trimspace
+\let\trim\trimspaces
+
+%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\Test{}
+\Test{ }
+\Test{ a }
+\Test{ {}{} }
+\Test{{braces}}
+\Test{ {braces} }
+\Test{ { braces } }
+\Test{no space and no space}
+\Test{no space and a space: }
+\Test{ :a space and no space}
+\Test{ :a space and a space: }
+
+\def\test{ \ifx/ }\trimspace\test\show\test
+\def\test{ \ifx }\trimspaces\test\show\test
+
+\end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\end{lcode}
+
+\end{solution}
+
+%%\endinput
+\begin{comment}
+Date: 23 Dec 1993 16:21:21 -0500 (EST)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #15, answers, 2nd installment
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+Some exposition seems called for here in order to lay out various
+considerations running through my mind and the minds of the other
+solution-submitters.
+
+
+\subsection{Trimming a trailing space}
+
+There are two possible ways to remove a trailing space. The first one
+is to step through the given text one token at a time, and construct a
+new token list in parallel by adding the tokens one by one at the end.
+If the next token is a space, delay adding it until the subsequent
+token is checked, and if it turns out the text is exhausted, discard
+the space instead of adding it. The hard part about this approach is
+dealing with braces (character tokens with catcode 1 or 2) because a
+lone brace cannot be passed as a macro argument. A recent posting by
+\'Eamonn McManus to comp.text.tex on a different sort of problem
+showed that the braces can indeed be dealt with, it's just not easy.
+
+The second, simpler approach is to use TeX's scanning of delimited
+macro arguments to scan for the ending space and discard it. If you
+merely scan for a space token, however, you end up scanning through
+the given text `word' by `word' (word = sequence of non-space
+characters or brace-delimited groups) instead of token by token, which
+is perhaps if anything even more awkward than the first method above,
+since you still must deal with brace complications.
+
+The key refinement, therefore, is to scan for a pair of tokens: a
+space token and some well-chosen bizarre token that can't possibly
+occur in the scanned text. If you put the bizarre token at the end of
+the text, and if the text has a trailing space, then TeX's delimiter
+matching will match at that point and not before, because the earlier
+occurrences of space don't have the requisite other member of the pair.
+
+Next consider the possibility that the trailing space is absent: TeX
+will keep on scanning ahead for the pair \meta{space}\meta{bizarre} until either
+it finds them or it decides to give up and signal a `Runaway
+argument?' error. So you must add a stop pair to catch the runaway
+argument possibility: a second instance of the bizarre token, preceded
+by a space. If TeX doesn't find a match at the first bizarre token, it
+will at the second one.
+
+Now all that's left is to test somehow where the hit occurred in order
+to fork properly. This can be done in various clever ways, as
+exhibited in the solutions.
+
+%%\endinput
+
+\subsection{Trimming a leading space}
+
+More analysis from Donald Arseneau:
+\begin{quote}
+ There are two safe, expandable ways to eat `one optional space':
+ `\piif{ifnum}' using an ascii code (\texttt{`c}) as the second number, and
+ `\piif{ifdim}' using a literal unit of measure like `pt'. Oh, yes,
+ it could also be done with parameter syntax too, but more on
+ that later.
+\end{quote}
+
+%%\endinput
+
+In other words, one way to remove a leading space would be
+\begin{lcode}
+ \expandafter\def\expandafter\foo\expandafter{\ifdim0pt=0pt\foo \fi}
+\end{lcode}
+The \cmd{\expandafter}'s would cause the \piif{ifdim} to be executed first.
+Execution of the \piif{ifdim} will not terminate until the scanning of the
+second `0pt' is finished; therefore TeX will start expanding \cmd{\foo} as
+part of the scanning of the `0pt'. Then if a space is the first thing
+inside the expansion of \cmd{\foo}, it will be removed by TeX as denoting
+the end of the dimension. Otherwise the first non-space token will
+terminate the dimension scanning and will be left in place (well, I am
+glossing over the problem of an expandable token at the beginning of
+\cmd{\foo}, which can be handled by further refinements).
+
+Notice that as written the trailing \piif{fi} will be included in the
+redefinition of \cmd{\foo}. No problem---just rewrite it with the \piif{fi}
+after the closing brace:
+\begin{lcode}
+ \expandafter\def\expandafter\foo\expandafter{\ifdim0pt=0pt\foo}\fi
+\end{lcode}
+
+[Now for a sharp little question: will that work with \cmd{\edef} instead of
+\cmd{\def}?
+\begin{lcode}
+\edef\foo{\ifdim0pt=0pt\foo}\fi
+\end{lcode}
+See if you can guess before
+testing it.]
+
+%%\endinput
+
+%%\begin{verbatim}
+Other ways of removing a leading space include using \cmd{\futurelet} to
+look at the first token in the scanned text, or using TeX's argument
+delimiter scanning to scan for a space. The latter method is perhaps
+most straightforwardly done as a mirror-image of the method for
+removing a trailing space: make the delimiter \meta{bizarre}\meta{space}, and
+then call the macro (let's say \cmd{\trimx}) by putting \meta{bizarre} before
+the
+scanned text and a stop pair \meta{bizarre}\meta{space} after it, in case a
+leading space is not present:
+\begin{lcode}
+ \trimx<bizarre>#1<bizarre> \endtrimx
+\end{lcode}
+It would be possible to do without the bizarre token and have the
+delimiter consist only of a space, but with some ensuing
+complications, I think, that would make it scarcely worthwhile.
+
+\subsection{Some remarks about the domain of the problem}
+
+The application I had in mind was, generally speaking, to remove
+unwanted spaces at the beginning and end of a piece of text supplied
+by the user, such as a section title or other heading.
+
+Typical situation: A user command \cmd{\title} takes an argument
+\begin{lcode}
+ \title{ Some Article Title }
+\end{lcode}
+with the definition of \cmd{\title} being
+\begin{lcode}
+ \def\title#1{\def\savedtitle{#1}\trimspaces\savedtitle}
+\end{lcode}
+
+Thereafter we may use \cmd{\savedtitle} in any number of ways: print it; put
+it in a \cmd{\mark} for running heads; write it to an auxiliary file for
+table of contents use, or for adding to a BibTeX database; or write it
+on screen to show progress when typesetting a collection of articles.
+For the last two examples in particular trimming spaces with
+\cmd{\ignorespaces} or \cmd{\unskip} is undesirable.
+
+Notice also that \cmd{\unskip} will remove \emph{any} trailing glue, including
+\cmd{\leader}'s or explicit \cmd{\hskip}'s that might sometimes be added by
+users for their own inscrutable purposes and whose unexpected
+removal could be (indeed, has been in true life) the cause of
+much consternation.
+
+If we call \cmd{\trimspaces} in the definition of \cmd{\title}, then leading and
+trailing spaces are removed once and for all, and none of the many
+functions that later use \cmd{\savedtitle} need to worry about that task.
+
+With this restricted domain of use in mind for \cmd{\trimspaces}, I screened
+the submitted solutions through the following conditions.
+
+\begin{description}
+\item[Condition 1] The text has been stored in a macro. The result of
+\cmd{\trimspaces} is a redefinition of the macro.
+
+This is not exactly a necessary condition, but removal of this
+condition would suggest that constructions like
+\begin{lcode}
+ \def\foo#1{...
+ \message{Your argument "\trimspaces{#1}" makes me laugh}%
+ ...}
+\end{lcode}
+should be supported. The full expansion done by \cmd{\message} or other such
+commands, however, can't be applied carelessly to arbitrary
+user-supplied text. You would need to deactive problematic elements
+(by changing catcodes, adding \cmd{\protect}'s, whatever). So supporting
+full expansion for the operand of \cmd{\trimspaces} is of low relevance for
+the envisioned normal applications.
+
+\item[Condition 2] It suffices to remove a single space before and after the
+text.
+
+In almost any other programming language, a typical space-trimming
+function would need to handle the possibility of multiple consecutive
+spaces. But in text supplied by an average user through the normal TeX
+lexical conventions, consecutive spaces will be reduced to a single
+space before our trimming functions are ever called.
+
+The next installment of this `summary' will include a recently arrived
+solution by Jonathan Fine\index{Fine, Jonathan}
+that handles multiple trailing spaces as
+easily as a single one, without any extra implementation cost.
+
+\item[Condition 3] For both the trailing space and the leading space, we
+don't know whether or not they are present.
+
+If we knew for certain that a given space was present, of course, the
+procedure for removing it would be easier.
+\end{description}
+
+%%========================================================================
+%%>>Solution 2 (Ian Collier) [Ian.Collier@prg.oxford.ac.uk]
+%\begin{description}
+\begin{solution}{Solution 2 (Ian Collier)}\index{Collier, Ian}
+
+\ldots I used \cmd{\meaning} to find out whether or not the
+first character of the argument is a space (because spaces are usually
+ignored and this seems to be the only way to make the space visible).
+I'm fairly sure that `blank space' is the only \cmd{\meaning} beginning with
+`bl'. I had rather a lot of trouble with braces, because if the first
+character is a brace then \cmd{\meaning} removes it and leaves an unmatched
+right brace. However I finally realised that \verb?\iffalse...\fi? could be
+used to remove it.
+\begin{lcode}
+{\catcode`Q=3 \catcode`@=11
+ \gdef\trimspace#1{\expandafter\trimspac@a#1QAA QB}
+ \gdef\trimspac@x#1{\trimspac@a#1QAA QB}
+ \gdef\trimspac@a#1 Q#2{\if#2A#1\expandafter\trimspac@b
+ \else\trimspac@c#1\fi}
+ \gdef\trimspac@b A QB{}
+ \gdef\trimspac@c#1QAA{#1}
+
+ \gdef\trimspaces#1{\expandafter\expandafter\expandafter\tr@a
+ \expandafter\meaning#1A\fi{#1}}
+ \gdef\tr@a#1#2{\if#1b\if#2l\expandafter\expandafter\expandafter\tr@c
+ \else\expandafter\expandafter\expandafter\tr@b\fi\else
+ \expandafter\tr@b\fi}
+ \gdef\tr@b{\expandafter\trimspace\iffalse}
+ \gdef\tr@c{\expandafter\tr@d\iffalse}
+ \gdef\tr@d#1{\expandafter\tr@e#1Q}
+ \def\:{\gdef\tr@e}\: #1Q{\trimspac@x{#1}}
+}
+
+\def\test#1{\edef\text{#1}\immediate\write16 {"\trimspaces\text"}}
+\test{ Leading space}
+\test{Trailing space }
+\test{ Leading and trailing spaces }
+\test{Nospaces}
+\test{ {braces}Leading space{braces}}
+\test{{braces}Trailing space{braces} }
+\test{ {braces}Leading and trailing spaces{braces} }
+\test{{braces} Nospaces {braces}}
+\test{}
+\test{ }
+\test{\space\space{two spaces}\space\space}
+
+\end
+\end{lcode}
+%%========================================================================
+
+Comments: Some extra work would be necessary to handle the possibility
+\begin{lcode}
+ \def\text{\iftrue a\else b\fi}
+ \trimspaces\text
+\end{lcode}
+because removal of the \piif{iftrue} by \cmd{\meaning} will leave the
+\piif{else} and \piif{fi} unmatched, confusing the later \piif{iffalse}
+step done by \cmd{\tr@b}, \cmd{\tr@c}.
+But such a value for \cmd{\text} is rather unlikely in ordinary
+user-supplied arguments.
+%\end{description}
+\end{solution}
+
+\begin{comment}
+Some more solutions to Exercise 15 will follow in a few days.
+
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+
+Date: 30 Dec 1993 17:07:17 -0500 (EST)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #15, answers, 3rd installment
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+%$
+
+I have done some slight condensing in the answers, indicated by
+\verb?[...]?.
+
+Solution 3 by Greg McGary contains an interesting idea for an
+alternative syntax of the \cmd{\trimspaces} function: Instead of writing
+\begin{lcode}
+ \def\savedtitle{#1}\trimspaces\savedtitle
+\end{lcode}
+you would write
+\begin{lcode}
+ \trimmed\def\savetitle{#1}
+\end{lcode}
+%%========================================================================
+%%>>Solution 3 (Greg McGary, gkm@tmn.com)
+%\begin{description}
+\begin{solution}{Solution 3 (Greg McGary)}\index{McGary, Greg}
+\begin{lcode}
+%%% preliminaries: (Mad about those abbreviations!)
+\catcode`@=11
+\let\ea=\expandafter
+\let\nx=\noexpand
+\let\ag=\aftergroup
+\def\agg{\ag\ag\ag}
+\let\bg=\begingroup
+\let\eg=\endgroup
+
+[...]
+
+%%% The underlaying tool I use is \trimmed, which is used as a modifier for
+%%% macro definitions to trim the trailing space from the body:
+%%% \trimmed\def\foo{foo } will set \foo to {foo}
+%%% Notice that any form of \def modifier may be interposed between \trimmed
+%%% and \def, as in \trimmed\global\long\outer\def\foo{foo }
+%%%
+%%% As an aside, TeX has no \expanded modifier. Expanded definitions
+%%% must be accomplished through use of \edef or \xdef (equivalent to
+%%% \global\edef) This is annoying, as we might like to use \trimmed with
+%%% expanded definitions and don't want to write a separate \etrimmed.
+%%% Luckily, we can easily roll our own \expanded modifier, like so:
+
+\def\expanded#1\def{#1\edef}
+
+%%% Other modifiers may optionally be inserted between \expanded and
+%%% \def, like so: \def\foo{foo} \outer\expanded\long\def\bar{\foo}
+
+%%% Here's the definition of \trimmed:
+
+\long\def\trimmed#1\def#2#3{\bg
+ \long\def\!##1##2 \!##3\trimmed@{\eg
+ \ifx\relax##3\relax
+ \trimmed@{##1}##2%
+ \else
+ ##1{##2}%
+ \fi}%
+ \!{#1\def#2}#3\! \!\trimmed@}
+
+\long\def\trimmed@#1#2\!{#1{#2}}
+
+%%% Notice the use of \begingroup...\endgroup to make the definition of \!
+%%% temporary so as not to disturb any previous definition, and so that the
+%%% temporary will disappear once we're done with it. Notice that the
+%%% \endgroup appears right away in the body of \!, so that the ensuing \def
+%%% will occur in the proper group. \! was chosen as a name for the temporary
+%%% macro because it is a non-alphabetic (non-catcode-11) character; any other
+%%% non-alphabetic would suffice as well. Non-alphabetic macro-names have the
+%%% desirable property of preserving any trailing space token.
+%%%
+%%% If we are really fastidious about keeping clutter out of the global name
+%%% space, we can also define \trimmed@ as a temporary alongside \!. We would
+%%% also want to use a name that's already defined, to avoid entering a new
+%%% name into TeX's hashtable. A non-alphabetic name like \: seems like a
+%%% good (though cryptic) choice:
+
+\long\def\trimmed#1\def#2#3{\bg
+ \long\def\:##1##2\!{\eg##1{##2}}
+ \long\def\!##1##2 \!##3\:{%
+ \ifx\relax##3\relax
+ \:{##1}##2%
+ \else
+ \eg##1{##2}%
+ \fi}%
+ \!{#1\def#2}#3\! \!\:}
+
+%%% Notice that we've had to delay the \endgroup until after our new
+%%% temporary \: has been used.
+%%%
+%%% Anyway, we may now define \trimspace as follows:
+
+\def\trimspace#1{\ea\trimmed\ea\def\ea#1\ea{#1}}
+
+%%% Notice that the replacement definition is a normal \def, whereas the
+%%% macro we started with could have had any number of modifiers attached,
+%%% such as \long, \outer, or \global. A further exercise might be to fix
+%%% this problem.
+%%%
+%%% A more generalized trim might allow any list of tokens to be trimmed off
+%%% the tail of another list of tokens. Here, we add an initial argument to
+%%% \trimmed specifying those tokens. In order to strip off trailing ".\par"
+%%% for instance, we could write: \trimmed{.\par}\outer\long\def\foo{foo.\par}
+%%%
+%%% Here's the general definition of \trimmed:
+
+\long\def\trimmed#1#2\def#3#4{\bg
+ \long\def\:##1##2\!{\eg##1{##2}}
+ \long\def\!##1##2#1\!##3\:{%
+ \ifx\relax##3\relax
+ \:{##1}##2%
+ \else
+ \eg##1{##2}%
+ \fi}%
+ \!{#2\def#3}#4\!#1\!\:}
+
+%%% The auxiliary \trimmed@ remains unchanged. Notice that we no longer really
+%%% need a non-alphabetic macro name for the temporary macro, since we don't
+%%% have to preserve the literal space token following the macro.
+%%%
+%%% Unfortunately, the literal space token problem doesn't disappear, it's just
+%%% pushed up a level. Now we have to give that space as an argument to \trimmed
+%%% in the definition of \trimspace, and hop over it with \expandafter!
+
+\edef\trimspace#1{\nx\ea\nx\trimmed\nx\ea
+ {\nx\ea\space\nx\ea}\nx\ea\def\nx\ea#1\nx\ea{#1}}
+
+%%% N.B., The curly braces, "\nx\ea{...\nx\ea}" around the "\nx\ea\space"
+%%% are necessary.
+%%%
+%%% This approach of defining \trimspace in terms of an underlaying \trimmed
+%%% \def'inition facility has the advantage of reusing code, but the
+%%% disadvantage of forcing a macro redefintion even if there is no trailing
+%%% space to remove. We could modify \trimmed to produce a new macro, \trim,
+%%% that redefines a macro only if it has the trailing pattern of interest.
+%%% (It also happens to be simpler!)
+
+\long\def\trim#1#2{\bg
+ \long\def\!##1#1\!##2\:{\eg
+ \ifx\relax##2\relax \else
+ \def#2{##1}%
+ \fi}%
+ \ea\!#2\!#1\!\:}
+
+%%% Now, we can define \trimspace in terms of \trim like so:
+
+\edef\trimspace#1{\nx\ea\nx\trim\nx\ea{\nx\ea\space\nx\ea}\nx\ea#1}
+
+%%% Ok, let's test it:
+
+\def\HasTrailingSpace{has trailing space }
+\def\NoTrailingSpace{no trailing space}
+
+\trimspace\HasTrailingSpace \show\HasTrailingSpace
+\trimspace\NoTrailingSpace \show\NoTrailingSpace
+
+%%% While we're at it, let's test another pattern:
+
+\def\HasTrailingDotPar{has trailing dot par.\par}
+\def\NoTrailingDotPar{no trailing dot par}
+
+\trim{.\par}\HasTrailingDotPar \show\HasTrailingDotPar
+\trim{.\par}\NoTrailingDotPar \show\NoTrailingDotPar
+
+%%% ### Exercise 15(b)
+%%% Write a macro \trimspaces that removes a leading space, if
+%%% present, and then calls \trimspace to remove a trailing space.
+
+%%% I'm going to solve this in a quick and dirty way, as it's getting
+%%% late and I'm running out of gas! Just use \futurelet sequestered
+%%% in a \vbox to inspect the first token. If it's a \space, gobble
+%%% the first token and subject the remaining tokens to \trimmed.
+
+\def\redefSansSp@ce#1 #2\redefSansSp@ce{\def#1{#2}}
+\def\redefSansSpace#1{\ea\redefSansSp@ce\ea#1#1\redefSansSp@ce}
+\def\trimspaces#1{\bg\setbox0=\vbox{%
+ \def\maybeRedefSansSpace{\ea\ifx\space\@\agg\redefSansSpace\agg#1\fi}%
+ \ea\futurelet\ea\@\ea\maybeRedefSansSpace#1}\eg
+ \trimspace#1}
+
+%%% \futurelet won't work for the more general case of trimming an
+%%% arbitrary leading pattern, as it only looks at one token.
+%%% I'll leave solving the general case as an exercise for the reader ;-)
+%%%
+%%% This is also not the most efficient solution, since we redefine the macro
+%%% twice if there is a leading space. Notice that we put the \setbox0
+%%% inside a group, to keep any previous definition of \box0 safe. This
+%%% is probably overkill, since \box0 is a temporary register and users
+%%% should be aware that it's fair game, but it doesn't hurt to be
+%%% courteous... Also note the abbreviation \agg, which pushes its argument
+%%% out two groups.
+
+[...]
+
+%%% Testing...
+
+\def\foo{ foo }
+\trimspaces\foo \show\foo
+\end{lcode}
+
+\end{solution}
+
+%%========================================================================
+
+In the previous posting I discussed the method of removing a trailing
+space by scanning for a token pair \meta{space}\meta{bizarre}. In Schmitt's
+solution, for example, the bizarre token was a greater-than character
+with catcode 3. And in my solution, I used a letter Q with catcode
+3. Solution 4 from Jonathan Fine takes the approach of using a second
+\meta{space} token for the \meta{bizarre} token. In practice this works for
+typical user-supplied text, as discussed before, since TeX's normal
+reduction of multiple spaces to single spaces makes the pair
+\meta{space}\meta{space} sufficiently bizarre. I have to admit I like this idea;
+those who attempted a solution for this exercise and struggled with
+various other delimiter possibilities will, I think, appreciate the
+humor of it as I did.
+
+As I mentioned last week, I found some theoretical interest in the
+fact that if multiple space tokens were present at the end of the text
+being trimmed, Fine's solution would remove them all, without needing
+to use recursion. But another correspondent pointed out since then
+that if multiple spaces were present at the end they might also be
+presumed possible in the middle of the scanned text, and an occurrence
+of multiple spaces in the middle would cause \cmd{\trim} to fail.
+
+
+
+\begin{solution}{Solution 4 (Jonathan Fine)}\index{Fine, Jonathan}
+\begin{lcode}
+%% NOTE: I have benefited from Michael Downes posting of answers, dated
+%% 16 December, particularly for stripping the leading space, and the
+%% discussion of the hazards of grouped arguments
+
+\catcode`\@=11
+%% The Solution
+\def\trim #1{\expandafter\trim@\expandafter{#1 }#1}
+\def\trim@ #1{\trim@@ @#1 @ #1 @ @@}
+\def\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @}
+\def\unbrace#1{#1}
+\unbrace{\def\trim@@@ #1 } #2@#3{\expandafter\def
+ \expandafter #3\expandafter {#1}}
+
+%% Test Code
+\def\Test{\afterassignment\Test@ \def\test}
+\def\Test@{\trim\test \afterassignment\Test@@ \def\test@}
+\def\Test@@{\message{\ifx\test\test@ Y\else FAIL:|\meaning\test|\fi}}
+\catcode`\@=12
+
+%% Testing The Solution
+\Test{}{}
+\Test{ }{}
+\Test{ a }{a}
+\Test{ {}{} }{{}{}}
+\Test{{braces}}{{braces}}
+\Test{ {braces} }{{braces}}
+\Test{ { braces } }{{ braces }}
+\Test{no space and no space}{no space and no space}
+\Test{no space and a space: }{no space and a space:}
+\Test{ :a space and no space}{:a space and no space}
+\Test{ :a space and a space: }{:a space and a space:}
+\Test{ \ifx }{\ifx}
+\Test{ \ifx/ }{\ifx/}
+\end{lcode}
+\end{solution}
+
+\begin{comment}
+Since my solution got rather long after I added some commentary I'll
+post it separately in a couple of days, rather than double the size of
+this post.
+
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+
+Date: 03 Jan 1994 17:14:14 -0500 (EST)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #15, answers, 4th (last) installment
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+%$
+
+My solution here is the result of weeks of incremental refinement,
+ending only last week, and consequently benefits from analysis of the
+other solutions.
+
+%%========================================================================
+\begin{solution}{Solution 5 (Michael Downes)}
+\begin{lcode}
+% Here I only solve part (b) of Exercise 15, in an attempt to make
+% a solution of utmost compactness (3 control sequences, 45 tokens).
+% Also, it seems likely that in actual use \cmd{\trimspaces} can be
+% applied without harm whenever \trimspace might be needed.
+%
+% The method for pausing after each test might be of ancillary
+% interest to some readers; unlike the alternative of setting
+% \pausing=1, the \test's aren't required to be on separate lines.
+
+\catcode`\Q=3
+
+% \cs{trimspaces}\x redefines \x to have the same replacement text sans
+% leading and trailing space tokens.
+%
+\def\cs{trimspaces}#1{%
+% Use grouping to emulate a multi-token afterassignment queue.
+ \begingroup
+% Put `\toks 0 {' into the afterassignment queue.
+ \aftergroup\toks\aftergroup0\aftergroup{%
+% Apply \trimb to the replacement text of #1, adding a leading
+% \noexpand to prevent brace stripping and to serve another purpose
+% later.
+ \expandafter\trimb\expandafter\noexpand#1Q Q}%
+% Transfer the trimmed text back into #1.
+ \edef#1{\the\toks0}%
+}
+
+% \trimb removes a trailing space if present, then calls \trimc to
+% clean up any leftover bizarre Qs, and trim a leading space. In
+% order for \trimc to work properly we need to put back a Q first.
+%
+\def\trimb#1 Q{\trimc#1Q}
+
+% Execute \vfuzz assignment to remove leading space; the \noexpand
+% will now prevent unwanted expansion of a macro or other expandable
+% token at the beginning of the trimmed text. The \endgroup will feed
+% in the \aftergroup tokens after the \vfuzz assignment is completed.
+%
+\def\trimc#1Q#2{\afterassignment\endgroup \vfuzz\the\vfuzz#1}
+
+\catcode`\Q=11
+
+\def\test#1{\errhelp{#1}\message{[\the\errhelp]}%
+ \edef\x{\the\errhelp}%
+ \global\tracingcommands2\global\tracingmacros2\global\tracingonline0
+ \cs{trimspaces}\x
+ \global\tracingcommands0\global\tracingmacros0\global\tracingonline0
+ \errhelp\expandafter{\x}\message{-> [\the\errhelp]}%
+ \read16 to\PressReturnToContinue
+}
+
+\test{ x } \test{ xy z } \test{} \test{{}}
+\test{{}{}} \test{ {x} } \test{ } \test{{ }}
+\test{\AA} \test{\fi} \test{\space x\space}
+\test{ #1 }
+
+\end
+\end{lcode}
+
+Commentary
+
+Suppose we have a macro \cmd{\x} with replacement text \verb?" {xyz} "?.
+The task of
+\cmd{\trimspaces} is to construct a statement of the form
+\begin{lcode}
+ \def\x{{xyz}}
+\end{lcode}
+i.e., to redefine \cmd{\x} with the same replacement text except for removal
+of a leading or trailing space. However, a similar statement
+\begin{lcode}
+ \toks0{{xyz}}\edef\x{\the\toks0}
+\end{lcode}
+is more robust if the replacement text might contain \# tokens. For
+example,
+\begin{lcode}
+ \def\x{\def\y##1{}}
+\end{lcode}
+works OK but after thus defining \cmd{\x}, the statements
+\begin{lcode}
+ \def\trimx#1{\expandafter\def\expandafter\x\expandafter{#1}}
+ \trimx\x
+\end{lcode}
+fail with an error message because the `\#1' in the definition of \cmd{\y} is
+misinterpreted as a parameter token for the redefinition of \cmd{\x}.
+
+Although \# tokens seem highly unlikely in average user-supplied text, I
+aimed for a statement of the second, robuster kind, as if I were writing
+\cmd{\trimspaces} for use in a major macro package with thousands of
+prospective users.
+
+The basic structure of \cmd{\trimspaces} is therefore: First remove a trailing
+space, then remove a leading space, then put the remaining text into
+\cmd{\toks}\texttt{0}, then transfer the text to \cmd{\x} with \cmd{\edef}.
+
+For removing the trailing space, I apply a macro scan with delimiter
+\verb?<space,10><Q,3>? Here the notation \verb?<c,n>? means the character token
+consisting of character code \texttt{c} with catcode \texttt{n}.
+
+The leading space is removed by executing the assignment
+\verb?\vfuzz=\the\vfuzz? at the beginning of the operand text, in order to use
+a side effect of the assignment: removal of a following space. (Credit
+to Donald Arseneau for this good idea.) The main reason for using
+\verb?\the\vfuzz? instead of 0pt is that it's slightly shorter (one token),
+although if we did not have the group structure to localize the `change'
+to \cmd{\vfuzz}, then using \verb?\the\vfuzz? would also be a good idea for the
+sake of preserving the variable's previous value.
+
+The statement \verb?\vfuzz=\vfuzz? (sans \cmd{\the}), by the way, would not gobble a
+following space: when TeX recognizes a suitable variable on the
+right-hand side of an assignment, it copies the value directly into the
+left-hand side and skips the scanning process entirely.
+
+Here's a step-by-step breakdown of the operation of \cmd{\trimspaces} through
+two possibilities, one where both a leading and a trailing space are
+present, and one where neither are present.
+\begin{lcode}
+------------------------------------------------------------------------
+Case 1 (spaces present) Case 2 (no spaces to be removed)
+------------------------------------------------------------------------
+\def\x{ {xyz} } \cs{trimspaces}\x \def\x{{xyz}} \cs{trimspaces}\x
+
+Step 1: Step 1:
+\begingroup... Same as for Case 1.
+\expandafter\trimb
+\expandafter\noexpand\x Q Q}...
+
+Step 2: || Step 2: ||
+\trimb\noexpand {xyz} Q Q... \trimb\noexpand{xyz}Q Q...
+ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
+Here the row of ^^^ indicates the In this case the first Q is taken
+material that is taken as argument up as part of #1, which is passed
+#1 of \trimb, and || indicates the to \trimc. The second Q added by
+tokens that match the macro \trimb therefore falls after the
+delimiter. #1 is now passed to leftover Q instead of before.
+\trimc, with another Q token added;
+the leftover <space>Q token pair
+follows.
+
+Step 3: | Step 3: |
+\trimc\noexpand {xyz}Q Q... \trimc\noexpand{xyz}QQ...
+ ^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^ ^
+Here we have #1, delimiter token Q, The situation at the end of the
+and #2. The space before the second trimmed text ends up being the same
+Q is skipped by TeX because it's as in Case 1, except for the
+looking for a nondelimited argument absence of a space between the Qs.
+for #2.
+
+Step 4: Step 4:
+\afterassignment\endgroup \afterassignment\endgroup
+\vfuzz\the\vfuzz\noexpand {xyz}}... \vfuzz\the\vfuzz\noexpand{xyz}}...
+ ^
+Here the ^ marks the leading space
+that is to be removed.
+
+Step 5: \endgroup{xyz}}... Step 5: \endgroup{xyz}}...
+
+\endgroup is from \afterassignment.
+
+Step 6: Step 6:
+\toks0{{xyz}} \toks0{{xyz}}
+^^^^^^^---from \aftergroup ^^^^^^^---from \aftergroup
+\edef\x{\the\toks0} \edef\x{\the\toks0}
+\end{lcode}
+
+\end{solution}
+
+\begin{comment}
+========================================================================
+
+That's a wrap on Exercise 15.
+
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+\end{comment}
+%$
+%%\endinput
+
+
+\chapter{Assorted numbers, skips, and modes}
+
+\section{Exercise}
+
+%%\input{ex016}
+% ex016.tex
+\begin{comment}
+Date: 13 Jan 1994 16:42:27 -0500 (EST)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #16
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+
+************************************************************************
+*** Exercise 16:
+\end{comment}
+
+\ed{\oposted{1994/01/13}. \arch{exercise.016}.}
+
+Predict the messages that will be produced by plain TeX for the
+following test file.
+\begin{lcode}
+\catcode`\@=11 \newcount\m
+\def\msg#1{\advance\m 1 \message{(\number\m): #1}}
+\def\T{\msg{T}}\def\F{\msg{F}}
+\mag=1728 \hfuzz=1pt \tabskip=1pt \baselineskip=12pt
+\topskip=10pt \lineskiplimit=1pt \lineskip=1pt
+
+\setbox0\vbox{%
+\mag=\time \ifnum\mag>1500 \T\else\F\fi % (1)
+\mag=\number\year \ifnum\mag>1500 \T\else\F\fi % (2)
+\hfuzz=99pt \ifdim\hfuzz=99pt \T\else \F\fi % (3)
+\tabskip=\z@ \ifdim\tabskip<\p@\T\else\F\fi % (4)
+\tabskip=\p@ minus2pt \ifdim\tabskip>\z@\T\else\F\fi % (5)
+\baselineskip=-\prevdepth \ifdim\baselineskip=12pt \T\else\F\fi % (6)
+\advance\baselineskip 2\topskip % (7)
+ \ifdim\baselineskip>\@m\p@ \T\else\F\fi %
+\lineskiplimit=\z@ \ifnum\lineskiplimit>0 \T\else\F\fi % (8)
+\lineskip=\z@skip \ifdim\lineskip>\lineskiplimit \T\else\F\fi % (9)
+\kern2pc\ifdim\lastkern=2pc \T \else\F\fi % (10)
+\hskip1em
+ \ifvmode\T\else\ifdim\lastskip>\z@\msg{FT}\else\msg{FF}\fi\fi % (11)
+\font\cmrtest=cmr10 \ifx\cmrtest\tenrm \T\else\F\fi % (12)
+}
+\end
+\end{lcode}
+Where should \cmd{\relax} be inserted?
+
+\begin{comment}
+************************************************************************
+
+Answers will be posted circa January 27, 1994.
+
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+\end{comment}
+%$
+%%\endinput
+
+
+\section{Answers}
+
+%%\input{ans016}
+% ans016.tex
+\begin{comment}
+[There was an error in the first posted version: \twelverm instead of
+the first \tenrm in the statement
+
+ \font\tenrm = \fontname\tenrm scaled 1200
+
+The posting containing this correction is appended below.]
+
+Date: 27 Jan 1994 11:59:48 -0500 (EST)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #16, answers
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+\ed{\oposted{1994/01/27}. \arch{answer.016}.}
+
+Here is my commentary on Around the Bend \#16.
+\begin{lcode}
+% \mag=1728 \hfuzz=1pt \tabskip=1pt \baselineskip=12pt
+% \topskip=10pt \lineskiplimit=1pt \lineskip=1pt
+
+% \mag=\time \ifnum\mag>1500 \T\else\F\fi % (1)
+\end{lcode}
+(1): F --- At the time of the \piif{ifnum}, \cmd{\mag} is in the range [0,1440)
+depending on what time it was when you ran TeX.
+
+\begin{lcode}
+% \mag=\number\year \ifnum\mag>1500 \T\else\F\fi % (2)
+\end{lcode}
+(2): F --- At the time of the \piif{ifnum}, \cmd{\mag} still has its previous value
+because TeX is still scanning for digits to add on after `1994'.
+
+\begin{lcode}
+% \hfuzz=99pt \ifdim\hfuzz=99pt \T\else \F\fi % (3)
+\end{lcode}
+(3): T --- Everything fine, dimension scanning terminated with the
+space after `99pt'.
+
+\begin{lcode}
+% \tabskip=\z@ \ifdim\tabskip<\p@\T\else\F\fi % (4)
+\end{lcode}
+(4): F --- \cmd{\z@} is a dimension register, therefore it serves only as the
+first part of the glue value that TeX is looking for. At the time of the
+\piif{ifdim}, TeX is still looking for `plus' or `minus' and hasn't yet
+finished the assignment of \cmd{\tabskip}.
+
+\begin{lcode}
+% \tabskip=\p@ minus2pt \ifdim\tabskip>\z@\T\else\F\fi % (5)
+\end{lcode}
+(5): T --- Glue value scanning terminated properly. \cmd{\p@} is a dimension
+register like \cmd{\z@} but the additional clause `minus 2pt' fills out the
+glue value to the required three parts. TeX assumes `plus 0pt' when it
+finds a `minus' clause without a preceding `plus' clause. Note that TeX
+does \emph{not} continue scanning for a possible `plus' after reading a minus
+component. Unlike the height, depth, and width components of a \cmd{\vrule} or
+\cmd{\hrule}, the components of a glue value have a required order and each
+part can only occur once.
+
+\begin{lcode}
+% \baselineskip=-\prevdepth \ifdim\baselineskip=12pt \T\else\F\fi % (6)
+\end{lcode}
+(6): T --- At the beginning of a vbox or at the beginning of a TeX run
+\cmd{\prevdepth} = -1000pt. So it would seem that \cmd{\baselineskip} should get set
+to +1000pt and the test should be False; but \cmd{\prevdepth} is a dimension
+register, not a glue register, so following stretch or shrink components
+are still possible, and \cmd{\baselineskip} does not yet have its new value at
+the time of the test.
+
+\begin{lcode}
+% \advance\baselineskip 2\topskip % (7)
+% \ifdim\baselineskip>\@m\p@ \T\else\F\fi %
+\end{lcode}
+(7): F --- Without the factor 2 in front of \cmd{\topskip}, the test would
+be True: \cmd{\topskip} is a glue register so TeX would copy each component of
+\cmd{\topskip} to the corresponding component of \cmd{\baselineskip}; then, having plus
+and minus components already in hand, TeX would not scan ahead for
+`plus' or `minus'. However, a preceding factor for a glue register
+causes TeX to use only the first component of the glue register,
+multiplied by the given factor, which means that additional scanning is
+then attempted for possible stretch or shrink components.
+
+\begin{lcode}
+% \lineskiplimit=\z@ \ifnum\lineskiplimit>0 \T\else\F\fi % (8)
+\end{lcode}
+(8): F --- Normal termination of dimension scanning. \cmd{\lineskiplimit}
+is a dimen register, not a glue register, so the dimen constant \cmd{\z@} is
+sufficient to complete the assignment and TeX scans no further.
+
+\begin{lcode}
+% \lineskip=\z@skip \ifdim\lineskip>\lineskiplimit \T\else\F\fi % (9)
+\end{lcode}
+(9): F --- Normal termination of glue scanning. \cmd{\z@skip} is a glue
+register so it suffices to complete the assignment of \cmd{\lineskip}. Compare
+to the \cmd{\tabskip} assignments above.
+
+\begin{lcode}
+% \kern2pc\ifdim\lastkern=2pc \T \else\F\fi % (10)
+\end{lcode}
+(10): F --- At the time of the \piif{ifdim}, TeX is still looking for
+an optional final space at the end of the dimension value `2pc'. If it
+were \verb?2\p@? instead of \verb?2pc?, the test would evaluate to True.
+
+\begin{lcode}
+% \hskip1em
+% \ifvmode\T\else\ifdim\lastskip>\z@\msg{FT}\else\msg{FF}\fi\fi % (11)
+\end{lcode}
+(11) FF --- TeX enters horizontal mode as soon as the \cmd{\hskip} command
+comes along, before it finishes scanning the skip amount. So the
+\piif{ifvmode} test is false. The \piif{ifdim} test is also false because scanning
+is not yet complete (TeX is looking ahead for a plus or minus component)
+so the glue has not yet been entered into the horizontal list, so it is
+not accessible to \cmd{\lastskip}.
+
+For more on the switch into horizontal mode, see `TeX from \cmd{\indent} to
+\piif{par}', Marek Ry{\'c}ko and Bogus{\l}aw Jackowski, TUGboat 14/3, October
+1993 (1993 Annual Meeting Proceedings), pp. 171--176.
+
+\begin{lcode}
+% \font\cmrtest=cmr10 \ifx\cmrtest\tenrm \T\else\F\fi % (12)
+\end{lcode}
+(12) F --- Interestingly, the following versions of the \piif{ifx} test are
+also false at that point:
+\begin{lcode}
+ \ifx\cmrtest\undefined, \ifx\cmrtest\relax.
+\end{lcode}
+The reason is that after `\verb?\font\cmrtest?' TeX immediately sets
+\verb?\cmrtest = \nullfont?, before scanning the rest of the font assignment. So the test
+\verb?\ifx\cmrtest\nullfont? would yield True. According to the \emph{TeXbook},
+the reason for this behavior is to allow statements of the form
+\begin{lcode}
+ \font\cmrtest=cmr10 \cmrtest
+\end{lcode}
+for switching to the font \cmd{\cmrtest} immediately after it is defined. TeX
+does a bit of boomeranging in such a case:
+\begin{lcode}
+ \font\cmrtest % set \cmrtest = \nullfont
+ =cmr10 % space terminates font name, start looking for
+ % "at" or "scaled"
+ \cmrtest % \cmrtest = \nullfont = nonexpandable, not
+ % "a", not "s"; terminate the font assignment
+ % and put back the \cmrtest token to be read
+ % again:
+ \cmrtest % Now \cmrtest selects the given font
+\end{lcode}
+Although I sympathize with Knuth's desire to smooth out a potential
+problem for naive users, I wonder if it only encourages users to pay
+less attention to the nitty-gritty details of scanning and expansion,
+and therefore lay themselves open to greater confusion later on when
+something similar fails (inconsistently!) to work. I'd have thought it
+better to require, and document, proper termination of font assignment
+scanning by \cmd{\relax} or whatever. Users would have to be a little more
+knowledgeable but they would be rewarded with a more consistent language
+to work with. As it stands TeX unnaturally forbids certain
+constructions that are perfectly colloquial to anyone who has an ear for
+the TeX language, such as
+\begin{lcode}
+ \font\tenrm = \fontname\tenrm\space scaled 1200
+\end{lcode}
+I hold a similar opinion for the way \cmd{\chardef} and \cmd{\mathchardef} set their
+arguments to \cmd{\relax} before scanning the number on the right-hand-side of
+the assignment. Occasionally I would \emph{like} to be able to write
+something like
+\begin{lcode}
+ \chardef\foo=\ifcase\foo 1\or 2\else 3\fi
+\end{lcode}
+ but TeX doesn't allow that.
+
+One could argue that the \cmd{\chardef} behavior should for consistency be
+imitated by \cmd{\edef}, \cmd{\xdef} so that if \cmd{\foo} is undefined then
+\begin{lcode}
+ \edef\foo{a\foo}
+\end{lcode}
+should not give an undefined control-sequence error for the \cmd{\foo} in the
+replacement text, but make it temporarily equivalent to \cmd{\relax} and leave
+it there. (Of course, this means that executing \cmd{\foo} will then start up
+an infinite loop, but my point was that it's the behavior of \cmd{\chardef}
+that should be changed to achieve consistency, not the behavior of
+\cmd{\edef}.)
+
+%%%========================================================================
+
+At the end of Exercise \#16 there was the question `Where should \cmd{\relax}
+should be inserted?'
+
+\cmd{\relax} should be inserted just before the \piif{if}... in statements (2), (6),
+(7), (11), and (12). In statement (4) \cmd{\z@skip} should be used instead of
+\cmd{\z@}; then \cmd{\relax} is unnecessary. A space suffices instead of \cmd{\relax} in
+(10). I would also tend to put a \cmd{\relax} at the end of the preliminary
+assignments to \cmd{\baselineskip} and \cmd{\lineskip}, as a matter of principle; I
+like to make sure that scanning is definitely terminated at the end of a
+line, so that if any error occurs during the scanning, TeX will show the
+line containing the assignment statement and not a later line. This is
+particularly relevant for font assignments: If \pfile{foo10.tfm} does not exist
+on your system, then the assignment
+\begin{lcode}
+ \font\foo=foo10
+ <blank line>
+\end{lcode}
+will cause TeX to show you the blank line instead of the preceding line
+in the error context:
+\begin{lcode}
+ ! Font \foo=foo10 not loadable: Metric (TFM) file not found.
+ <to be read again>
+ \par
+ l.2
+\end{lcode}
+And if the following material is some complicated macro instead of a
+blank line, TeX will go into the replacement text of the macro, looking
+for `at' or `scaled', before giving the error message!
+
+\begin{comment}
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+
+Date: 28 Jan 1994 08:01:12 -0500 (EST)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #16, answers, correction
+To: info-tex@shsu.edu
+
+Instead of
+
+ \font\twelverm = \fontname\tenrm\space scaled 1200
+
+read
+
+ \font\tenrm = \fontname\tenrm\space scaled 1200
+
+The latter line is what I originally wrote but I changed it in an obtuse
+moment a day later, forgetting the very point it was supposed to
+illustrate.
+\end{comment}
+%$
+%%\endinput
+
+
+\chapter{Missing \cs{input} file}
+
+\section{Exercise}
+
+%%\input{ex017}
+% ex017.tex
+\begin{comment}
+Date: 14 Jan 1994 12:44:13 -0500 (EST)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #17
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+\ed{\oposted{1994/01/15}. \arch{exercise.017}.}
+
+%%************************************************************************
+%%*** Exercise 17:
+When TeX cannot find an input file it prompts with `Please enter another
+input file name:'. On some systems you can enter `nul' in response to
+this prompt to have TeX input a null file and continue processing. On
+most systems TeX also allows you to enter a system-dependent end-of-file
+character (Control-Z (DOS, VMS), Control-D (Unix), ...?), to which it
+responds with an "Emergency stop" instead of continued processing.
+
+An alternative would be to maintain a file called `\pfile{.tex}' containing an
+error message so that merely pressing RETURN would cause TeX to read
+`\pfile{.tex}' and issue the error message. Unlike the null file case or
+EOF-character case, this would allow normal access to the full menu of
+error recovery options, including e.g., exiting to an editor, inserting
+or deleting tokens, or changing the interaction mode. It would probably
+be nice to have the file also accessible under various aliases `\pfile{h.tex}',
+`\pfile{help.tex}', `\pfile{?.tex}', `\pfile{q.tex}', `\pfile{quit.tex}',
+`\pfile{x.tex}', `\pfile{exit.tex}', or
+`\verb?@#&@%$.tex?' corresponding to typical responses from stumped users.
+
+But making a robust `\pfile{.tex}' file for input error recovery is not so
+simple a task as might first seem. One needs to take into account, for
+example, the possibility that an \cmd{\input} might be attempted when normal
+catcodes or normal \cmd{\endlinechar} are not in effect.
+
+Given the programmability of TeX, an all-encompassing solution is
+probably not possible, so this exercise has two parts: consider what
+would be a reasonable minimal set of assumptions for an input error
+recovery file; and write a \pfile{.tex} file containing a suitable
+error message and satisfying the assumptions.
+%%************************************************************************
+
+Motivation: From \url{comp.text.tex}:
+\begin{lcode}
+> From: wayne@csri.toronto.edu (Wayne Hayes)
+> Subject: Why does TeX ignore interupts???
+> Message-ID: <1993Dec24.000935.2007@jarvis.csri.toronto.edu>
+> Date: 24 Dec 93 05:09:35 GMT
+>
+> If there's ONE thing that annoys me more than anything about a program,
+> it's when it refuses to die on command, and for no good reason. The
+> absolute worst case is when it's waiting for input and you don't know
+> what to tell it, and would like to quit for now.
+>
+> Thus my extreme annoyance every time I mistype an \input command to TeX
+> and it asks me on the terminal "Please input another file name: ", and
+> I usually just want to exit and re-edit my file to fix the \input
+> error. But TeX refuses to die when I press ^C at this moment, and will
+> only die if I send a QUIT (^\), at which point it dumps a
+> multi-megabyte core file into the current directory. ARGGGHHHH!! Why
+> does it do this? I can't see any good reason why it ignores interupts
+> at this point. Is this intended? Is it a bug? Does it drive anyone
+> else as nuts as it drives me?? Can it be changed in the next release???
+\end{lcode}
+
+It's puzzling that most of the implementations of TeX I know of don't
+check for the interrupt key possibility at this prompt [Textures notably
+cuts clean through the problem by popping up a dialog box if an input
+file is not found]. Seems as if interrupt-key checking at that point
+would be a desirable addition to the set of system-dependent changes for
+each system.
+
+\begin{comment}
+A summary will be posted circa February 17, 1994.
+
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+\end{comment}
+%$
+%%\endinput
+
+\section{Answers}
+
+%%\input{ans017}
+% ans017.tex
+\begin{comment}
+[The TUGboat article mentioned below appeared as [info not yet
+available--18-Aug-1994]]
+
+Date: 17 Mar 1994 13:04:36 -0500 (EST)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #17, answers
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+\end{comment}
+
+\ed{\oposted{1994/03/13}. \arch{answer.017}.}
+
+Exercise 17 (posted January 14) asked for an error recovery file to
+provide better recovery from file input errors: When TeX cannot find an
+input file, it prompts for an alternative file name and refuses to
+continue until a valid file name is entered or the user presses some
+(system-dependent) abort key. This can be rather unfriendly, especially
+for novice users.
+
+At the request of Barbara Beeton\index{Beeton, Barbara} (TUGboat's editor)
+I wrote up the
+results of this exercise as an article for publication in TUGboat, so
+this posting will be largely redundant with that article.
+
+
+%%%-------------------------------------
+%%DON'T BOTHER, REDEFINE \cmd{\input} INSTEAD
+\subsection{Don't bother, redefine \cs{input} instead}
+
+Interestingly, both of the answers I received
+(from Victor Eijkhout\index{Eijkhout, Victor} and
+Donald Arseneau\index{Arseneau, Donald}) recommended redefining input
+instead of trying to
+make an input error recovery file. Donald summed it up thus:
+\begin{quotation}
+ Since verbatim file input is an important mainstream application,
+ the task is hopeless.
+
+ The right approach is to redefine \cmd{\input} and check for the file's
+ existence at the macro level.
+\end{quotation}
+
+I.e., consider the way a typical \cmd{\verbfile} commands works: first, start
+a group; next, deactivate all special characters such as \verb?\ { } # % }? by
+changing their catcodes; then input the desired file; and finally close
+the group to restore normal catcodes. If the desired file is not found
+and an input error recovery file is read instead, the IERF will not be
+able to do anything because of the deactivation of \verb?\ { }? etc.
+
+
+%%----------------------------------------------
+%%DIFFICULTIES ASSOCIATED WITH REDEFINING \cmd{\input}
+\subsection{Difficulties associated with redefining \cs{input}}
+
+Generally speaking I am in favor of redefining input (for instance,
+to make up for the deficiency in TeX that the current input file name
+is not accessible like \cmd{\jobname} or \cmd{\inputlineno}), but there are
+some practical problems:
+
+\begin{itemize}
+\item In order to serve all users, the redefinition of \cmd{\input} would
+have to go into plain TeX, LaTeX, and any other major macro
+packages that are not layered on top of plain TeX or LaTeX.
+
+\item The most commonly used approach to test for the existence of an input
+file is
+\begin{lcode}
+ \openin N=file.name \ifeof N ...
+\end{lcode}
+but for
+some TeX implementations \cmd{\openin} will only open a file in the
+current directory, and not search through the entire `TeX inputs'
+path. I believe that this restriction is canonical in \pfile{TeX.web}
+therefore only overridden by the system-dependent changes of each TeX
+implementation according to the judgment of the individual implementor.
+
+\item The details of how to redefine \cmd{\input} are nontrivial. If you
+redefine \cmd{\input} to take an argument delimited by a space, for
+example, there is some risk of bombing on existing files with
+statements like
+\begin{lcode}
+ \input x.y\relax
+\end{lcode}
+It becomes especially nontrivial if you want to use some method other
+than simple \verb?\openin ... \ifeof? to test for file existence, so that
+the method will be reliable across all systems.
+
+It is worth noting that in LaTeX2e the \cmd{\input} command has
+been dramatically overhauled so that it solves, among other things,
+some of the problems mentioned here. Anyone doubting the claim that
+the work is nontrivial is invited to look at the LaTeX2e definitions.
+
+\item Redefining \cmd{\input} will (generally speaking) not help for the
+jobname file itself. When the file name is given on the command line, or
+following a ** prompt, the input operation is done directly by
+TeX instead of through invoking the control sequence \cmd{\input}.
+
+\item When a non-existing file is called for by a verb-file command,
+TeX will prompt the user for a file name, and then if a \pfile{.tex} recovery
+file exists, pressing \meta{return} will typeset the contents of that file;
+but this is at least as good as inputting a null file, in that you are
+not stuck at the prompt with no obvious way to quit.
+\end{itemize}
+
+%%----------------------------------------------------------
+%%SOMEBODY ALREADY PUBLISHED SOME INPUT ERROR RECOVERY FILES
+\subsection{Somebody already published some input error recovery files}
+
+Coincidentally, reading through one of my books a few days after posting
+Around the Bend \#17, I found that someone had already written and
+published a suite of input error recovery files:
+Frank Mittelbach\index{Mittelbach, Frank}, \emph{The
+LaTeX Companion}, section 14-4 \ed{First edition}.
+
+
+%%------------------------------------------------------
+%%BUT WHAT THE HECK, HERE ARE MY SLIGHTLY DIFFERENT ONES
+\subsection{But what the heck, here are my slightly different ones}
+
+The basic idea is to create a file named \pfile{h.tex} that will produce an
+\cmd{\errmessage}\verb?{...}? statement. Copies (or links) of this file will be made
+under several different names corresponding to the typical user
+responses to an input file error, to the extent that the operating
+system permits.
+
+So a first attempt would be something like this:
+\begin{lcode}
+ \errmessage{Enter x to exit or ? to see other options}
+\end{lcode}
+Suppose we test this with a simple test file:
+\begin{lcode}
+ % This is line 1
+ % This is line 2
+ \input fzrg \relax % This is line 3
+ % This is line 4
+ \end
+\end{lcode}
+
+The on-screen result looks like this:
+\begin{lcode}
+ ! I can't find file `fzrg.tex'.
+ l.3 \input fzrg
+ \relax % This is line 3
+ Please type another input file name: h
+ (h.tex
+ ! Enter x to exit or ? to see other options.
+ l.1 ... to exit or ? to see other options}
+
+ ?
+\end{lcode}
+
+Then if the user enters \texttt{?} they will see
+\begin{lcode}
+ Type <return> to proceed,
+ S to scroll future error messages,
+ R to run without stopping,
+ Q to run quietly,
+ I to insert something,
+ E to edit your file,
+ 1 or ... or 9 to ignore the next 1 to 9 tokens of input,
+ H for help, X to quit.
+ ? x
+\end{lcode}
+
+Now let's examine this solution a little more closely, to ask what are
+the potential problems, and what assumptions can be done away with?
+
+One problem is the possibility of an unusual catcode for space, question
+mark, left brace, right brace, backslash, or \cmd{\endlinechar}. For the
+backslash (and the letters) we don't have much choice; if they don't
+have normal catcodes, \pfile{h.tex} cannot issue an \cmd{\errmessage} command, or even
+try to fix up the catcodes. (This is why the problem of verbatim file
+input is insoluble, if primitive \cmd{\input} is used.) Note that for users of
+a macro package such as texinfo, which has \verb?@? for the escape character
+instead of backslash, a different IERF would be required.
+
+The \cmd{\endlinechar} problem can be solved by adding a percent sign at the
+end of the line:
+\begin{lcode}
+ \errmessage{...}%
+\end{lcode}
+but at the cost of a new assumption: percent must have catcode 14. This
+and some of the other catcode assumptions can be removed with a bit of
+extra work:
+\begin{lcode}
+ \begingroup\chardef\%37\catcode\%14\chardef\ 32\catcode\ 10\relax%
+ \catcode123 1\catcode125 2\catcode63 12 %
+ \errmessage{%
+ Enter x to exit or ? to see other options}%
+ \endgroup\endinput%
+\end{lcode}
+This enforces the desired catcodes for \verb|space, %, {, }, and ?|; and
+putting \% at the end of each line makes \cmd{\endlinechar} harmless, no matter
+what its prevailing value and catcode might happen to be. The
+\cmd{\begingroup} ... \cmd{\endgroup} pair of course keep the catcode changes local,
+just in case (though I expect that the user will normally choose to exit
+anyway). I write
+\begin{lcode}
+ \chardef\%37\catcode\%14
+\end{lcode}
+in preference to the alternatives
+\begin{lcode}
+ \catcode37 14
+ \catcode37=14
+ \catcode37'16
+ \catcode37"E
+ \catcode`\%14
+\end{lcode}
+which require assuming a usable catcode for one extra character (space
+or = or ' or ...). Even using \cmd{\string}, as in
+\begin{lcode}
+ \catcode37\string"E
+\end{lcode}
+would fail if \texttt{"} had catcode 5, 9, 10, 11, 14, or 15.
+
+Here now is the screen output produced by the above IERF:
+\begin{lcode}
+ ! I can't find file `fzrg'.
+ l.3 \input fzrg
+ \relax % This is line 3
+ Please type another input file name: h
+ (h.tex
+ ! Enter x to exit or ? to see other options.
+ l.5 Enter x to exit or ? to see other options}
+ %
+ ? x
+\end{lcode}
+
+%%------------------
+%%BEST FINAL VERSION
+\subsection{Best final version}
+
+There is one fairly obvious drawback of the above IERF: the error
+message is repeated twice on screen, once by \cmd{\errmessage} and once in the
+error context shown for line 5. There is a little trick that can be used
+to fix that: Use only the error context for showing the message text, by
+putting it in a comment rather than in the argument of \cmd{\errmessage}!
+[Cf.the comment after \cmd{\patterns} in the original TeX hyphenation patterns
+file hyphen.tex.]
+
+\begin{lcode}
+ \begingroup\chardef\%37\catcode\%14\chardef\?63\catcode\?12\relax%
+ \chardef\{123\catcode\{1\chardef\ 32\catcode\ 2\relax%
+ \errmessage{Input\string canceled\string ..%
+ % Enter x to exit or ? to see other options %
+ \endgroup\endinput%
+\end{lcode}
+I have thrown in some extra cleverness with the catcode of space to
+clean up the screen output a tiny bit more. The result looks like this:
+\begin{lcode}
+ ! I can't find file `fzrg'.
+ l.3 \input fzrg
+ \relax % This is line 3
+ Please type another input file name: h
+ (h.tex
+ ! Input canceled ...
+ l.4
+ % Enter x to exit or ? to see other options %
+ ? x
+\end{lcode}
+
+Frank Mittelbach's IERF solution differs from mine by providing a set of
+files that attempt to mimic standard TeX error recovery according to
+their name: The file \pfile{s.tex}, for example, arranges to switch into
+\cmd{\scrollmode} and continue processing, as would happen if you entered `s'
+at a normal error message prompt. And there are files named \pfile{e.tex},
+\pfile{x.tex}, \pfile{q.tex} that mimic the corresponding error message actions. His
+IERFs also don't bother to worry about possible odd catcodes for \{,
+space, \}, etc.---an approach whose simplicity perhaps outweighs the
+minor added robustness of my version.
+
+%%-----------
+%%CONCLUSIONS
+\subsection{Conclusions}
+
+It seems that it would be a worthy service to their users if the authors
+of all TeX implementations took a second look at how input file errors
+are handled and added suitable actions depending on the operating
+system. For example, under DOS it is difficult to create a file named
+\pfile{.tex}, so perhaps emTeX, PCTeX, TurboTeX, etc., should check for the case
+when the user presses the \meta{return} key at the prompt, and automatically
+exit instead of trying to input a highly improbable file! Similar
+arguments would hold for an input file name of \pfile{?} or \pfile{?.tex}
+for operating
+systems where \texttt{?} is an OS wild-card character.
+
+And another part of improving the input error handling might be to add
+to their standard distributions a set of IERFs in the TeX inputs area,
+to help users who are using some macro package \emph{other} than LaTeX2e.
+(Or, even for LaTeX2e users, to help in the case when it is the jobname
+file itself that was not input-able.) I recommend of course my IERF
+given above; my feelings would not be deeply wounded, however, if
+Frank's version gets used instead. Installing either version would be
+much better for end users than none at all.
+
+\begin{comment}
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+\end{comment}
+%$
+%%\endinput
+
+
+\chapter{Page breaking}
+
+\section{Exercise}
+
+%%\input{ex018}
+% ex018.tex
+\begin{comment}
+Date: 21 Apr 1994 09:48:48 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #18
+To: info-tex@shsu.edu
+X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>
+
+========================================================================
+*** Exercise 18:
+\end{comment}
+
+\ed{\oposted{1994/04/21}. \arch{exercise.018}.}
+
+On page 254 of the \emph{TeXbook} the following output routine is described:
+\begin{lcode}
+ \output={\unvbox255 \penalty\outputpenalty}
+\end{lcode}
+and in the ensuing text Knuth writes `If the \cmd{\vsize} hasn't changed, and
+if no insertions have been held over, the same page break will be
+found.' This claim is rather false. Why? How should the output routine
+be rewritten to work as intended?
+%%========================================================================
+
+Thanks to William Baxter\index{Baxter, William}
+%(web@superscript.com)
+for contributing this question.
+
+\begin{comment}
+Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+\end{comment}
+%$
+%%\endinput
+
+
+\section{Answers}
+
+%%\input{ans018}
+% ans018.tex
+\begin{comment}
+Date: 27 May 1994 08:19:39 -0400 (EDT)
+From: Michael Downes <MJD@MATH.AMS.ORG>
+Subject: Around the Bend #18, answer
+To: info-tex@shsu.edu
+\end{comment}
+
+\ed{\oposted{1994/05/27}. \arch{answer.018}.}
+
+I intended to post this sooner but in researching the answer it turned
+out that in order to clear up a couple of nagging questions I had to
+follow some side trails a long way.
+
+%%Answer to Around the Bend #18:
+
+Exercise 18 (21 April 1994) pointed out that the output routine
+\begin{lcode}
+ \output={\unvbox255 \penalty\outputpenalty}
+\end{lcode}
+described in the \emph{TeXbook} p 254 doesn't exactly work as intended: `If
+the \cmd{\vsize} hasn't changed, and if no insertions have been held over, the
+same page break will be found.'
+
+The same pagebreak will be found only if the original page break
+occurred at a penalty item. Otherwise (\emph{TeXbook}, p 125) TeX
+sets \cmd{\outputpenalty}\texttt{=10000} before firing up the user's output
+routine. Consequently, the output routine constructs a vertical list in
+which the original break point has disappeared.
+
+By an optimization found in section 890 of \emph{TeX: The Program}, the
+penalty between two paragraph lines---the sum of all applicable
+penalties from the set \cmd{\interlinepenalty}, \cmd{\clubpenalty},
+\cmd{\widowpenalty}, \cmd{\displaywidowpenalty}, and \cmd{\brokenpenalty}---is
+not actually added to
+the vertical list unless it is nonzero. Thus when \cmd{\interlinepenalty} =
+0 (default from IniTeX/plain TeX) and hyphenated lines are not too
+frequent, `most' pairs of lines in a paragraph have no intervening
+penalty. And there is usually no penalty between ordinary text
+paragraphs. Thus an \cmd{\outputpenalty} value of 10000 will occur fairly
+often in practice.
+
+W. E. Baxter\index{Baxter, William}\index{Baxter, W E|see{Baxter, William}}
+(the submitter of this exercise)
+looked into the
+possibility of recompiling TeX without the cited optimization, but found
+that the resulting version fails the trip test.
+
+In order for the example to work as intended it would have to be
+rewritten as
+\begin{lcode}
+ \output={\unvbox255
+ \ifnum\outputpenalty=10000 \else \penalty\outputpenalty\fi}
+\end{lcode}
+For completeness it should be pointed out that the output routine
+could come even closer to the goal of `doing nothing' if the parameter
+\cmd{\holdinginserts}, added in TeX version 3.0 (circa 1990), were set to
+some value greater than 0, so that the state of floating inserts would
+be preserved; but that has to be done before the output routine is
+entered.
+
+I would have said that such a do-nothing output routine is useless, but
+as a matter of fact I wrote something rather close to it as one cycle of
+a multi-cycle output routine a couple of years ago. The goal was to look
+at the values of \cmd{\pagetotal}, \cmd{\pagestretch}, etc in order to print a
+complete survey of the page contents in a marginal note, to help the
+person dealing with page break decisions when the automatic breaks
+turned out to be inadequate. Unfortunately, the values of \cmd{\pagetotal} etc
+reported in the output routine are not exactly the values that are
+needed, because if the page break did not occur at a forcing penalty
+($<=-10000$) then the values include material on the recent contributions
+list, yet only the material up to the chosen page break is relevant. So
+in order to get accurate values I had to insert a do-almost-nothing
+cycle that merely inserted a forcing penalty at the break point after
+dumping the contents of \texttt{box255} back on the main vertical list.
+
+%%------------------------------------------------------------------------
+\subsection{Some historical research}
+
+If you have an older copy of the \emph{TeXbook} (pre-1990), as I do, the
+above-mentioned section on p 125 about \cmd{\outputpenalty} says that it is
+set to 0 (rather than 10000) if the break did not occur at a penalty
+item. Thus the output routine example on p 254 seems to be another
+case of a well-known phenomenon: documentation failing to keep up with
+changes in the software. Make a note of it in your copy!
+
+Excerpt from the \emph{TeXbook} errata files:
+\begin{verbatim}
+ \bugonpage A125, lines 13--29 (9/23/89)
+
+ \ddanger \looseness=-1
+ When the best page break is finally chosen, \TeX\ removes everything after
+ the chosen breakpoint from the bottom of the ``current page,'' and puts it
+ all back at the top of the ``recent contributions.'' The chosen
+ breakpoint itself is placed at the very top of the recent contributions.
+ If it is a penalty item, the value of the penalty is recorded in
+ ^|\outputpenalty| and the penalty in the contribution list is changed
+ to $10000$; otherwise |\outputpenalty| is set to 10000.
+\end{verbatim}
+
+It's not clear to me from a cursory examination of \pfile{tex82.bug},
+\pfile{errata-five.tex}, and \pfile{tex.web} when this change occurred
+in \pfile{tex.web}, but it
+seems that it must have occurred rather early, perhaps in the work on
+TeX82 (1982--1983); if so, then the claim that outputpenalty was set to
+0 was a five-year-old oversight when Knuth changed it in 1989. In
+\pfile{tex82.bug} there is no reference to output\_penalty or even inf\_penalty
+near 9/23/89, and tracing backwards from there didn't turn up anything
+that seemed relevant to me. Furthermore, a copy of TeX version 2 (circa
+1985) that I was able to dig up had outputpenalty 10000 instead of 0,
+following the erratum, and my 1986 copy of \emph{TeX: The Program} (i.e.
+the woven version of tex.web) agrees with that.
+
+Thanks again to W. E. Baxter\index{Baxter, William} for contributing
+this exercise and several parts of the answer.
+
+%%\endinput
+
+
+
+\chapter{Author lists}
+
+%%\input{bend019}
+% bend019.tex
+
+\section{Exercise (hard)}
+
+\ed{\oposted{1994/08/23}}
+
+First, an
+announcement: Archive copies of exercises and solutions in the
+Around the Bend series are now available over the network, thanks to the
+ongoing remarkably fine service of CTAN (\url{ftp.shsu.edu},
+\url{ftp.dante.de}, \url{ftp.tex.ac.uk},\ldots). Look in the directory
+\url{tex-archive/info/aro-bend}.
+
+%========================================================================
+%%*** Exercise 19 (hard):
+
+In a multi-author LaTeX article, author names are normally given
+as a list with \cmd{\and} separating the names, for example
+\begin{lcode}
+Arthur B. Clark\and Damian Edlan\and Ferency G. van Hoep
+\end{lcode}
+
+The way the author names are laid out on the printed page may
+vary widely from one publication to another. The generic
+`article' documentclass provides a definition for \cmd{\and} to print
+the author names together with their addresses in an array form.
+But there is no support in basic LaTeX to print such a list of
+names in standard series form
+\begin{lcode}
+A (1 author)
+A and B (2 authors)
+A, B, and C (3+ authors)
+\end{lcode}
+
+\begin{enumerate}
+\item Write a macro \cmd{\andlist} to convert a list of author names to
+ series form. Assume that the names reside in a macro \cmd{\@author}.
+
+ Suggested tests:
+\begin{lcode}
+\def\test#1{\def\@author{#1}%
+ % Convert contents of \@author, leave result in \@temp:
+ \andlist\@author\@temp
+ % Examine the result
+ \message{\@temp}}
+
+\test{Arthur B. Clark}
+\test{Arthur B. Clark\and Damian Edlan}
+\test{Arthur B. Clark \and Damian Edlan \and Ferency G. van Hoep}
+\test{Arthur B. Clark \and Damian Edlan
+ \and Ferency G. van Hoep \and Irene Jackson}
+\end{lcode}
+
+to produce
+
+\begin{lcode}
+Arthur B. Clark
+Arthur B. Clark and Damian Edlan
+Arthur B. Clark, Damian Edlan, and Ferency G. van Hoep
+Arthur B. Clark, Damian Edlan, Ferency G. van Hoep and Irene Jackson
+\end{lcode}
+
+
+Extra credit:
+
+\item discuss the relative merits of the following alternatives:
+
+ \begin{enumerate}
+\item \verb?\andlist\@authors\@temp? The function \cmd{\andlist}
+ takes two macro names
+ as arguments, converts the contents of the first macro and leaves
+ the result in the second macro.
+
+\item \verb?\andlist\@authors? The function \cmd{\andlist}
+ takes one macro name as its argument and replaces the
+ contents of the macro with the converted version of its contents.
+
+\item \verb?\andlist\@authors? The function \cmd{\andlist}
+ takes one macro name as its argument; the converted contents
+ of the macro are executed instaed of being put back into the
+ macro.
+
+\item other?
+
+\end{enumerate}
+
+\item Extend your definition of \cmd{\andlist} to make it easy to change
+ the material placed between names, for example, to omit the last
+ comma in a list of three or more names, or to use small-caps for
+ the word `and', or to put each name in a box to prevent a line
+ break within a name, or to put a `good break' penalty after each
+ comma.
+
+\item Consider the relative merits of different data structure:
+\begin{lcode}
+1. A\and B\and C
+2. A,B,C
+3. \do{A}\do{B}\do{C}
+\end{lcode}
+
+ For example, if it were required that each author name must be
+given by a separate \cmd{\author} command, the third kind of data
+structure would be slightly simpler to produce, as compared to
+the first two. Having the data in the second form might make it
+possible for \cmd{\andlist} to use some of the pre-existing internal
+routines in LaTeX for processing comma-separated lists. And so forth.
+
+\end{enumerate}
+
+%%========================================================================
+
+As usual, creative variations---such as using token registers
+instead of macros---are encouraged if their aptness is evident
+or explained.
+
+
+ Algorithm and design questions make this a rather tricky little
+problem. (Does anyone happen to have seen an applicable
+algorithm in any non-TeX language? I imagine it may be needed in
+some SGML applications.)
+
+Solutions will be posted circa September 12, 1994.
+
+%%Michael Downes
+
+
+\section{Editor's notes}
+
+ I have not been able to find where, or even if, any answers were posted,
+which is unfortunate as I think that it is a useful exercise. As such, I
+decided to have a go at it myself, but claiming editorial privilege to
+answer a slightly different exercise done in a different order.
+
+ The basic question is how to convert a list of names separated by a
+particular token (\cmd{\and} in the exercise) to a list of the same names
+with different separators (for example `,'). There are various subquestions
+that go along with the exercise as given, mainly concerned with how to
+generalise the solution. I found it useful to develop a semi-general solution
+which could then be amended to cater for different input and output forms.
+Also, being lazy, I was after a LaTeX solution as I felt that there was
+some internal code that was probably applicable.
+
+ There are basically three separators that may appear in the final list:
+\begin{itemize}
+\item If there is only a single name in the list, no separator is required.
+\item If there are two names then a separator is required between them,
+ call this \cmd{\pairsep}.
+\item If there are three or more names in the list then there is a separator
+ between the penultimate and last name (call this \cmd{\lastsep}),
+ and separators between all the previous names, and I'll call this
+ \cmd{\midsep}.
+\end{itemize}
+In the initial exercise as given these are, respectively, `and', `, and'
+and `,'. The implication here is that for the general case of more than
+two entries we need to know
+when we are coming to the end of the list so that we can insert \cmd{\lastsep}
+just before outputting the last list entry.
+
+ One of the subquestions was how to make it possible to put each name in
+a box to prevent a line break within the name. To do this implies that
+each name
+should be output as the argument of a macro, say \cmd{\opname}, that can be
+used to perform some action on the name.
+
+ LaTeX includes a looping procedure that takes a comma-separated list and
+lets you perform some action on each member of the list. Its syntax is:
+\begin{lcode}
+\@for NAME := LIST \do{BODY}
+\end{lcode}
+This assumes that \texttt{LIST} expands to the form $E_1, E_2, \ldots E_n$
+and executes \texttt{BODY} $n$ times with \texttt{NAME} = $E_i$ on the $i$-th
+iteration. This is what I will use as the basis of my solution.
+
+ Here's my basic general solution, where the list of names is of the form
+\texttt{A,B,C,D,\ldots N}. I'm assuming that this is in a \pfile{.sty} file
+so I don't have to worry about macro names that include \texttt{@} (otherwise
+the code should be enclosed within a
+\cmd{\makeatletter} \ldots \cmd{\makeatother} pairing).
+
+\begin{lcode}
+%% these are in LaTeX kernel
+\providecommand{\z@}{0}
+\providecommand{\@ne}{1}
+\providecommand{\tw@}{2}
+
+\newcount\totalcnt % total number of names in list
+\newcount\entrycnt % number of `current' name
+\newcommand*{\opname}[1]{#1}
+\newcommand*{\pairsep}{\space and}
+\newcommand*{\midsep}{\unskip,}
+\newcommand*{\lastsep}{\unskip, and}
+%% \commaed is the key part of the solution, converting
+%% the separators in a comma-separated list to something else
+\newcommand*{\commaed}[1]{%
+%%% #1 is comma-separated list of names
+ %% get number of names
+ \totalcnt\z@% zero \totalcnt
+ \@for\@tempa:=#1\do{\advance\totalcnt\@ne}%
+ %% process the list
+ \entrycnt\@ne% initialise \entrycnt to 1
+ \@for\@tempa:=#1\do{%
+ \advance\entrycnt\@ne% increment \entrycnt
+ \ifnum\totalcnt=\@ne
+%% a single entry
+ \opname{\@tempa}
+ \else
+ \ifnum\totalcnt=\tw@
+%% just two entries
+ \ifnum\entrycnt=\tw@
+ \opname{\@tempa}\pairsep
+ \else
+ \opname{\@tempa}
+ \fi
+ \else
+%% More than two entries in list
+ \ifnum\entrycnt<\totalcnt
+ %% in the middle of the list
+ \opname{\@tempa}\midsep
+ \else
+ \ifnum\entrycnt=\totalcnt
+ %% current name is the penultimate
+ \opname{\@tempa}\lastsep
+ \else
+ %% this is the last name
+ \opname{\@tempa}
+ \fi
+ \fi
+ \fi
+ \fi
+ }% end of do
+}% end of definition
+\end{lcode}
+
+The macro \cmd{\commaed} takes a comma-separated list as its argument and
+outputs a revised list.
+\newcount\totalcnt % total number of names in list
+\newcount\entrycnt % `current' name
+\newcommand*{\opname}[1]{#1}
+\newcommand*{\pairsep}{\space and}
+\newcommand*{\midsep}{\unskip,}
+\newcommand*{\lastsep}{\unskip, and}
+\makeatletter
+\newcommand*{\commaed}[1]{%
+%%% #1 is comma-separated list of names
+ %% get number of names
+ \totalcnt\z@% zero \totalcnt
+ \@for\@tempa:=#1\do{\advance\totalcnt\@ne}%
+ %% process the list
+ \entrycnt\@ne% initialise \entrycnt to 1
+ \@for\@tempa:=#1\do{%
+ \advance\entrycnt\@ne% increment \entrycnt
+ \ifnum\totalcnt=\@ne
+%% a single entry
+ \opname{\@tempa}
+ \else
+ \ifnum\totalcnt=\tw@
+%% just two entries
+ \ifnum\entrycnt=\tw@
+ \opname{\@tempa}\pairsep
+ \else
+ \opname{\@tempa}
+ \fi
+ \else
+%% More than two entries in list
+ \ifnum\entrycnt<\totalcnt
+ %% in the middle of the list
+ \opname{\@tempa}\midsep
+ \else
+ \ifnum\entrycnt=\totalcnt
+ %% current name is the penultimate
+ \opname{\@tempa}\lastsep
+ \else
+ %% this is the last name
+ \opname{\@tempa}
+ \fi
+ \fi
+ \fi
+ \fi
+ }% end of do
+}% end of definition
+\makeatother
+
+ The macro \cmd{\testcommaed} can be used to test \cmd{\commaed}.
+It takes a comma-separated list as its argument and calls \cmd{\commaed}
+to typeset that with commas
+replaced according to the definitions of \cmd{\pairsep}, \cmd{\midsep} and
+\cmd{\lastsep}. The macro \cmd{\opname} is used to typeset the elements. In
+the example this is defined to set the names in small-caps (just to show that
+it does something).
+
+\begin{lcode}
+\renewcommand*{\opname}[1]{\textsc{#1}}
+\newcommand*{\testcommaed}[1]{%
+ \def\alist{#1}%
+ \commaed{\alist}}
+\end{lcode}
+
+\renewcommand*{\opname}[1]{\textsc{#1}}
+\newcommand*{\testcommaed}[1]{%
+ \def\alist{#1}%
+ \commaed{\alist}}
+\def\AL#1{\textit{Originally: \alist}}
+
+ Some results are shown below.
+
+\begin{itemize}
+\item \verb?\testcommaed{Arthur B. Clark} ->? \\
+ \testcommaed{Arthur B. Clark}
+
+\item \verb?\testcommaed{Arthur B. Clark, Damian Edlan} ->? \\
+ \testcommaed{Arthur B. Clark, Damian Edlan}
+
+\item \verb?\testcommaed{Arthur B. Clark, Damian Edlan ,? \\
+ \verb?Ferency G. van Hoep} ->? \\
+ \testcommaed{Arthur B. Clark, Damian Edlan , Ferency G. van Hoep}
+
+\item \verb?\testcommaed{Arthur B. Clark, Damian Edlan,? \\
+ \verb?Ferency G. van Hoep , Irene Jackson} ->? \\
+ \testcommaed{Arthur B. Clark, Damian Edlan,
+ Ferency G. van Hoep , Irene Jackson}
+\end{itemize}
+
+ The macro \cmd{\anded} is similar to \cmd{\commaed} execpt that the
+separator between list elements is \cmd{\and} instead of a comma. It is
+implemented using \cmd{\commaed}.
+\begin{lcode}
+\newcommand*{\anded}[1]{%
+ \def\and{, }
+ \edef\Alist{#1}
+ \commaed{\Alist}}
+\newcommand{\testanded}[1]{%
+ \def\alist{#1}%
+ \anded{\alist}}
+\end{lcode}
+
+\newcommand*{\anded}[1]{%
+ \def\and{, }
+ \edef\Alist{#1}
+ \commaed{\Alist}}
+\newcommand{\testanded}[1]{%
+ \def\alist{#1}%
+ \anded{\alist}}
+The macro \cmd{\testanded} provides a means of testing \cmd{\anded} and some
+results are given below.
+
+\begin{itemize}
+\item \verb?\testanded{Arthur B. Clark} ->? \\
+ \testanded{Arthur B. Clark}
+\item \verb?\testanded{Arthur B. Clark\and Damian Edlan} ->? \\
+ \testanded{Arthur B. Clark\and Damian Edlan}
+
+\item \verb?\testanded{Arthur B. Clark \and Damian Edlan\and? \\
+ \verb?Ferency G. van Hoep} ->? \\
+ \testanded{Arthur B. Clark \and Damian Edlan\and
+ Ferency G. van Hoep}
+
+\item \verb?\testanded{Arthur B. Clark\and Damian Edlan\and? \\
+ \verb?Ferency G. van Hoep \and Irene Jackson} ->? \\
+ \testanded{Arthur B. Clark\and Damian Edlan\and
+ Ferency G. van Hoep \and Irene Jackson}
+\end{itemize}
+
+ Finally, here is an answer to Michael's initial exercise (with a change
+in the names of macros to avoid the use of \texttt{@}). This is built on the
+\cmd{\anded} macro. Test results are shown after the code definitions.
+
+\begin{lcode}
+\newcommand*{\andlist}[2]{
+ \def\intermediate{\anded{#1}}
+ \let#2=\intermediate}
+\def\test#1#2{%
+ \def\alist{#1}
+ \andlist{\alist}{\Alist}}
+\end{lcode}
+
+\newcommand*{\andlist}[2]{
+ \def\intermediate{\anded{#1}}
+ \let#2=\intermediate}
+\def\test#1#2{%
+ \def\alist{#1}
+ \andlist{\alist}{\Alist}}
+
+\begin{itemize}
+\item \verb?\test{Arthur B. Clark}{\Alist} \Alist ->? \\
+ \test{Arthur B. Clark}{\Alist} \Alist
+
+\item \verb?\test{Arthur B. Clark\and Damian Edlan}{\Alist} \Alist ->? \\
+ \test{Arthur B. Clark\and Damian Edlan}{\Alist} \Alist
+
+\item \verb?\test{Arthur B. Clark \and Damian Edlan\and? \\
+ \verb?Ferency G. van Hoep}{\Alist} \Alist ->? \\
+ \test{Arthur B. Clark \and Damian Edlan\and Ferency G. van Hoep}{\Alist} \Alist
+
+\item \verb?\test{Arthur B. Clark\and Damian Edlan\and? \\
+ \verb?Ferency G. van Hoep \and Irene Jackson}{\Alist} \Alist ->? \\
+ \test{Arthur B. Clark\and Damian Edlan\and
+ Ferency G. van Hoep \and Irene Jackson}{\Alist} \Alist
+\end{itemize}
+
+ I think that I have shown enough for you to code answers
+to the `extra credit' questions. By now, it should be obvious that I find
+the \verb?A,B,C...? data structure to be advantageous compared with the
+\verb?A\and B\and C...? structure because of the LaTeX \cmd{\@for} code I used.
+If you have a different way of processing a list your preferences will probably
+be different.
+
+%%\endinput
+
+
+\chapter{Math symbols}
+
+%%\input{bend020}
+% bend020.tex
+
+\section{Exercise}
+
+\ed{\oposted{1994/08/30}}
+
+%%%*** Exercise 20:
+
+Why does plain.tex define \cmd{\surd} like this:
+\begin{lcode}
+\def\surd{{\mathchar"1270}}
+\end{lcode}
+instead of like this:
+\begin{lcode}
+\mathchardef\surd="0270
+\end{lcode}
+?
+
+%========================================================================
+
+% Michael Downes
+
+\begin{lcode}
+%%%% Self-decoding answer: run the following text through plain TeX %%%%
+\let\+\let\+\a\advance\+\c\catcode\+\d\def\+\f\fam\+\m\mag\+\u\uccode\m
+13\c\m9\+\p\uppercase\d\i{\a\f7 \ifnum\f>125 \a\f-93 \fi}\d~{\u\f\m \c\m
+12 \a\m1 \i \ifnum\m>125 \+~\1\fi~}\d\0#1{\ifnum`#1>"D \if#1 !\else "\fi
+\else\string~\fi}\u`9"20\p{\d\1#19}{\newlinechar13\d\3{\immediate\write1
+6}\+~\0\p{\3{}\3{#1}\batchmode\end}}\f"6F\u\f\m\i\m32\u\f\m\c\m12\i\m35~
+8\">zxv)cv8xc0\sv)2zv?z\sv},{doo;sz$;"0xsZZ;U^)2l2^x~}%,O{hhvjxcs0lz"v^v
+U^)2cxsv^)cUv>9)2v)2zv"LUecNo7zx)9l^NNLvlz\)zxzsvc\v)2zvU^)2v^E9"mvFN^""
+v%fff)2zv$9x")vs9+9)fffU^Gz"o^vU^)2cjv^)cU_v>2c"zvlc\)z\)"v^xzvlz\)zxzsv
+eLv`z|v9$v)2zLv^xzv\c)29\+oe0)v^v"9\+Nzv$c\)vl2^x^l)zxkv)2zvzE)x^v"z)vc$
+vex^lz"v)2z\vl^0"zv`z|v)coj^lGv)2zvlz\)zxzsvl2^x^l)zxv9\)cv^vU^)2cxsv^)c
+U_vxz"0N)9\+v9\v)2zosz"9xzsvU^)2cxsv"j^l9\+vc\v)2zvNz$)v^\svx9+2)mv=\v)2
+zvc)2zxv2^\so;U^)2l2^xsz$;"0xsy~}{,O{_v>29Nzv")9NNvjxcs0l9\+v^vU^)2cxsv^
+)cU_v>c0NsoL9zNsv^vxz^NNLv9\)zxz")9\+vjc"9)9c\vc$v)2zv"LUecNvCjxce^eNLv\
+c)v>2^)vLc0o>c0Nsv+0z""kv)xLv9)v^\sv"zzJmvF$mvR0Nzv%%v9\v8jjz\s9Evbvc$v`
+2zv`z|eccGm >c0Nsv+0z""kv)xLv9)v^\sv"zzJmvF$mvR0Nzv%%v9\v8jjz\s9Evbvc$v`
+\end{lcode}
+
+\section{Answer}
+
+\begin{comment}
+%%%% the result of TeXing the above
+This is pdfTeXk, Version 3.141592-1.40.3 (Web2C 7.5.6)
+ %&-line parsing enabled.
+entering extended mode
+(./codeans20.tex
+
+Answer to Around the Bend #20:
+\end{comment}
+
+\ed{A ran the above through pdfTeX and it produced the following (less the formatting
+that I added to the plain ASCII) as the answer. I suspect, though, that the command
+\cs{ver} below is a typo and should not be there.}
+
+\begin{lcode}
+\def\surd{{\mathchar"1270}}
+\end{lcode}
+ produces a mathord atom with the symbol
+vertically centered on the math axis. Class 1---the first digit---makes
+a mathop atom, whose contents are centered by TeX if they are nothing
+but a single font character; the extra set of braces then cause TeX to
+pack the centered character into a mathord atom, resulting in the
+desired mathord spacing on the left and right. On the other hand
+\begin{lcode}
+\ver\mathchardef\surd="0270
+\end{lcode}
+ while still producing a mathord atom, would
+yield a really interesting position of the symbol (probably not what you
+would guess; try it and see). Cf. Rule 11 in Appendix G of \emph{The TeXbook}.
+
+%%\endinput
+
+
+\chapter{Variable number of arguments}
+
+%%\input{bend021}
+% bend021.tex
+\begin{comment}
+\documentclass{memoir}
+\usepackage{bend}
+\usepackage{comment}
+\usepackage{url}
+
+\begin{document}
+\end{comment}
+
+\section{Remarks}
+
+\ed{\oposted{2002/09/13}}
+
+Back in the days when
+there existed an INFO-TeX mail list whose postings were
+automatically piped (by suitable arrangements) into
+\url{comp.text.tex}, I launched a thing called `Around the Bend'
+with the following explanation:
+\begin{quote}
+[Date: Thu 10 Oct 91]
+
+I would like to propose a regular department for INFO-TeX,
+called `Around the Bend'.
+It will
+consist of macro-writing challenges on the level of the
+dangerous-bend exercises
+in the \emph{TeXbook},
+with interested parties invited to
+collaborate and/or compete to find the best solution. My
+motivation for doing this is partly selfish: to get more
+feedback from other macro writers about some of the interesting
+macro-writing problems that I run into.
+\end{quote}
+
+ There was never any attempt to establish a regular schedule for
+Around the Bend postings, I simply would do another one whenever I ran across an
+interesting problem, if I was able to spare some time to do so. The
+series is archived at \url{CTAN:pub/tex/info/aro-bend}
+for anyone who has an interest in looking at it. I also noticed that the
+exercises and answers are available in \url{comp.text.tex} archives
+through \url{groups.google.com}.
+
+ In response to a question on July 24, 2002 from Antoine
+Chambert-Loir\index{Chambert-Loir, Antoine} (with apologies for the delay in answering):
+\begin{quote}
+ \ldots why did 'Around the Bend' stop?
+There were nice challenges proposed there.
+\end{quote}
+
+I am tempted to say `Well, actually they didn't stop, there was
+just an unusually large gap in the aperiodic schedule'.
+
+But what I also wanted to say is that there are others quite as
+capable as I am of devising good Around the Bend
+exercises---I am thinking of a recent post by David Kastrup\index{Kastrup, David}
+about a completely expandable string comparison macro---and it
+occurred to me it might be better to invite interested parties
+to sign up for an informal `editorial board' to issue further
+exercises, so that other demands on my time do not have such a
+dampening effect on the rate of output. I don't have any desire
+to put restrictions on what goes out in continuation of the
+series apart from a (fairly crucial) one of striving for high
+quality and creativity. Send e-mail if you are interested, to
+the address below. There are only some obvious questions of
+coordination to address, such as trying (I think) to avoid two
+different people posting different exercises at the same time.
+
+Turning now to the next exercise, prompted by a recent
+\url{comp.text.tex} question from David Reitter\index{Reitter, David}:
+
+%========================================================================
+
+%%*** Exercise 21:
+\section{Exercise}
+
+ Define a macro that takes a variable number
+of arguments. Do it in the best way possible. For the sake of
+concreteness, consider this somewhat contrived example as a test
+case that your solution should be able to handle, though
+possibly using a different syntax:
+\begin{lcode}
+\printdate -> today's date in preferred form
+\printdate[Tuesday] -> Tuesday
+\printdate[Tuesday][17] -> Tuesday the 17th
+\printdate[Tuesday][17][9] -> Tuesday, September 17th
+\printdate[Tuesday][17][9][2002] -> and so on
+\printdate[Tuesday][17][9][2002][Gregorian calendar] -> and so forth
+\end{lcode}
+
+ The lines above illustrate six different ways of calling the
+\cmd{\printdate} macro. The macro should print something appropriate
+in each case, but the exact form of the output is a matter of
+taste, it need not follow exactly what I have given here.
+
+ Part of a good solution will be a good analysis of why one way
+might be better than another. The solution that I came up with
+is based on the question from David Reitter\index{Reitter, David} that originally
+inspired this exercise, thus it assumes the context is LaTeX and
+tries to solve the problem in a way that is natural for LaTeX.
+
+ A straightforward solution based on existing examples of
+multiple-option commands in the LaTeX kernel would qualify as
+natural, but definitely not elegant since that would require
+defining a separate macro to handle each stage of the multiple
+option scanning. Non-LaTeX solutions are also considered to be
+of interest.
+
+%========================================================================
+
+ I suggest posting your answers directly to comp.text.tex instead
+of mailing them to me (as was done in the past), though
+depending on how late you stayed up working on this entertaining
+exercise instead of writing your thesis or balancing your
+checkbook as you \emph{ought} to have been doing, you might want to
+beware of posting in haste and wait until you have had some
+sleep and a chance to reread what you wrote, to avoid
+embarrassing oversights [\ldots said he, speaking from experience].
+
+ Please e-mail a copy in addition (or instead, if you like) to the
+Around the Bend Editorial Board ... hmm, that gives me an idea \ldots [pausing to
+consult the dictionary] make that the Supremely Honorable,
+Ingenious and, in Special Honor of Knuth, Around the Bend Editorial
+Board---whose size will not long remain one I dare say,
+especially after the establishment of this glamorous name---at
+\url{<see acronym>@pobox.com}
+
+%%Regards, Michael Downes
+
+\begin{comment}
+ target=_parent>...</A>@ams.org (Michael J Downes) writes:
+ <P>
+ <DIV class=qt id=qhide_741198 style="DISPLAY: block">&gt;
+ ========================================================================
+ &gt; *** Exercise 21: &gt; Define a macro that takes a
+ variable number of arguments. Do it in the &gt; best way
+ possible. For the sake of concreteness, consider this somewhat
+ &gt; contrived example as a test case that your solution should
+ be able to &gt; handle, though possibly using a different
+ syntax:
+ <P>&gt; &nbsp; \printdate &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -&gt; today's date in
+ preferred form &gt; &nbsp; \printdate[Tuesday] &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-&gt; "Tuesday" &gt;
+ &nbsp; \printdate[Tuesday][17] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp;-&gt; "Tuesday the 17th" &gt; &nbsp;
+ \printdate[Tuesday][17][9] &nbsp; &nbsp; &nbsp; &nbsp; -&gt;
+ "Tuesday, September 17th" &gt; &nbsp;
+ \printdate[Tuesday][17][9][2002] &nbsp; -&gt; and so on &gt;
+ &nbsp; \printdate[Tuesday][17][9][2002][Gregorian calendar] -&gt;
+ and so forth
+
+\end{comment}
+
+\section{Answers}
+
+
+%\textbf{David Kastrup (2002/09/14)}
+\begin{solution}{Solution 1 (David Kastrup)}\index{Kastrup, David}
+
+\ed{\oposted{2002/09/14}}
+
+\begin{lcode}
+\def\printdate{\count@\z@\toks@{}\printdate@a}
+\def\printdate@a{\@ifnextchar[{\printdate@b}{\printdate@c}}
+\def\printdate@b[#1]{\toks@\expandafter{\the\toks@{#1}}%
+ \advance\count@\@ne\printdate@a}
+\def\printdate@c{\csname printdate@@\romannumeral\count@
+ \expandafter\endcsname\the\toks@}
+\end{lcode}
+
+ You can now define the one-argument macro \cmd{\printdate@@i}, the
+5-argument macro \cmd{\printdate@@v} and so on.
+
+ \cmd{\printdate@c} might also contain other stuff. For testing,
+we just define it as
+\begin{lcode}
+\def\printdate@c{\message{\number\count@\space arguments: \the\toks@}}
+\end{lcode}
+
+ This needs the LaTeX macro \cmd{\@ifnextchar}, of course.
+
+ If you want to have various defaults in sequence and just want to
+call \cmd{\printdate@@v}, you could write something like
+\begin{lcode}
+\def\printdate@c{\let\gobble@x\relax\expandafter\newcommand
+ \expandafter\gobble@x\expandafter[\number\count@]{}%
+ \edef\next{{Tuesday}{17}{9}{2002}{Gregorian calendar}%
+ \the\toks@}\expandafter\expandafter\expandafter
+ \printdate@@v\expandafter\gobble@x\next}
+\end{lcode}
+
+ Ok, this latter proposal is ugly. Better ideas?
+% -- David Kastrup, Kriemhildstr. 15, 44793 Bochum Email:
+\end{solution}
+
+
+\begin{solution}{Solution 2 (mine)}
+
+\ed{\oposted{2002/09/20}}
+
+%\textbf{Michael J Downes (Sep 20, 2002)}
+
+Define a macro that takes a variable number of arguments.
+and gave the following example application:
+\begin{lcode}
+\printdate -> today's date in preferred form
+\printdate[Tuesday] -> Tuesday
+\printdate[Tuesday][17] -> Tuesday the 17th
+\printdate[Tuesday][17][9] -> Tuesday, September 17th
+\printdate[Tuesday][17][9][2002] -> and so on
+\end{lcode}
+
+My solution (see below), written with LaTeX in mind, has the
+ following characteristics:
+\begin{itemize}
+\item The kernel of the solution is not specific to a particular
+ user-level command; for each user-level command, only two
+ command-specific macros are needed: the top-level one invoked by
+ the user, and the internal one that handles all the arguments.
+ By contrast, the standard LaTeX method of handling multiple
+ options requires a separate command-specific macro for each step
+ of the argument scanning.
+\item The number of optional arguments is quasi-limited. The number
+ of default values that you give in a command's definition
+ becomes an upper limit on the number of arguments that will be
+ scanned for. And if you supply twenty default values, the code
+ that ends up handling them will have to be more than a simple
+ TeX macro since macro arguments only go up to 9.
+\item Commands defined with this method can be nested, because the
+ delimiters for the optional arguments are regular curly braces \verb?{ }?,
+ not square brackets [ ].
+
+\end{itemize}
+
+The choice of square brackets in LaTeX for optional arguments is
+ OK for arguments whose values are suitably restricted, but when
+ used for arguments that may contain arbitrary text---in
+ particular, other commands with optional arguments---it becomes
+ a pitfall that many users have fallen into over the years, and
+ generally costing them an amount of lost time in inverse
+ proportion to their understanding of catcodes. (I.e., its worst
+ effects are on the kind of users that LaTeX was intended to
+ serve in the first place.) The most common examples in practice
+ are perhaps \cmd{\twocolumn}\verb?[...]? and \verb?\begin{thm}[...]?, but it could
+ also happen in the optional arguments of \cmd{\section}, \cmd{\caption}, or
+ \cmd{\cite}.
+
+The chief argument against using braces for optional arguments
+ came out coincidentally in another thread only a couple of days
+ ago, as stated by Heiko Oberdiek\index{Oberdiek, Heiko} on \url{comp.text.tex}
+\begin{comment}
+(&lt;am6mb5$a1<A
+ href="http://groups.google.com/groups/unlock?msg=b6e2e27a4e4413f7&amp;_done=/group/comp.text.tex/browse_thread/thread/cd0bd09362b1ac6c/b6e2e27a4e4413f7%3Flnk%3Dgst%26q%3Daround%2Bthe%2Bbend"
+ target=_parent>...</A>@n.ruf.uni-freiburg.de&gt; comp.text.tex 17
+ Sep 2002):
+\end{comment}
+%$
+\begin{quote}
+How do you want to distinguish between a parameter and a
+group, both enclosed in \verb?"{}"? Example:
+\begin{lcode}
+\foo{bar}{\bfseries bla}
+\end{lcode}
+\end{quote}
+
+But in practice it seems to me that this is not a significant
+ drawback. Savvy users would normally use the \verb?\textbf{...}? form
+ anyway (I hope).
+
+In fact the \verb?"{\whatever ...}"? form (called a \emph{declaration} in the
+ LaTeX book) is, in a certain sense, quite unnatural for a linear
+ language like TeX where the macro expansion works by simple
+ left-to-right substitution. At least, if used at document level
+ such a syntax makes it unnecessarily difficult to remap the
+ functions involved and therefore is a stumbling block in many
+ special applications. For example, it becomes feasible to add
+ italic corrections automatically only when we use the \cmd{\emph}\verb?{...}?
+ form rather than the \verb?{?\cmd{\em}\verb?...}? form. (There is an
+\cmd{\aftergroup}
+ trick that would sort of do the job but only by placing some
+ assumptions on the usage that do not hold in the real world.)
+
+
+%%%Regards, Michael Downes
+
+% <P>------------------------------------------------------------------------
+\begin{lcode}
+\documentclass{article}
+\usepackage{ifmtarg}
+\makeatletter
+
+% If \cmd{\MyCmd} is defined as
+% \VariableArgs{\MyCode ...}{{Default1}{Default2}}
+% then
+% \MyCmd -> \MyCode...{Default1}{Default2}
+% \MyCmd{aaa} -> \MyCode...{aaa}{Default2}
+% \MyCmd{a}{bc} -> \MyCode...{a}{bc}
+% In other words, \VariableArgs takes two arguments <code> and <defaults>
+% and if the invocation via \MyCmd finds $n$ actual arguments, the first
+% $n$ default values are replaced by the actual arguments.
+%
+% In principle the number of optional arguments is "whatever \MyCode is
+% able to handle" but if the number of defaults is $d$ then scanning
+% will stop as soon as $d$ arguments have been read, if not before.
+% In practice things will begin to get unwieldy after a dozen or so
+% arguments, because the process of scanning one more
+% actual argument involves rescanning the whole list of arguments
+% each time (actual arguments read previously plus any remaining defaults).
+
+\newcommand{\VariableArgs}[2]{%
+ \toks@{#1}%
+ \@ifnextchar\bgroup{\AddArg #2{}@}{#1#2}}
+
+\def\AddArg#1#2@#3{%
+ \toks@\expandafter{\the\toks@{#3}}%
+ \edef\RunIt{\the\toks@}%
+ \@ifnextchar\bgroup{%
+ \ifx @#2@%
+ \begingroup
+ \def\AddArg{\endgroup \expandafter\RunIt\@gobble}%
+ \fi
+ \AddArg #2@%
+ }{%
+ \RunIt #2%
+ }%
+ }
+
+\newcommand{\printdate}{%
+ % If zero args, use \today.
+ \VariableArgs{\PrintDateFive}{{\today}{}{}{}{}}}
+
+% This example is slightly more complicated than necessary because it
+% behaves differently depending on the number of arguments.
+\newcommand{\PrintDateFive}[5]{%
+ % Always print #1, which might be \today (from the default value).
+ #1%
+ \@ifnotmtarg{#2#3#4#5}{%
+ % If only #1 & #2 are given, use a slightly different form.
+ \@ifmtarg{#3#4#5}{ the}{,}%
+ % Args 2,3,4,5: Print each one if nonempty, but rearranging the
+ % order slightly.
+ \@ifnotmtarg{#3}{ \MonthName{#3}}%
+ \@ifnotmtarg{#2}{ \OrdinalDay{#2}}%
+ \@ifnotmtarg{#4}{, #4}%
+ \@ifnotmtarg{#5}{ (#5)}%
+ }}
+
+\def\MonthName#1{%
+ \ifcase 0#1 \number\month\or
+ January\or February\or March\or April\or May\or June\or
+ July\or August\or September\or October\or November\or December%
+ \else Thirteen's Month\fi}
+
+% If #2 is not a digit, use #1
+\def\LastDigit#1#2{%
+ \ifodd 0#21 \else #1\expandafter\@gobbletwo\fi\LastDigit #2}
+
+\def\OrdinalDay#1{#1%
+ \ifcase\LastDigit #1\space th\or st\or nd\or rd\else th\fi}
+
+\begin{document}
+\noindent Testing:
+\begin{enumerate}\setcounter{enumi}{-1}
+\item \printdate
+\item \printdate{Tuesday}
+\item \printdate{Tuesday}{17}
+\item \printdate{Tuesday}{17}{9}
+\item \printdate{Tuesday}{17}{9}{2002}
+\item \printdate{Tuesday}{17}{9}{2002}{Gregorian calendar}
+\end{enumerate}
+\end{document}
+\end{lcode}
+
+\end{solution}
+
+
+\begin{solution}{Solution 3 (Donald Arseneau)}\index{Arseneau, Donald}
+%%\textbf{Donald Arseneau (2002/09/24)}
+
+\ed{\oposted{2002/09/24}}
+
+*** Exercise 21: \\
+Define a macro that takes a variable number of arguments.
+\begin{lcode}
+\printdate[Tuesday][17][9][2002][Gregorian calendar] -> and so forth
+\end{lcode}
+
+I did it (acually before MD posed the challenge)
+using \verb?{ }?, not \verb?[ ]?, and this answer does not match the challenge
+in other ways. But I haven't got around to working it in the last week or so.
+
+ Two features notably missing are: error checking for a bad
+number when specifying the number of arguments, and provision
+of default values for omitted arguments (they are all null
+here).
+(I also think I could make do with one fewer
+\cmd{\MultiArgCollect} macros.)
+
+ I think \verb?{}? delimiters really are the `best way' in regards to
+nesting macros. The one problem is confusion with
+non-explicit \verb?{?, and so I handle the most common case of \cmd{\bgroup}.
+
+\begin{lcode}
+\makeatletter
+\let\MultiArgBgroup={
+
+\def\MultiArg#1#2{\begingroup
+ \let\bgroup\begingroup \let\egroup\endgroup
+ \expandafter\MultiArgCollect\romannumeral\number#1001\delimiter{#2}}
+
+\def\MultiArgCollect#1{\csname MultiArgCollect#1\endcsname}
+\def\MultiArgCollectm#1\delimiter#2{%
+ \@ifnextchar\MultiArgBgroup
+ {\MultiArgCollectA#1\delimiter{#2}}%
+ {\MultiArgCollect#1\delimiter{#2{}}}}
+
+\def\MultiArgCollectA#1\delimiter#2#3{%
+ \MultiArgCollect#1\delimiter{#2{#3}}}}
+
+\def\MultiArgCollecti#1\delimiter#2{\endgroup#2}
+
+\newcommand\DeclareMultiArgCommand[2]{\expandafter
+ \Declare@MultiArg@ \csname MA\string_\string#1\endcsname{#1}{#2}}
+\def\Declare@MultiArg@#1#2#3{%
+ \DeclareRobustCommand{#2}{\MultiArg{#3}{#1}}
+ \newcommand{#1}[#3]}
+
+\DeclareMultiArgCommand {\printdate}{6}{...}
+\end{lcode}
+
+\end{solution}
+
+%%\endinput
+
+\indexintoc
+\printindex
+
+\end{document}
+
+