home *** CD-ROM | disk | FTP | other *** search
- From rs@mirror.TMC.COM Thu Apr 2 14:23:42 1987
- Path: seismo!rutgers!pyrnj!mirror!rs
- From: rs@mirror.TMC.COM (Rich Salz)
- Newsgroups: net.sources,comp.text
- Subject: Quicky "mail-merge" program
- Message-ID: <2763@mirror.TMC.COM>
- Date: 2 Apr 87 19:23:42 GMT
- Organization: Mirror Systems, Cambridge MA
- Lines: 373
-
- We needed to generate a whole bunch of form letters, and it was quicker
- and easier to throw together his general solution, than for me to write
- a general-purpose troff .rd macro-caller. Besides, sometimes we just
- quick something straight to the lineprinter.
-
- You should be able to specify the number of lines per field on the command
- line, I suppose...
- /r$
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # If this archive is complete, you will see the message:
- # "End of shell archive."
- # Contents: mmerge.1 mmerge.l Makefile Test.list Test.template
- # Wrapped by rs@mirror on Thu Apr 2 14:19:28 1987
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo shar: Extracting \"mmerge.1\" \(2456 characters\)
- if test -f mmerge.1 ; then
- echo shar: Will not over-write existing file \"mmerge.1\"
- else
- sed "s/^X//" >mmerge.1 <<'END_OF_mmerge.1'
- X.TH MMERGE 1 LOCAL
- X\" $Header:$
- X.SH NAME
- Xmmerge \- ``quick and dirty'' mail-merge program.
- X.SH SYNOPSIS
- X.B mmerge
- Xtemplate_file list_file
- X.SH DESCRIPTION
- X.I Mmerge
- Xis a short little program designed to help generate form letters and
- Xthe like.
- XIt should be given two arguments: the name of the template file, and
- Xthe name of the list file.
- XIf either name is a dash,
- X.BR \- ,
- Xstandard input is used.
- XOutput is sent to standard output, presumably to be piped into
- X.IR lpr (1)
- Xor
- X.IR ptroff (1).
- X.PP
- XThe template file is a normal text file, that contains special ``markers''
- Xindicating where you want the input from the address list to appear.
- XFor example:
- X.RS
- X.nf
- X\&^L
- X$$1$
- X$$3$, $$4$
- XApril 1, 1986
- X
- XDear $$1$:
- X
- XYou may already be a winner! That's right, $$2$, you could be
- Xthe first in the town of $$3$, $$4$, to win $1000.
- X .
- X.sp -.5
- X .
- X.sp -.5
- X .
- X Sincerely,
- X
- X Ed McMahon
- X.fi
- X.RE
- X(You would probably want to start or end the template with a formfeed if
- Xyou are sending your output to a lineprinter, hence the ``^L'' as the
- Xfirst line.)
- X.PP
- XWithin the template, there can be any number of markers of the form
- X.BI $$ digits $
- Xmeaning that the contents of field number
- X.I digits
- Xfrom the list file should be inserted at that point.
- X.PP
- XContinuing this example, here is what a sample list file might look
- Xlike:
- X.RS
- X.nf
- XLINES: 4
- X
- XRichard Salz
- XRich
- XCambridge
- XMassachusetts
- X
- XJohnny Carson
- XJoohhhny!
- XBurbank
- XCalifornia
- X
- X.fi
- X.RE
- XThe first line of the file contains the word
- X.I LINES
- Xin all capitals, followed by a colon and space, then the number of fields
- Xin each entry.
- XThe second line is blank.
- XThen, each record appears, separated by a blank line.
- X(Note that the file
- X.I ends
- Xwith a blank line, too.)
- X.PP
- XFinally, if the template file (shown first) is called
- X.IR temp ,
- Xand the list file (shown second) is called
- X.IR list ,
- Xthen typing:
- X.RS
- Xmmerge temp list | lpr
- X.RE
- Xwould send the following to the lineprinter:
- X.RS
- X.nf
- X.I "(new page)"
- XRichard Salz
- XCambridge, Massachusetts
- XApril 1, 1986
- X
- XDear Richard Salz:
- X
- XYou may already be a winner! That's right, Rich, you could be
- Xthe first in the town of Cambridge, Massachusetts, to win $1000.
- X .
- X.sp -.5
- X .
- X.sp -.5
- X .
- X Sincerely,
- X
- X Ed McMahon
- X.I "(new page)"
- XJohnny Carson
- XBurbank, California
- XApril 1, 1986
- X
- XDear Johnny Carson:
- X
- XYou may already be a winner! That's right, Joohhny!, you could be
- Xthe first in the town of Burbank, California, to win $1000.
- X .
- X.sp -.5
- X .
- X.sp -.5
- X .
- X Sincerely,
- X
- X Ed McMahon
- X.fi
- X.RE
- END_OF_mmerge.1
- if test 2456 -ne `wc -c <mmerge.1`; then
- echo shar: \"mmerge.1\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: Extracting \"mmerge.l\" \(2511 characters\)
- if test -f mmerge.l ; then
- echo shar: Will not over-write existing file \"mmerge.l\"
- else
- sed "s/^X//" >mmerge.l <<'END_OF_mmerge.l'
- X
- X%{
- X/*
- X** MMERGE
- X** A quick and dirty "mail merge" program.
- X**
- X** Sloppy programming: we let exit() close all open files for us.
- X*/
- X
- X#include <stdio.h>
- X
- X#ifndef lint
- Xstatic char RCS[] = "$Header: mmerge.c,v 1.1 87/04/02 10:35:34 rs REL $";
- X#endif /* lint */
- X
- X#define LINESIZE 99
- X#define MARK '$'
- X#define NIL (char *)NULL
- X
- Xstatic int Lines;
- Xstatic char LINES[] = "LINES: ";
- Xstatic char **Text;
- X
- Xextern int errno;
- Xextern int sys_nerr;
- Xextern char *sys_errlist[];
- Xextern char *calloc();
- Xextern char *index();
- X
- X
- Xstatic void
- XYelp(a, b)
- X char *a;
- X char *b;
- X{
- X int e;
- X
- X e = errno;
- X fprintf(stderr, "mmerge: ");
- X fprintf(stderr, a, b);
- X fprintf(stderr, " (errno = %d, %s).\n",
- X e, e < 0 || e > sys_nerr ? "oops" : sys_errlist[errno]);
- X exit(1);
- X}
- X
- X
- Xmain(ac, av)
- X int ac;
- X char *av[];
- X{
- X register FILE *Input;
- X register char *p;
- X register int i;
- X char buff[BUFSIZ];
- X
- X /* Check usage. */
- X if (ac != 3)
- X Yelp("Bad usage", NIL);
- X
- X /* Open files. */
- X if ((yyin = strcmp(av[1], "-") ? fopen(av[1], "r") : stdin) == NULL)
- X Yelp("Can't open %s as template file", av[1]);
- X if ((Input = strcmp(av[2], "-") ? fopen(av[2], "r") : stdin) == NULL)
- X Yelp("Can't open %s as input file", av[2]);
- X if (yyin == stdin && Input == stdin)
- X Yelp("Both files can't be from standard input", NIL);
- X
- X /* First line of Input should be "LINES: #"; second should be blank. */
- X if (fgets(buff, sizeof buff, Input) == NULL
- X || strncmp(buff, LINES, sizeof LINES - 1) != 0
- X || (Lines = atoi(buff + sizeof LINES - 1)) == 0
- X || fgets(buff, sizeof buff, Input) == NULL
- X || buff[0] != '\n')
- X Yelp("Input file has bad format!", NIL);
- X
- X /* Get space for each field. */
- X if ((Text = (char **)calloc((unsigned int)Lines+1, sizeof(char *))) == NULL)
- X Yelp("calloc failure #1", NIL);
- X for (i = Lines + 1; --i >= 0; )
- X if ((Text[i] = (char *)calloc(LINESIZE, 1)) == NULL)
- X Yelp("calloc failure #2", NIL);
- X
- X while (!feof(Input)) {
- X /* Read a field array from the list file. */
- X for (i = 0; i <= Lines; i++) {
- X if (fgets(Text[i], LINESIZE, Input) == NULL) {
- X if (i)
- X Yelp("Premature end of input?", NIL);
- X exit(0);
- X }
- X if (p = index(Text[i], '\n'))
- X *p = '\0';
- X }
- X
- X /* Read the template file, doing fill-ins as directed. */
- X (void)rewind(yyin);
- X yylex();
- X }
- X
- X exit(0);
- X}
- X%}
- X
- X%%
- X
- X\$\$[0-9]+\$ {
- X int i;
- X
- X i = atoi(&yytext[2]) - 1;
- X printf("%s", i >= 0 && i < Lines ? Text[i] : yytext);
- X }
- X. ECHO;
- X
- X%%
- END_OF_mmerge.l
- if test 2511 -ne `wc -c <mmerge.l`; then
- echo shar: \"mmerge.l\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: Extracting \"Makefile\" \(366 characters\)
- if test -f Makefile ; then
- echo shar: Will not over-write existing file \"Makefile\"
- else
- sed "s/^X//" >Makefile <<'END_OF_Makefile'
- X##
- X## MMERGE MAKEFILE
- X##
- X
- X## Edit appropriately.
- XCFLAGS = -O
- XDESTPROG= /usr/local/bin/mmerge
- XDESTMAN = /usr/man/man1/mmerge.1
- X
- Xall: mmerge lint
- X
- Xinstall: all
- X cp mmerge $(DESTPROG)
- X cp mmerge.1 $(DESTMAN)
- X
- Xmmerge: mmerge.c
- X $(CC) $(CFLAGS) -o mmerge mmerge.c -ll
- X
- Xlint: mmerge
- X lint -hba mmerge.c >lint
- X
- Xclean:
- X rm -f mmerge a.out foo core tags lint mmerge.[oc]
- END_OF_Makefile
- if test 366 -ne `wc -c <Makefile`; then
- echo shar: \"Makefile\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: Extracting \"Test.list\" \(97 characters\)
- if test -f Test.list ; then
- echo shar: Will not over-write existing file \"Test.list\"
- else
- sed "s/^X//" >Test.list <<'END_OF_Test.list'
- XLINES: 4
- X
- XRichard Salz
- XRich
- XCambridge
- XMassachusetts
- X
- XJohnny Carson
- XJoohhhny!
- XBurbank
- XCalifornia
- X
- END_OF_Test.list
- if test 97 -ne `wc -c <Test.list`; then
- echo shar: \"Test.list\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: Extracting \"Test.template\" \(193 characters\)
- if test -f Test.template ; then
- echo shar: Will not over-write existing file \"Test.template\"
- else
- sed "s/^X//" >Test.template <<'END_OF_Test.template'
- X
- X$$1$
- X$$3$, $$4$
- XApril 1, 1986
- X
- XDear $$1$:
- X
- XYou may already be a winner! That's right, $$2$, you could be
- Xthe first in the town of $$3$, $$4$, to win $1000.
- X .
- X .
- X .
- X Sincerely,
- X
- X Ed McMahon
- END_OF_Test.template
- if test 193 -ne `wc -c <Test.template`; then
- echo shar: \"Test.template\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of shell archive.
- exit 0
- --
- --
- Rich $alz "Drug tests p**s me off"
- Mirror Systems, Cambridge Massachusetts rs@mirror.TMC.COM
- {adelie, mit-eddie, ihnp4, harvard!wjh12, cca, cbosgd, seismo}!mirror!rs
-
-
-