summaryrefslogtreecommitdiff
path: root/macros/latex209/contrib/address/Paper.tex
blob: 7cd1a9e417e19fc3b2f3875e87e764f189d040a1 (plain)
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
%%% ============================================================
%%%  @LaTeX-style-file{
%%%    author            = "Jackie Damrau",
%%%    version           = "1.0",
%%%    date              = "July 1991",
%%%    time              = "NULL",
%%%    filename          = "3across.tex",
%%%    address           = "SSC Laboratory, MS-1011
%%%                         2550 Beckleymeade Avenue
%%%                         Dallas, TX  75237-3946",
%%%    telephone         = "(214) 708-6048",
%%%    FAX               = "(214) 708-5143",
%%%    checksum          = "NA",
%%%    email             = "damrau@sscvx1.ssc.gov (Internet)
%%%                         damrau@sscvx1 (Bitnet)",
%%%    codetable         = "ISO/ASCII",
%%%
%%%    keywords          = "LaTeX, TeX, formletter, mailing labels",
%%%    supported         = "yes",
%%%
%%%    docstring         = "Conference paper (Paper.tex) explaining
%%%                         how to use the program.",
%%%  }
%%% =================================================================
\documentstyle{ltugproc}
\newcommand{\ouradd}{{\sf address}}
%
%corrections inserted 1 May 1991

\def\fileversion{v1.03}
\def\filedate{11 Mar 91}

%\preprinttrue % Comment this line out for final version following meeting

% \let\Now=\null % Uncovering this will remove time stamps on preprints
%
%======================================================================
\begin{document}
\title{Form Letters with 3-Across Labels Capability}
\shortTitle{Form Letters with 3-Across Labels}
\shortAuthor{Jackie Damrau and Michael Wester}
%
\author{Jackie Damrau}
\address{Superconducting Super Collider Laboratory \\ Dallas, Texas,
75237 USA \\ 214-708-6048; FAX:  214-708-5143}
\netaddress[\network{Internet}]{damrau@sscvx1.ssc.gov}
%
\author{Michael Wester}
\address{Department of Mathematics and Statistics \\
University of New Mexico \\ Albuquerque, New Mexico, 87131 USA \\
505-277-4613}
\netaddress[\network{Internet}]{wester@spectre.unm.edu}

\begin{abstract}
This article discusses a general-purpose program for generating form letters,
using either \TeX\ or \LaTeX.  Given three inputs: a preamble
file for initializations, a list of blank separated addresses, and a letter
template, this program can be used to generate a letter per address and
provide personalizations as directed by the template.  Sample applications
are presented, including one which constructs 3-across mailing labels.  Thus,
both form letters and mailing labels can be generated from the same list of
addresses by simply changing two inputs to the program.
\end{abstract}

\maketitle

\section{Introduction}

With \TeX\ or \LaTeX, it is not hard to produce a letter to be sent to a
single addressee.  Nor is it difficult to create multiple letters that
follow a similar format by setting up a form in which changeable
parameters, such as the name and address, are specified by macros.
The form can then be input a fixed number of times, each time preceded
by a redefinition of the parameters. However, there are problems with
this approach. Modifying the list of addresses or adding new parameters
to the form can be cumbersome. Also, serious reformatting may be
required to use the individual pieces of information (such as the names
and addresses) in other contexts.

An easy-to-use, general-purpose program to generate form letters has
been developed that overcomes the above problems.  This program,
\ouradd, is written using \TeX\ constructs and macros and can be
executed by \TeX{}ing or \LaTeX{}ing it.

The \ouradd\ program requires three user-supplied files: a preamble for
performing initializations (which is optional), a list of addresses
separated by blank lines, and a template.  On execution, \ouradd\
asks for three file names, and then reads in the addresses one by
one. For each address, the individual components are assigned to various
macros, after which the template file is \verb+\input+.  The template can,
therefore, refer to these macros.

The address list need not contain any formatting instructions as
individual lines of text within a given address are retained by \ouradd.
 This allows the address file to be pure text and usable by any other
program.  Nor is it required that an address be simply that; any other
data, such as telephone numbers, test scores, or whatever, may be
included.  Macros are provided to extract both individual lines and
individual blocks of data.

In the following sections, instructions on how to set
up the necessary files and details on running the program are furnished.
In addition, a template for producing 3-across labels is provided which
demonstrates a simple, but useful application.  Finally, some discussion
of the construction of the macros in \ouradd\ is given, explaining some
of the difficulties encountered and how they were overcome.

\section{Setting Up the Files}

The easiest file to set up is the address list.  It consists of blocks
of text separated by blank lines.  Commonly, the first line of a block
will be the name of an addressee, while the rest of the lines form the
address.  The \ouradd\ program therefore assigns these segments of text
to the macros \verb+\Name+ and \verb+\Address+, respectively.

Unlike normal \TeX\ input, individual lines of text within an address
(which can be of arbitrary length) retain their identity.  This is
accomplished by concatenating the lines, using \verb+\\+ as a
separator.  For \LaTeX, this is quite convenient since a reference to
\verb+\Address+ will result in the expansion of each \verb+\\+ as a new
line.  In \TeX, a similar effect can be obtained by
\begin{quote}
\begin{verbatim}
\def\\{\hfil\break}
\end{verbatim}
\end{quote}

In the template file, individual lines within \verb+\Address+ can be
selected by \verb+\AddrLine{+$n$\verb+}+, where $n$ is a positive
integer.  In addition, \verb+\Laddr+ will count the number of lines in
\verb+\Address+ and \verb+\Naddr+ will refer to the current position in
the address list.

It is often desirable to include other information along with the
address.  The easiest way to do this with \ouradd\ is to divide the
lines of text in the address segment into subblocks, each of which can
be of variable length.  The macro call, \verb+\AddrBlock{+$k$\verb+}+,
is provided to select the $k^{\rm th}$ subblock, where a line consisting
of \verb+---+ acts as a separator between subblocks.  (Two consecutive
lines of \verb+---+ will not produce an empty subblock, but this effect
can be achieved by inserting a line consisting of \verb+{}+ between the
lines.)

To extract individual lines from a subblock of \verb+\Address+, a
two-step process is required.
\verb+\StoreAddrBlock{+$k$\verb+}\in\Block+ will define the contents of
the macro \verb+\Block+ to be the $k^{\rm th}$ subblock of
\verb+\Address+.  \verb+\GetLine{+$n$\verb+}\of\Block+ will then select
the $n^{\rm th}$ line of the \verb+\Block+.  This procedure is necessary
to circumvent some peculiarities of \TeX\ macro expansion.

One of the more salient features of \ouradd\ is the ability to
intelligently parse the \verb+\Name+ and break it up into its
components.  For example, suppose the name is {\sf The Honorable and
Mrs.\ Henry \verb+\+\& Matilda Edward Bo van Frothingham III, Royals}.
The following macro assignments will then be made when this name is
parsed:
\begin{center}
\begin{tabular}{l@{$\; \rightarrow\; $}l}
	\verb+\SocialTitle+ & {\sf The Honorable and Mrs.} \\
	\verb+\FirstName+   & {\sf Henry \verb+\+\& Matilda} \\
	\verb+\MiddleName+  & {\sf Edward Bo} \\
	\verb+\LastName+    & {\sf van Frothingham} \\
	\verb+\Suffix+      & {\sf III} \\
	\verb+\OtherTitle+  & {\sf Royals}
\end{tabular}
\end{center}
Simpler names will result in some of the above macros having null
definitions.

The macros associated with the \ouradd\ program are summarized in the
following table.
\vbox{
\begin{flushleft}
%\begin{tabular}{|l|p{1.15in}|}
 \begin{tabular}{|l|p{1.15in}|}
\hline
\verb+ + & \\[-8pt]
\verb+\DEFAULTtolist+	& default address list (initially, {\tt tolist})\\
\verb+\DEFAULTletter+	& default letter template (initially, {\tt letter})\\[1.5p
t]
\hline
\verb+ + & \\[-8pt]
\verb+\Name+		& first line of the address \\
\verb+\Address+		& subsequent lines of the address \\
\verb+\SocialTitle+	& e.g., Dr., Mr., Ms. \\
\verb+\FirstName+	& first name \\
\verb+\MiddleName+	& middle names \\
\verb+\LastName+	& last name \\
\verb+\Suffix+		& e.g., Sr., Jr., III \\
\verb+\OtherTitle+	& academic and professional titles \\[1.5pt]
\hline
\verb+ + & \\[-8pt]
\verb+\Naddr+		& position of the address in the {\tt tolist} \\
\verb+\Laddr+		& number of lines in \verb+\Address+ \\
\verb+\AddrLine{+$n$\verb+}+	& $n^{\rm th}$ line of \verb+\Address+ \\
\verb+\AddrBlock{+$n$\verb+}+	& $n^{\rm th}$ subblock of \verb+\Address+ \\
\verb+\StoreAddrBlock{+$n$\verb+}\in\B+	& store the $n^{\rm th}$ subblock of
	\verb+\Address+ in \verb+\B+ \\
\verb+\GetLine{+$n$\verb+}\of\B+	& $n^{\rm th}$ line of \verb+\B+ \\[1.5pt]
\hline
\verb+ + & \\[-8pt]
\verb+\addspace\A+	& adds a space after \verb+\A+ if it is not null \\
\verb+\topbox{+$H$\verb+}{+$W$\verb+}{text}+	& top aligned box of height $H$
	and width $W$ \\[1.5pt]
\hline
\end{tabular}
\end{flushleft}
%\end{center}
%\vskip .1in
\vskip 4pt
An example of an address list appears below.  Notice that following the
address in each instance is a separate block of two lines.
\begin{quote}
\begin{verbatim}
Mrs. Apple Thesaurus
Apt. Z
234 Gestalt Lane
Cockermouth, Umbria, U.K.
---
artichokes
jalape\~nos

Harry K. Banana
P.O. Box 29Z46
Kahului, Maui, Hawaii
---
mustard greens
okra
\end{verbatim}
\end{quote}
}
A typical (\LaTeX) letter template that might be used with the above list of
addresses looks like:
\begin{quote}
\begin{verbatim}
\Name\\
\AddrBlock{1}

\StoreAddrBlock{2}\in\veggies
Dear \addspace\SocialTitle\LastName:

Welcome to the vegetable of the month
club!  Your introductory offer of
two selections this first month are
\GetLine{1}\of\veggies\ and
\GetLine{2}\of\veggies.  ...
\newpage
\end{verbatim}
\end{quote}
The macro \verb+\addspace+ is used to produce correct spacing in the
salutation by adding a proper space after \verb+\SocialTitle+ if it
contains text and doing nothing if \verb+\SocialTitle+ is empty (as
would be the case for the second addressee).

The last file needed by \ouradd\ is the preamble.  This file is
\verb+\input+ once and is used to perform initializations, such as
setting margins and defining macros.  If \ouradd\ is being \LaTeX{}ed,
the preamble is input before the \verb+\begin{document}+ that is
executed automatically before processing the addresses.  A sample
preamble that can be used under \TeX\ or \LaTeX\ is given below. (The
definition for \verb+\ifundefined+ can be found in Knuth
[page~40] and is present in \ouradd.)
\begin{quote}
\begin{verbatim}
%
% Generic TeX/LaTeX preamble for
%    address.tex .
%
\ifundefined{LaTeX}             % TeX
   \magnification=\magstep1
   \voffset=0in
   \hoffset=0in
   \vsize=9in
   \hsize=6.5in
   \nopagenumbers
   %
   \def\\{\hfil\break}
   \def\newpage{\vfil\eject}
\else                           % LaTeX
   \documentstyle[12pt]{letter}
   \topmargin 0in
   \headheight 0in
   \headsep 0in
   \oddsidemargin 0in
   \textheight 9in
   \textwidth 6.5in
   \pagestyle{empty}
\fi
\end{verbatim}
\end{quote}

\section{Running the Program}

The \ouradd\ program is executed simply by typing {\em tex address} or
{\em latex address}.  This action produces the following set of requests:
\begin{quote}
\begin{verbatim}
Enter the filename of the preamble
   [preamble.tex]:
Enter filename of recipients' addresses
   [tolist.tex]:
Enter the filename of the letter
   template [letter.tex]:
\end{verbatim}
\end{quote}

The filenames in square brackets (\verb+[ ]+)
are default values and are
accepted by pressing a \fbox{RETURN}\,.  (The default names for the
second and third files can be changed by redefining the macros
\verb+\DEFAULTtolist+ and \verb+\DEFAULTletter+ in the preamble.)  Of
course, the various files should contain commands appropriate to the
package actually being used.

\ouradd\ is designed to be reasonably robust.  This and
\TeX's rules for reading input allows some sloppiness in setting up the
address list.  For example, leading and trailing white space and extra
blank lines are all ignored.  Also, a \verb+%+ can be used to
comment-out text. This last item implies that any line with a \verb+%+ as its
first nonblank character will be treated as a blank line.

\section{Making 3-Across Mailing Labels}

By taking advantage of the macros defined in \hbox{\ouradd,} it is not
difficult to design a template that can produce 3-across labels.  The
following template will create a three-column, 33 labels-per-page format
for a standard sheet of 2.75''$\times$1'' labels.  The resulting
output can be sent directly to sheets of labels or onto regular
paper, which can then be photocopied onto label sheets.

\begin{small}
\begin{verbatim}
\ifcase\the\Naddr
  \or\topbox{1in}{2.75in}{\Name\\\AddrBlock1}%
  \or\topbox{1in}{2.75in}{\Name\\\AddrBlock1}%
  \or\topbox{1in}{2.75in}{\Name\\\AddrBlock1}\\
     \Naddr=0
\fi
\end{verbatim}
\end{small}

{
The methodology used here is to produce differing output depending on
the value of \verb+\Naddr+.  The \verb+\ifcase+ construct will result in
three horizontally aligned boxes, each containing the current contents
of \verb+\Name+ and the first subblock of \verb+\Address+, as
\verb+\Naddr+ takes on the values 1, 2 and 3.  At the end of the third
case, a new line is started and \verb+\Naddr+ is reset to 0.  Thus, the
next time around, \ouradd\ will have incremented \verb+\Naddr+ back to 1
and the process will start over.  The macro
\verb+\topbox{+$H$\verb+}{+$W$\verb+}{text}+, defined in \ouradd\
by\parfillskip=0pt\par }

\begin{quote}
\begin{verbatim}
\def\topbox#1#2#3{\leavevmode
  \vtop to #1{\hsize=#2 #3\vfil\eject}}
\end{verbatim}
\end{quote}
will produce a top-aligned box containing the \verb+text+ of height $H$
and width $W.$

The above strategy is easily modified to handle any number of columns
and any spacing requirements for a regular gridlike pattern of labels.
Depending on the printer settings, the top and left margins established
in the preamble (not shown) may need to be changed as well.  Using
12-point fonts, it is possible to put 6 lines of text in a one-inch-high
label.  This can be increased by decreasing the fontsize set in the
preamble.

\subsection{Comments on other labeling schemes.}

A label-making capability is already available in \LaTeX, as well
as in other programs; but these do not possess the flexibility
nor the ease of use exhibited by \ouradd.
According to Lamport [page~67], the \verb+\makelabels+ command
prints a ``list of mailing labels, one for each {\tt letter} environment, in
a format suitable for xerographic copying onto `peel-off' labels.''
However, the two-column format produced does not correspond nicely to
3-across and other common mailing label arrangements nor can it be changed
easily.

In printing 3-across mailing labels in Microsoft Word, it is necessary
to type three sets of field names, a NEXT instruction telling Microsoft
Word to place information from more than one record onto a single copy
of a form document, and various other commands and formatting statements.
Typically, in programs of this type, a number of steps will be required;
and again, the choice of output formats will be quite limited.  Also, the
data typically cannot be a simple ASCII file but must be converted into
the program's possibly multifield internal format.

\section{Comments on the Code}

In developing \ouradd, certain difficulties had to be overcome.  The
solutions found may be of benefit to other users.  One problem
encountered was creating a box of text that had a definite height, as
well as a definite width.  The \verb+\topbox+ macro mentioned above has
these features.  It is adapted from the definition of \LaTeX's
\verb+\parbox+ command.  With respect to \TeX's viewpoint, the $H$ in
the definition of \verb+\topbox+ is really a depth with the height of
the box being zero, but these details can normally be ignored.

A second obstacle was obtaining sequential space delimited strings
(e.g., words) from a line of text in a robust manner.  Macros to do this
were needed to build the name-parsing macro (\verb+\breakup+).  For
example, suppose \verb+\List+ is defined by \verb+\def\List{ a1 b2 c3 }+.
The first `word' of \verb+\List+ is \verb+a1+, the second is
\verb+b2+, and the third is \verb+c3+. One way to select elements in
this fashion is to construct macros, \verb+\wcar+ and \verb+\wcdr+, that
are analogous to the Lisp functions, CAR and CDR. \verb+\wcar\List\nil+
should select \verb+a1+ and \verb+\wcdr\List\nil+ should return
\verb+{b2 c3 }+.  Moreover, \verb+\wcar+ and \verb+\wcdr+ of \verb+{ }+
and \verb+{}+ should be null, and any sequence of multiple spaces should
be treated like a single space.

If \verb+\List+ is a simple list of tokens (for example, \verb+{ a b c }+),
then a token CAR and CDR can be defined as follows:
\begin{quote}
\begin{small}
\begin{verbatim}
%
% Test for {}.
%
\def\ifnull#1{\ifx#1\empty}
%
% \tcar\List\nil picks off the first non-
%    blank token (which is typically a
%    character or a control sequence) in
%    the \List.  If the \List is blank or
%    empty, then a null string is returned.
%
\def\tcar#1\nil{\ifnull#1
                   \empty
                \else
                   \tCar#1\nil
                \fi}
\def\tCar#1#2\nil{#1}
%
% \tcdr\List\nil removes the first nonblank
%    token in the \List and any preceding
%    blanks.  If the \List is blank or
%    empty, then a null string is returned.
%
\def\tcdr#1\nil{\ifnull#1
                   \empty
                \else
                   \tCdr#1\nil
                \fi}
\def\tCdr#1#2\nil{#2}
\end{verbatim}
\end{small}
\end{quote}
The general case is trickier and requires auxiliary macros.
\begin{quote}
\begin{small}
\begin{verbatim}
%
% \ABDReverseExpand{D}{C}{B}{A}
%    first expands A, then expands B, then
%    expands D.
%
\def\ABDReverseExpand#1#2#3#4{%
   \expandafter\expandafter
      \expandafter#1%
         \expandafter\expandafter
            \expandafter#2\expandafter#3#4}
%
% Used to remove leading spaces.
%
\def\pretrim.#1{#1}
%
% \wcar\List\nil picks off the first word
%    (string of nonblank characters) in the
%    \List.  If the \List is blank or
%    empty, then a null string is returned.
%
\def\wcar#1\nil{%
   \ifnull#1
      \empty
   \else
      \expandafter\wCar\pretrim.#1 \nil
   \fi}
\def\wCar#1 #2\nil{#1}
%
% \wcdr\List\nil removes the first word and
%    any preceding blanks from the \List.
%    If the \List is blank or empty, then a
%    null string is returned.
%
\def\wcdr#1\nil{%
   \ifnull#1
      \empty
   \else
      \ABDReverseExpand
            \ifx\empty\wCdr\pretrim.#1 \nil
         \empty
      \else
         \expandafter\wCdr\pretrim.#1\nil
      \fi
   \fi}
\def\wCdr#1 #2\nil{#2}
\end{verbatim}
\end{small}
\end{quote}
\verb+\ABDReverseExpand+ is a simplification of the example found in
Knuth [page~374] in the ``Dirty Tricks'' appendix.\footnote{The comment
there incorrectly predicts that such a construction is ``probably too
lengthy to be of any use.''}

One more pair of useful Lisplike macros are \verb+\setq+ and
\verb+\gsetq+, which are defined by
\begin{quote}
\begin{verbatim}
\def\setq#1#2{\edef#1{\expandafter#2}}
\def\gsetq#1#2{\xdef#1{\expandafter#2}}
\end{verbatim}
\end{quote}
These macros allow statements such as
\begin{quote}
\begin{verbatim}
\setq\List{\wcdr\List\nil}
\end{verbatim}
\end{quote}
to function correctly by performing an immediate expansion on the second
argument.  This particular example results in \verb+\List+ being
redefined to be \verb+{b2 c3 }+.

Using the preceding as building blocks, it is easy to devise more complex
macros. \ouradd\ defines
\verb+\wmember\Element\of\List\nil+, which causes \verb+\ifwmember+ to be
true if the \verb+\Element+ is found in the \verb+\List+ (false
otherwise); and \verb+\wendcarcdr\List\nil\A\B+, which assigns \verb+\A+
and \verb+\B+ to the CAR and CDR of the \verb+\List+, starting at the
{\em right}.  The assignment to macros provided as arguments in the
latter case is done for two reasons.  It is more efficient in this
situation to make both assignments at once.  More importantly, since
\verb+\wendcarcdr+
uses recursion via the \verb+\loop+ construct, as well as defining
temporary variables, \TeX\ will complain if an attempt to
force an immediate expansion of the result is made with \verb+\edef+.
Thus, \verb+\wendcarcdr+ uses \verb+\xdef+ internally to define
\verb+\A+ and \verb+\B+.

The problem of being unable to store and further manipulate the results
of certain macro expansions can be solved in a second way.  The
\verb+\StoreAddrBlock+ macro mentioned earlier is defined by
\begin{quote}
\begin{verbatim}
\def\StoreAddrBlock#1\in#2{%
   {\setbox0=\hbox{\AddrBlock#1}%
    \toks0=\expandafter{\Current}%
    \xdef#2{\the\toks0}}}
\end{verbatim}
\end{quote}
In the first line, \verb+\AddrBlock+ completely expands within the
\verb+\hbox+ and the result is assigned to a box which is subsequently
ignored.  As a side effect of the expansion, the global macro
\verb+\Current+ is set to be the value of the reference to
\verb+\AddrBlock+.  The last two lines of the macro then store this
result in the second argument, operating with a token list to prevent
premature expansion of any \verb+\\+'s that may be present.  The extra
set of braces ensure that the assignments to \verb+\box0+ and
\verb+\toks0+ are local to the macro.

This section concludes with a small, but important point.  \TeX\ will
append an end-of-line character to any line of input text unless
\verb+\endlinechar=-1+ is performed.  This character will be treated
like a space unless the line is blank, in which case it will be
converted into a \verb+\par+.  Since \verb+\ifx+ performs one level of
macro expansion on its arguments, one way to read a line from a file and
test if it is blank is:
\begin{quote}
\begin{verbatim}
\read\file to \Line
\ifx\Line\blank
\end{verbatim}
\end{quote}
where \verb+\def\blank{\par}+ must be done somewhere previous.

\section{Summary}

We have designed a general-purpose form-letter generator that runs
directly under \TeX\ or \LaTeX.  This program requires three files,
supplied by the user: a (optional) preamble, a simple format address
list, and a letter template.  These files are prompted for interactively,
and they default to certain names if none are specified.  We have also
developed various sample files, including a preamble and template to
produce 3-across labels. Thus, form letters and mailing labels can both
be generated from the same address list by just changing two inputs to the
program.  Of course, there is nothing magical about names and addresses;
this program can certainly be adapted to other uses.

This form-letter program has been designed to be both robust and
easy to work with.
The former means, for example, that excess white space and
lines commented out with a \verb+%+ in the address list will not cause
havoc. To make the program easy to work with,
the files have been designed to be easily modified for various types
of results. Thus, the files themselves have been made READABLE so that
anyone who wishes to alter them may do so easily.  These files will be
made publicly available from the \TeX\ repositories at {\tt
sun.soe.clarkson.edu} and {\tt ymir.claremont.edu}.

\section{Acknowledgments}

Thanks are due to Ellen Golden and Sam Matthews for
providing certain crucial help during the development of this program.
Also, Tom Stickels is due thanks for the encouragement and sound
editing advice provided throughout the development of this paper.
Finally, hats off to the reading club for instigating this endeavor.

\section{Bibliography}

\bibentry Knuth, Donald~E. \TB. Reading, Mass.: \AW, 1984.

\bibentry Lamport, Leslie.  {\sl \LaTeX{}:  A Document Preparation
System.}  Reading, Mass.:  \AW, 1986.

\bibentry Microsoft Corporation.  {\sl Microsoft Word Processing Program
Version 3.0 for IBM Personal Computers and Compatibles.}  Redmond,
Wash.:  Microsoft Corporation, 1986.

\section{Appendix: Selected Macro Definitions}

\begin{small}
\begin{verbatim}
\newif\ifnotdone
\newif\ifwmember
% =============================================
%
% Allow \par's within \loop constructs.
%
\long\def\loop#1\repeat{\def\body{#1}\iterate}
% ---------------------------------------------
\def\AddrLine#1{\GetLine#1\of\Address}
%
\def\AddrBlock#1{%
   \GetBlock#1\of\Address\by{\\---\\}}
%
\def\GetLine#1\of#2{\GetBlock#1\of#2\by\\}
%
% \GetBlock{N}\of\List\by\Delim gets block N of
%    the \List.  The blocks in the \List are
%    assumed to be separated by \Delim's.
%    \Current will hold the last block
%    selected.
%
\def\Current{}
\def\GetBlock#1\of#2\by#3{%
   {\count0=#1
    \toks0=\expandafter{#2#3}%
    \edef\List{\the\toks0}%
    \def\lcar##1#3##2\nil{##1}%
    \def\lcdr##1#3##2\nil{##2}%
    \notdonetrue
    \loop
       \ifx\List\empty
          \notdonefalse
          \gdef\Current{}%
       \else
          \advance\count0 by -1
          \ifnum\count0=0
             \notdonefalse
             \toks0=\expandafter\expandafter
                       \expandafter{%
                          \expandafter
                             \lcar\List\nil}%
             \xdef\Current{\the\toks0}%
             \Current
          \fi
       \fi
       \ifnotdone
          \toks0=\expandafter\expandafter
                    \expandafter{%
                       \expandafter
                          \lcdr\List\nil}%
          \edef\List{\the\toks0}%
    \repeat}}
%
% \wendcarcdr\List\nil\A\B picks off the last
%    word in the \List and places it in \A.
%    The rest of the list (stripped of leading
%    blanks) is placed in \B.
%
\def\wendcarcdr#1\nil#2#3{%
   {\edef\List{#1}%
    \def\carList{}%
    \def\newList{}%
    %
    \notdonetrue
    \loop
       \ifnull\List
          \notdonefalse
          \xdef#2{\carList}%
          \xdef#3{\newList}%
       \else
          \ifx\List\space
             \notdonefalse
             \xdef#2{}%
             \xdef#3{}%
          \fi
       \fi
       \ifnotdone
          \ifx\newList\empty
             \edef\newList{\carList}%
          \else
             \edef\newList{%
                \newList\space\carList}%
          \fi
          \setq\carList{\wcar\List\nil}%
          \setq\List{\wcdr\List\nil}%
    \repeat}}
%
% \wmember\Element\of\List\nil causes
%    \ifwmember to be true if the \Element is a
%    member of the \List and false otherwise.
%
\def\wmember#1\of#2\nil{
   {\global\wmemberfalse
    \edef\Element{#1}%
    \edef\List{#2}%
    \setq\carList{\wcar\List\nil}%
    %
    \ifnull\Element
       \notdonefalse
    \else
       \notdonetrue
    \fi
    \loop
       \ifnull\carList
          \notdonefalse
       \fi
       \ifnotdone
          \ifx\Element\carList
             \notdonefalse
             \global\wmembertrue
          \else
             \setq\List{\wcdr\List\nil}%
             \setq\carList{\wcar\List\nil}%
          \fi
    \repeat}}
\end{verbatim}
\end{small}
\end{document}