From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Mon, 2 Sep 2019 13:46:59 +0900
Subject: Initial commit

---
 macros/latex/contrib/textmerg/textmerg.dtx | 890 +++++++++++++++++++++++++++++
 1 file changed, 890 insertions(+)
 create mode 100644 macros/latex/contrib/textmerg/textmerg.dtx

(limited to 'macros/latex/contrib/textmerg/textmerg.dtx')

diff --git a/macros/latex/contrib/textmerg/textmerg.dtx b/macros/latex/contrib/textmerg/textmerg.dtx
new file mode 100644
index 0000000000..58befcbfa2
--- /dev/null
+++ b/macros/latex/contrib/textmerg/textmerg.dtx
@@ -0,0 +1,890 @@
+%    \iffalse meta-comment
+%    \begin{macrocode}
+%<*textmerg|plain>
+\def\fileversion{2.01}
+\def\filedate{1994/06/20}
+\def\filename{textmerg.dtx}
+\def\Copyright{Copyright (C) 1992,1994 Mike Piff, University of Sheffield, England}
+%</textmerg|plain>
+%    \end{macrocode}
+%
+% This file is placed in the public domain.  No provision is made for
+% support of the use of the facilities herein.
+%
+% For updates, contact your nearest CTAN site.
+%
+%    \fi
+%
+% \changes{2.01}{1994/06/20}{First version for LaTeX2e}
+% \changes{2.01a}{2000/08/25}{rf10@cam.ac.uk --- relaxation of licence
+%   terms}
+%
+%\CheckSum{349}
+%
+%\title{Text merges in \TeX\ and \LaTeX\thanks{This article originally
+%appeared in TUGboat Vol 13(4), 1992, p518--523.}}
+%\author{Mike Piff}
+%\maketitle
+%\thispagestyle{headings}
+%\begin{abstract}
+%   In this article the author explains how to do some standard
+%   and not so standard word processor text merges in \TeX\ documents,
+%   using no other tools than \TeX\ itself.
+%   A common application is to the mail merge or form letter,
+%   where names and addresses are
+%   stored in a file, together with other bits of information, and a standard
+%   letter with variable fields embedded in it is customized for every name
+%   from this file.
+%   Another application is to the pretty-printing of the contents of a database.
+%
+%   The macros described in |textmerg.sty| work equally
+%   in both plain \TeX\ and \LaTeX. However, this has meant heavy use
+%   of |\def| where |\newcommand| would have been preferable.
+%\end{abstract}
+%
+%\tableofcontents
+%
+%\section{Introduction}
+%It is often said that although \LaTeX\ is good at typesetting
+%mathematics, it is wholly unsuitable for common word processor functions
+%such as mail merges.
+%The latter are easy to achieve in most ordinary word processors,
+%but in its raw state \LaTeX\ is incapable of doing a mail merge, or, indeed, of
+%generating the same block of text over and over again but with different
+%parameters in each block, those parameters having been read from a subsidiary
+%merge file.
+%The latter file might possibly be the output from a database or any other
+%program.
+%
+%This article aims to show the reader that such a repetitive task need not be
+%as difficult as it at first appears. In \TeX, it is possible to hide many
+%details of a facility inside a subsidiary style file, so that the user is
+%unaware of what fearful processes are going on in the background.
+%It is then possible to present the end-user with an extremely simple
+%interface, perhaps simpler and more powerful than is available in other
+%systems.
+%
+%In earlier TUGboat articles
+%\cite{Bell:TB8-1-54,Garavelli:TB8-1-53,Lee:TB7-3-187,%
+%McKinstry:TB8-1-60} it was shown how a standard letter could be
+%customized by adding names and addresses from a separate file. I aim to show
+%that it is possible to achieve far more than this with a fairly compact
+%but general set of macros.
+%
+%\section{A simple example}
+%Suppose that we have a list of student names and examination grades, one
+%per student, and that we wish to send a letter to each student giving
+%his/her exam grade.
+%We must decide first what bits of information must be prepared in
+%our subsidiary file, by looking at an example letter and finding out which
+%items change from letter to letter.
+%
+%Suppose that one instance of our letter is the following,
+%a  \LaTeX\ example.
+%\begin{verbatim}
+%\begin{letter}{Miss Iusta Mo\\
+%   34 Winchester Road\\
+%   Sheffield\\
+%   England}
+%   \opening{Dear Miss Mo,}
+%   This letter is to inform you
+%   that you obtained grade A in
+%   your recent examinations.
+%   \closing{Yours faithfully,}
+%\end{letter}
+%\end{verbatim}
+%We can see that we need to know the student's title, forename(s), surname,
+%address and grade to compose such a letter.
+%
+%One of the simplest ways of achieving this effect is to prepare a file
+%with lines of the form
+%\begin{verbatim}
+%\MyLetter{Mr}...{C}
+%\end{verbatim}
+%for each student and then simply |\input| it into a \LaTeX\ file in which
+%|\MyLetter| has been defined as having five parameters.
+%A problem with this approach is that we may not be able to coax the student
+%database into producing such a file.
+%Another problem is that we need something more subtle if there are fifty
+%parameters. For example, we might want to print out the
+%contents of the student database with one page per student, but it could be
+%that there are fifty information fields per student. Even worse,
+%the number of pieces of information per student might not be a
+%constant number, because, say, we are printing out fields from a related
+%file in which marks on individual examination papers are held.
+%
+%We shall tackle our simple example in a way that lends itself
+%to more generality later on, and in a form that most database programs
+%should be capable of handling.
+%
+%We thus prepare a subsidiary file |results.dat|
+%with records of five fields in it.
+%Each student is represented by five lines of this file,
+%    \begin{macrocode}
+%<*results>
+Miss
+Iusta
+Mo
+34 Winchester Road\\Sheffield\\England
+A
+Mr
+Arthur
+Minit
+43 Sheffield Road\\Winchester\\England
+C
+%</results>
+%    \end{macrocode}
+%and the student records appear one after another in this file.
+%Thus both the field and record separators are carriage returns.
+%
+%\DescribeMacro{\Merge}
+%\DescribeMacro{\Fields}
+%\TeX\ itself needs to know three bits of information:
+%\begin{enumerate}
+%   \item the name of the subsidiary file,
+%   \item the fields to read, and
+%   \item the template of the letter.
+%\end{enumerate}
+%We pass it this information in the following form
+%    \begin{macrocode}
+%<*examp>
+\documentclass[12pt]{letter}
+\usepackage{textmerg}
+\begin{document}
+\Fields{\Title\Forenames\Surname
+   \Address\Grade}
+\Merge{results.dat}{%
+\begin{letter}{\Title\ \Forenames\
+   \Surname\\\Address}
+   \opening{Dear \Title\ \Surname,}
+   This letter is to inform you
+   that you obtained grade \Grade\ in
+   your recent examinations.
+   \closing{Yours faithfully,}
+\end{letter}}
+\end{document}
+%</examp>
+%    \end{macrocode}
+%\LaTeX\ should
+%open the subsidiary file and, for each set of five parameters,
+%generate a letter in the |dvi| file. When it reaches the end of
+%the merge file, \LaTeX\ should terminate execution of the |\Merge|
+%command and presumably finish the document.
+%
+%\section{A few complications}
+%
+%Looking at the above example in a bit more generality,
+%we see that we are reading
+%records of $n$ fields from the merge file and placing them into a \TeX\ document
+%in such a way that they replace $n$ preassigned control sequences.
+%However, it may happen that the merge file is prepared by humans, who might
+%possibly have inserted some extra blank lines into the file. Again, it
+%could be that certain sorts of fields might be blank,
+%whereas others can never be blank.
+%Perhaps it would be better to build in some degree of error recovery.
+%
+%\DescribeMacro{\Fields}
+%We shall make the assumption that the first field in any record is definitely
+%a non-blank one and that we know beforehand whether each
+%of the others might conceivably be blank.
+%We make a modification to our |\Fields| statement.
+%It can contain not only
+%the field name control sequences but also the tokens |+| and~|-|,
+%with the following interpretation. A |+| indicates that all following
+%fields should be re-read until a non-blank result is obtained.
+%A |-| indicates that any following fields could conceivably be blank,
+%subject to the restriction that the very first field is always non-blank.
+%
+%Thus the command
+%\begin{verbatim}
+%\Fields{\a+\b\c-\d}
+%\end{verbatim}
+%would indicate that only |\d| is allowed to be blank, because the
+%|+| token has no effect.
+%In
+%\begin{verbatim}
+%\Fields{-\a\b+-\c+\d}
+%\end{verbatim}
+%the initial |-| token enables blank reading of data tokens, but the very
+%first data token is not permitted to be blank anyway.
+%Thus |\a| is read as a non-blank token and |\b| as a
+%possibly blank token.
+%The sequence |+-| now switches non-blank reading on and off again,
+%so |\c| is read as possibly blank.
+%Finally |\d| is non-blank.
+%
+%Another complication we allow is that the |\Fields| command can
+%appear several times in our file. The interpretation is that
+%the last occurrence of |\Fields| before we encounter the |\Merge|
+%command will indicate the fields to be read for every record. Any
+%occurrences of |\Fields| within the merged text indicate a new list
+%of fields to be read when that command is encountered. This lets us
+%do some conditional processing, such as\footnote{It is assumed that
+%{\tt\string\Mrs} expands to {\tt Mrs}.}
+%\begin{verbatim}
+%   \ifx\Title\Mrs
+%      \Fields{\MaidenName}
+%   \fi
+%\end{verbatim}
+%and also gives us some flexibility about the field order later on.
+%
+%It should also be stressed that the undefined control sequences
+%appearing in the template need not
+%correspond exactly to the fields in the subsidiary file.
+%An example might be that the subsidiary file contains the text
+%\begin{verbatim}
+%Spriggs, Mr Abraham L
+%\end{verbatim}
+%and one field read is |\FullName|.
+%\TeX\ would then have to pre-process this
+%name to generate its several components as used in the template.
+%The command |\PreProcess| could be included at the start of the template.
+%\begin{verbatim}
+%\def\parse#1, #2 #3\endparse{%
+%   \def\Surname{#1}\def\Title{#2}%
+%   \def\Forenames{#3}}
+%\def\PreProcess{\expandafter
+%   \parse\FullName\endparse}
+%\end{verbatim}
+%
+%An alternative and simpler looking approach to reading fields from a file
+%|\fil| might be to define each such field as
+%follows.
+%\begin{verbatim}
+%\def\Field#1{\def#1{\read\fil to#1#1}}
+%\Field\Name \Field\Address \Field\Mark
+%\end{verbatim}
+%The first time |\Name| is encountered, it reads its own expansion
+%from |\fil| and then expands itself.
+%Henceforth, it has acquired its new expansion.
+%The disadvantage is that |\Name| must appear in the
+%text before any subsidiary field such as |\Surname|
+%can be used.
+%
+%Finally we should consider the possibility that the second parameter of
+%|\Merge| might be too large to fit into memory. We can clearly handle
+%this problem by allowing the second parameter merely to consist of the text
+%|\input template|, so that the root file handles two subsidiary
+%files, one containing the template and the other containing the fields.
+%
+%
+%\section{A complicated example}
+%
+%We will next look at an example in which the template contains a table
+%of indeterminate length, albeit fixed width. So far our macros work
+%in either plain \TeX\ or in \LaTeX, but the way in which these
+%two packages handle
+%tables is slightly different. However, the only difference that need
+%concern us is that \LaTeX\ uses |\\| where plain \TeX\ uses |\cr|.
+%
+%\DescribeMacro{\MultiRead}
+%The example given here is in \LaTeX, but our style will work equally well
+%in plain \TeX. In our student letter we wish to insert a table of course
+%codes and marks. Since each student did a different number of courses, we
+%need some way of recognizing the end of the course list in the merge file.
+%The default will be to insert a blank line at the end of such a sub-list.
+%Thus, the following text appears before the close of the letter template.
+%\begin{verbatim}
+%Here are your marks on individual papers.
+%\begin{center}
+%   \begin{tabular}{|lr|}\hline
+%      Code&Mark\\\hline
+%      \MultiRead{2}\\\hline
+%   \end{tabular}
+%\end{center}
+%\end{verbatim}
+%The merge file now has the following structure.
+%\begin{verbatim}
+%Title
+%...
+%Grade
+%Code
+%Mark
+%...
+%Code
+%Mark
+%\end{verbatim}
+%$\langle${\it blank\/}$\rangle$
+%\begin{verbatim}
+%Title
+%...
+%\end{verbatim}
+%
+%\DescribeMacro{\MarkEnd}
+%In other applications some of the fields in the table might possibly be blank.
+%We then let the user change the $\langle${\it blank\/}$\rangle$
+%line marking the end of a list to some other string of his own choosing.
+%\begin{verbatim}
+%\MarkEnd{***}
+%\end{verbatim}
+%
+%There might be multiple tables in the same template,
+%with their data intermingled in the merge file with main fields.
+%The generalized |\Fields| command allows us
+%to order the merge file however we want. Thus we could have main fields, then
+%a table, followed by more main fields, and so on.
+%
+%\DescribeMacro{\Process}
+%A final complication is that the fields appearing in a table are essentially
+%anonymous. By this I mean that they are transferred into the table as
+%they are, without any pre-processing possible through appearing
+%in the template as control sequences. If we wish what appears in
+%the table to be different from what appears in the file, a mechanism is needed
+%to tell \TeX\ that a certain column has to be treated in a certain way.
+%The command
+%\begin{verbatim}
+%\Process{n}{\foo}
+%\end{verbatim}
+%will replace every field $\langle f\rangle$ read into column $n$
+%by |\foo{|$\langle f\rangle$|}|.
+%It is even possible to do some numerical calculations by this method.
+%
+%Here is a \LaTeX\ example to illustrate the table processing
+%features of |textmerg.sty|.
+%    \begin{macrocode}
+%<*example>
+\documentclass[12pt]{article}
+\usepackage{textmerg}
+\MarkEnd{***}
+\Process{2}{\Advance}
+\def\Advance#1{#1\addtocounter{page}{#1}}
+\Fields{+\Name\Verb}
+\begin{document}
+\Merge{silly.dat}{%
+   Dear \Name,\par
+   Here is a table to \Verb\ at:
+   \Fields{\Width}%
+   \begin{tabular}{*{\Width}c}
+      \MultiRead\Width
+   \end{tabular}.\par
+   \Fields{\Adj}%
+   That was \Adj!
+   \clearpage}
+\end{document}
+%</example>
+%    \end{macrocode}
+%The effect of this file is not apparent until we see |silly.dat|.
+%It is listed here.
+%    \begin{macrocode}
+%<*silly>
+Mike
+look
+3
+1
+2
+3
+11
+12
+13
+***
+good
+Shelagh
+gaze
+2
+21
+22
+23
+24
+***
+horrid
+%</silly>
+%    \end{macrocode}
+%
+%    The same can be done in plain \TeX.
+%    \begin{macrocode}
+%<*plainexample>
+\input textmerg
+\MarkEnd{***}
+\Process{2}{\Advance}
+\def\Advance#1{#1\global\advance\count0by#1}
+\Fields{+\Name\Verb}
+\Merge{silly.dat}{%
+   Dear \Name,\par
+   Here is a table to \Verb\ at:
+   \Fields{\Width}%
+   \vbox{\halign{\hfil{} ## {}\hfil&&\hfil{} ## {}\hfil\cr
+      \MultiRead\Width\cr
+   }}.\par
+   \Fields{\Adj}%
+   That was \Adj!
+   \vfill\eject}
+\end
+
+%</plainexample>
+%    \end{macrocode}
+%
+%
+%\StopEventually{
+%\begin{thebibliography}{GHWW84}
+%\bibitem[{Bel}87]{Bell:TB8-1-54}
+%Edwin~V. {Bell, II}.
+%\newblock {{AutoLetter: A \TeX\ form letter procedure}}.
+%\newblock {\em TUGBoat}, 8(1):54, April 1987.
+%
+%\bibitem[Gar87]{Garavelli:TB8-1-53}
+%John~S. Garavelli.
+%\newblock {{Form letter macros}}.
+%\newblock {\em TUGBoat}, 8(1):53, April 1987.
+%
+%\bibitem[Lee86]{Lee:TB7-3-187}
+%John Lee.
+%\newblock {{Form letters}}.
+%\newblock {\em TUGBoat}, 7(3):187, October 1986.
+%
+%\bibitem[McK87]{McKinstry:TB8-1-60}
+%Graeme McKinstry.
+%\newblock {{Form letters}}.
+%\newblock {\em TUGBoat}, 8(1):60, April 1987.
+%\end{thebibliography}
+%}
+%
+%    \section{Identification}
+%
+%    This package can only be used with \LaTeXe, so
+%    an appropriate message is displayed when another
+%    format is used\footnote{However, some code is inserted
+%    to allow its use with plain \protect\TeX}.
+%    \begin{macrocode}
+%<*textmerg>
+\NeedsTeXFormat{LaTeX2e}[1994/01/01]
+%    \end{macrocode}
+%
+%    Announce the package name and its version:
+%    \begin{macrocode}
+\ProvidesPackage{textmerg}[\filedate]
+%    \end{macrocode}
+%
+%     And display it on the terminal (and the log file):
+%    \begin{macrocode}
+\typeout{Package `textmerg' <\filedate>.}
+\typeout{\Copyright}
+%</textmerg>
+%    \end{macrocode}
+%
+%    The plain \TeX\ version will simply |\input| this package file. Thus
+%    we need to know that it will understand everything in the file.
+%    \begin{macrocode}
+%<*plain>
+\def\NeedsTeXFormat#1[#2]{}
+\def\ProvidesPackage#1[#2]{}
+\def\typeout#1{\immediate\write0{#1}}
+\input textmerg.sty
+%</plain>
+%    \end{macrocode}
+%
+%
+%\section{Implementation of the simple case}
+%
+%    \begin{macro}{\glet}
+%For convenience we define a frequently used combination here.
+%    \begin{macrocode}
+%<*textmerg>
+\def\glet{\global\let}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\MergeFile}
+%    \begin{macro}{\InputFile}
+%The subsidiary merge file is defined next. A macro is then defined that
+%attempts to open it for reading. If that is unsuccessful, the file is
+%closed and an error message is issued.
+%    \begin{macrocode}
+\newread\MergeFile
+\def\InputFile#1{%
+   \openin\MergeFile=#1
+   \ifeof\MergeFile
+   \errmessage{Empty merge file}%
+   \closein\MergeFile
+   \long\def\MakeTemplate##1{%
+      \def\Template{}}%
+   \else\GetInput\fi}
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%The command |\MakeTemplate| will be used later to generate the body
+%of the form into which fields are inserted. We redefine it if the file
+%is empty so that it produces no text.
+%
+%    \begin{macro}{\GetInput}
+%Because the conditional |\ifeof| does not return true until after an
+%unsuccessful read operation, a mechanism of looking ahead is used which is
+%similar to that found in Pascal.
+%    \begin{macrocode}
+\def\GetInput{{\endlinechar=-1
+   \global\read\MergeFile to\InputBuffer}}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\SeeIfEof}
+%    \begin{macro}{\LookAgain}
+%We set up a mechanism for deciding whether or not we have
+%exhausted the merge file. It forces |\ifeof| to return true
+%by skipping over blank lines.
+%    \begin{macrocode}
+\def\SeeIfEof{%
+   \let\NextLook\relax
+   \ifeof\MergeFile
+   \else
+      \ifx\InputBuffer\empty
+         \LookAgain
+      \fi
+   \fi
+   \NextLook}
+\def\LookAgain{\GetInput
+   \let\NextLook\SeeIfEof}
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%
+%    \begin{macro}{\ifNonBlank}
+%    \begin{macro}{\AllowBlank}
+%    \begin{macro}{\DontAllowBlank}
+%We can now prepare to read actual fields from the merge file. A conditional
+%is used to indicate whether or not the field we are about to read is
+%allowed to be blank. We also set up a mechanism for changing its value.
+%    \begin{macrocode}
+\newif\ifNonBlank \NonBlankfalse
+\def\AllowBlank{\global\NonBlankfalse}
+\def\DontAllowBlank{\global\NonBlanktrue}
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%    \end{macro}
+%
+%    \begin{macro}{\ReadIn}
+%    \begin{macro}{\MissingField}
+%Fields are actually read by means of the following command. Its only
+%parameter is the name of the control sequence into which the field is
+%read.
+%    \begin{macrocode}
+\def\ReadIn#1{%
+   \ifNonBlank\SeeIfEof\fi
+   \ifeof\MergeFile
+      \gdef#1{??}\MissingField
+   \else
+      \glet#1\InputBuffer
+      \GetInput
+   \fi}
+\def\MissingField{%
+   \message{Missing field in file}}
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%
+%    \begin{macro}{\GlobalFields}
+%    \begin{macro}{\Fields}
+%The |\Fields| command places its parameter into a token
+%register called |\GlobalFields|.
+%This command will be redefined by the |\Merge| command.
+%    \begin{macrocode}
+\newtoks\GlobalFields
+\def\Fields#1{\GlobalFields{#1}}
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%
+%    \begin{macro}{\ParseFields}
+%    \begin{macro}{\EndParseFields}
+%When a field token list is read,
+%each individual token within it must be either
+%read as a field or interpreted as a blank/nonblank switch.
+%The next token is then read by tail recursion.
+%It is assumed that the final token in the list is |\EndParseFields|.
+%This must be defined to expand to something unlikely to be read as a
+%value of one of the fields, and so we |\let| it to |\ParseFields|.
+%    \begin{macrocode}
+\def\ParseFields#1{%
+   \ifx#1\EndParseFields
+      \let\NextParse\relax
+   \else
+      \let\NextParse\ParseFields
+      \ifx#1+\DontAllowBlank
+      \else
+         \ifx#1-\AllowBlank
+         \else\ReadIn#1
+         \fi
+      \fi
+   \fi\NextParse}
+\let\EndParseFields\ParseFields
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%
+%    \begin{macro}{\ReadFields}
+%We apply this command to our token register after expanding it.
+%    \begin{macrocode}
+\def\ReadFields#1{\expandafter\ParseFields
+   \the#1\EndParseFields
+   \AllowBlank}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\Merge}
+%    \begin{macro}{\MakeTemplate}
+%At long last we are ready to define the |\Merge| command itself.
+%The first parameter is the filename of the subsidiary file and the second
+%is the template or form into which fields are inserted.
+%Since a |\Fields| command within the |\Merge| text is meant
+%to act immediately on the token list that follows it, we redefine it
+%to operate in a different way.
+%    \begin{macrocode}
+\long\def\Merge#1#2{\begingroup%
+   \InputFile{#1}%
+   \def\Fields##1{%
+      \ParseFields##1\EndParseFields}%
+   \MakeTemplate{#2}\Iterate}
+\long\def\MakeTemplate#1{\def\Template{#1}}
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%The grouping keeps any changes to the definition of |\MakeTemplate|
+%local to this merge.
+%Thus several consecutive merges can be handled
+%within one document.
+%The |\endgroup| is supplied by the macro |\Iterate|
+%when the merge file has been exhausted.
+%
+%    \begin{macro}{\Iteratecounter}
+%    \begin{macro}{\Iterate}
+%|\Iterate| must read the fields which were declared before it was entered,
+%substitute them into its template and repeat itself using tail recursion
+%if the end of the merge file has not been encountered.
+%    \begin{macrocode}
+\countdef\Iteratecounter=2
+\Iteratecounter=0
+\def\Iterate{%
+   \global\advance\Iteratecounter by1
+   \ReadFields\GlobalFields
+   \Template
+   \SeeIfEof
+   \ifeof\MergeFile
+      \def\NextIteration{%
+         \endgroup\closein\MergeFile}%
+   \else
+      \let\NextIteration\Iterate
+   \fi
+   \NextIteration}
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%The point of the use of counter 2 in the above is that it is accessible to
+%the print driver for page selection.
+%Anyone who has started printing 150 letters, all with page number~1,
+%only to run out of paper half way, will appreciate the use of this artifice!
+%
+%\section{Implementation of merged tables}
+%
+%    \begin{macro}{\MultiCount}
+%    \begin{macro}{\MaxCount}
+%    \begin{macro}{\ifStartOfList}
+%We set up two counters, one for the column we are reading and the
+%other for the total number of columns in the table.
+%We also need a conditional to mark the start of the table, so that
+%we terminate each row correctly with |\\| or |\cr|, or nothing at all
+%at the beginning of the first row.
+%    \begin{macrocode}
+\newcount\MultiCount \newcount\MaxCount
+\newif\ifStartOfList
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%    \end{macro}
+%
+%    \begin{macro}{\MultiRead}
+%The parameter to |\MultiRead| is the number of columns to read at a
+%time. This command passes control to |\NextRead| after initializing
+%certain parameters.
+%    \begin{macrocode}
+\def\MultiRead#1{%
+   \ifnum#1>0
+      \SelectCR
+      \MakeEmpty{#1}%
+      \global\StartOfListtrue
+      \glet\NextRead\MRead
+      \AllowBlank
+      \global\MaxCount=#1
+      \NextRead
+   \fi}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\Emptyctr}
+%    \begin{macro}{\MakeEmpty}
+%The command |\MakeEmpty| is required by the pre-pro\-cess\-ing
+%of each field.
+%The idea is that the command |\csname pr|$nn$|\endcsname|,
+%which we will loosely call |\pr|$nn$,
+%is executed on each field in column $nn$. However, most of these commands
+%will be undefined, and so we equate each of those that has not been
+%defined to |\empty|.
+%    \begin{macrocode}
+\newcount\Emptyctr
+\def\MakeEmpty#1{\Emptyctr=0
+   \loop
+      \advance\Emptyctr by1
+      \expandafter\ifx\csname
+         pr\the\Emptyctr\endcsname\relax
+         \expandafter\glet\csname
+            pr\the\Emptyctr\endcsname\empty
+      \fi
+      \ifnum\Emptyctr<#1
+   \repeat}
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%Note that, because of the way we are accessing it via |\csname|,
+%the first time |\pr|$nn$ is encountered it equates to |\relax|.
+%
+%    \begin{macro}{\Process}
+%The command |\Process#1#2| defines |\pr#1| to mean |#2|.
+%    \begin{macrocode}
+\def\Process#1#2{%
+   \expandafter\def\csname
+      pr#1\endcsname##1{#2{##1}}}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\MarkEnd}
+%We need to know how the last row is to be recognized. The default is an
+%empty line in the merge file.
+%    \begin{macrocode}
+\def\MarkEnd#1{\gdef\EndMarker{#1}}
+\MarkEnd{}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\NextLine}
+%    \begin{macro}{\NextField}
+%We collect each row in a token register. The full row is assembled
+%in |\NextLine| before being passed back to \TeX. Each field is
+%read in |\TempField| and then placed temporarily into
+%|\NextField|.
+%    \begin{macrocode}
+\newtoks\NextLine \newtoks\NextField
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%It is not necessary to do things this way; |\edef| can be used
+%instead, but that approach might expand tokens prematurely.
+%
+%    \begin{macro}{\AppendNextField}
+%After the next field has been read, it is appended to |\NextLine|.
+%    \begin{macrocode}
+\def\AppendNextField{%
+   \global\advance\MultiCount1
+   \NextField=\expandafter{\TempField}%
+   \edef\Append{\NextLine=
+      {\the\NextLine&\csname
+         pr\the\MultiCount\endcsname
+         {\the\NextField}}}%
+   \Append}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\EndLine}
+%    \begin{macro}{\FinishLine}
+%We need to insert the correct end marker after each row of the table.
+%The token |\cr| must be disguised a little before it is acceptable
+%in a \LaTeX\ document.
+%    \begin{macrocode}
+\def\SelectCR{\glet\EndLine\\}%
+%</textmerg>
+%<plain>\def\SelectCR{\gdef\EndLine{\cr}}%
+%<*textmerg>
+\def\FinishLine{%
+   \ifStartOfList
+      \global\StartOfListfalse
+   \else\EndLine\fi}
+%    \end{macrocode}
+%    \end{macro}
+%    \end{macro}
+%This makes the assumption that if |\array| is defined then we must be
+%in \LaTeX.
+%
+%    \begin{macro}{\StopProcessing}
+%We need a command to finish off a table. This should reset |\NextRead|
+%to |\AllowBlank| to terminate the tail recursion,
+%and also do some
+%error recovery in case the file ends prematurely in the middle of a row.
+%    \begin{macrocode}
+\def\StopProcessing{%
+   \global\MultiCount\MaxCount
+   \glet\NextRead\AllowBlank}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\MRead}
+%The command |\MRead| prepares to read a row of a table. It reads a
+%field from the merge file and checks to see whether the table has been
+%exhausted.
+%    \begin{macrocode}
+\def\MRead{%
+   \global\MultiCount=1
+   \ReadIn\TempField
+   \ifx\TempField\EndMarker
+      \StopProcessing
+   \else
+      \FinishLine
+      \NextField=\expandafter{\TempField}%
+      \edef\StartLine{\NextLine={\csname
+         pr1\endcsname{\the\NextField}}}%
+      \StartLine
+      \ConstructNextRow
+   \fi
+   \NextRead}
+%    \end{macrocode}
+%    \end{macro}
+%
+%    \begin{macro}{\ConstructNextRow}
+%Command |\ConstructNextRow| does most of the work of assembling a row of
+%the table.
+%It assembles |\MaxCount| fields
+%at a time into |\NextLine| unless an error is encountered.
+%    \begin{macrocode}
+\def\ConstructNextRow{%
+   \ifnum\MultiCount<\MaxCount
+      \loop
+         \ReadIn\TempField
+         \ifx\TempField\EndMarker
+            \glet\TempField\empty
+            \StopProcessing
+            \MissingField
+         \else
+            \ifeof\MergeFile
+               \glet\TempField\empty
+               \StopProcessing
+               \MissingField
+            \fi
+         \fi
+         \AppendNextField
+         \ifnum\MultiCount<\MaxCount
+      \repeat
+    \fi
+   \the\NextLine}
+%</textmerg>
+%    \end{macrocode}
+%    \end{macro}
+%
+%
+%    \section{The documentation driver file}
+%
+%    This is the driver file that produces this documentation.
+%    We use the document class provided by the \LaTeXe\ distribution
+%    for producing the documentation.
+%    \begin{macrocode}
+%<*driver>
+\documentclass{ltxdoc}
+\RecordChanges
+\begin{document}
+  \DocInput{textmerg.dtx}
+  \PrintIndex
+  \PrintChanges
+\end{document}
+%</driver>
+%    \end{macrocode}
+%
+%
+%
+%\Finale
+%
+%\endinput
-- 
cgit v1.2.3

