diff options
Diffstat (limited to 'Master/texmf-dist/doc/generic/arobend/AroundTheBend.tex')
-rw-r--r-- | Master/texmf-dist/doc/generic/arobend/AroundTheBend.tex | 7419 |
1 files changed, 0 insertions, 7419 deletions
diff --git a/Master/texmf-dist/doc/generic/arobend/AroundTheBend.tex b/Master/texmf-dist/doc/generic/arobend/AroundTheBend.tex deleted file mode 100644 index ac01d718075..00000000000 --- a/Master/texmf-dist/doc/generic/arobend/AroundTheBend.tex +++ /dev/null @@ -1,7419 +0,0 @@ -% 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">> - ======================================================================== - > *** Exercise 21: > 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: - <P>> \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{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} -(<am6mb5$a1<A - href="http://groups.google.com/groups/unlock?msg=b6e2e27a4e4413f7&_done=/group/comp.text.tex/browse_thread/thread/cd0bd09362b1ac6c/b6e2e27a4e4413f7%3Flnk%3Dgst%26q%3Daround%2Bthe%2Bbend" - target=_parent>...</A>@n.ruf.uni-freiburg.de> 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} - - |