mh@killer.UUCP (04/05/87)
[]
Speaking of mail merging, here's an older one.
#!/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".
#
# Wrapped by mh on Sat Apr 4 19:16:26 CST 1987
# Contents: letter list mmerge.c mmerge.doc
echo x - letter
sed 's/^XX//' > "letter" <<'@//E*O*F letter//'
XX3 August 1985
XX@1
XX@2
XX@3
XX@4
XX@5
XXDear @6,
XX The current offer is rejected, please resubmit in 90 days.
XXSincerely,
XXJoe Blow Industries
XXNew York
@//E*O*F letter//
chmod u=rw,g=r,o=r letter
echo x - list
sed 's/^XX//' > "list" <<'@//E*O*F list//'
XX.XXX
XXMr. Corncob Bueller
XXFinancial Wizard
XX301 N. Pork Chop
XXDallas, TX 10101
XXMr. Bueller
XX.XXX
XXMrs. G. Ricardo
XXPlaintiff
XX1441 E. 3rd St.
XXDallas, TX 01010
XXMrs. Ricardo
@//E*O*F list//
chmod u=rw,g=r,o=r list
echo x - mmerge.c
sed 's/^XX//' > "mmerge.c" <<'@//E*O*F mmerge.c//'
XX/*
XX mmerge.c
XX Matthew Rapaport, July 1985
XX Scaetrix Co, 222 Fifth St, Petaluma, CA, 94952
XX Compuserve 70371,255
XX This version works with C/80(tm) v3.0
XX and UniFLEX(tm) v2.0
XX This program merges a list of names to a letter
XX Sends impersonal mail to prospective customers
XX*/
XX#ifdef CPM
XX#include "a:stdio.h"
XX#include "a:printf.h"
XX#else
XX#include <stdio.h>
XX#endif
XX#define FALSE 0
XX#define TRUE ~FALSE
XX#define MAXLINE 40
XXstruct record {
XX char testln[MAXLINE];
XX char nameln[MAXLINE];
XX char titlln[MAXLINE];
XX char addrln[MAXLINE];
XX char cityln[MAXLINE];
XX char auxone[MAXLINE];
XX char auxtwo[MAXLINE];
XX} currec;
XXmain(argc,argv)
XXint argc;
XXchar *argv[];
XX{
XX#ifdef CPM
XX FILE list, letter;
XX#else
XX FILE *list, *letter;
XX#endif
XX char *fgets();
XX if (argc != 3) {
XX fprintf(stderr,"\nusage: mmerge listfile letterfile\n");
XX exit(0);
XX }
XX if ((list = fopen(argv[1],"r")) == 0) {
XX fprintf(stderr,"\nCan't open list file %s\n",argv[1]);
XX exit(0);
XX }
XX if ((letter = fopen(argv[2],"r")) == 0) {
XX fprintf(stderr,"\nCan't open letter file %s\n",argv[2]);
XX exit(0);
XX }
XX for(;;) {
XX if ((fgets(currec.testln,MAXLINE,list)) == 0)
XX break;
XX fgets(currec.nameln,MAXLINE,list);
XX fgets(currec.titlln,MAXLINE,list);
XX fgets(currec.addrln,MAXLINE,list);
XX fgets(currec.cityln,MAXLINE,list);
XX fgets(currec.auxone,MAXLINE,list);
XX fgets(currec.auxtwo,MAXLINE,list);
XX mergit(&currec,letter);
XX }
XX fclose(list);
XX fclose(letter);
XX}
XXmergit(ptr,letter)
XXstruct record *ptr;
XX#ifdef CPM
XXFILE letter;
XX#else
XXFILE *letter;
XX#endif
XX{
XX int i, letchar;
XX char d, flag, string[MAXLINE];
XX while ((letchar = getc(letter)) != EOF) {
XX if (letchar == '@') {
XX d = letchar;
XX letchar = getc(letter);
XX flag = FALSE;
XX switch (letchar) {
XX case '1':
XX strcpy(string,ptr->nameln);
XX break;
XX case '2':
XX strcpy(string,ptr->titlln);
XX break;
XX case '3':
XX strcpy(string,ptr->addrln);
XX break;
XX case '4':
XX strcpy(string,ptr->cityln);
XX break;
XX case '5':
XX strcpy(string,ptr->auxone);
XX break;
XX case '6':
XX strcpy(string,ptr->auxtwo);
XX break;
XX/* if the next char was not a number 1 - 6, print the '@' and what ever */
XX/* followed it on the standard output */
XX default:
XX flag = TRUE;
XX putchar(d);
XX putchar(letchar);
XX }
XX if (!flag)
XX for(i = 0; string[i] != '\n'; i++)
XX putchar(string[i]);
XX }
XX else /* no '@' so just put the char to stdout */
XX putchar(letchar);
XX }
XX putchar('\f'); /* form feed the printer */
XX#ifdef CPM
XX seek(letter,0,0); /* rewind letter file to beginning */
XX#else
XX rewind(letter);
XX#endif
XX}
XX#ifdef CPM
XXchar *
XXfgets(buf,size,fp) /* missing in c/80 library */
XXFILE fp;
XXint size;
XXchar *buf;
XX{
XX int c;
XX char *cs;
XX cs = buf;
XX while (--size > 0 && (c = getc(fp)) != EOF)
XX if ((*cs++ = c) == '\n')
XX break;
XX *cs = '\0';
XX return((c == EOF && cs == buf) ? NULL : buf);
XX}
XX#endif
@//E*O*F mmerge.c//
chmod u=rw,g=r,o=r mmerge.c
echo x - mmerge.doc
sed 's/^XX//' > "mmerge.doc" <<'@//E*O*F mmerge.doc//'
XXAugust 3, 1985
XXMailmerge anyone? Here is a short program that merges a list of
XXnames, titles, addresses, etc. with documents specially formatted
XXto receive the list. The program takes the data to be merged
XXfrom a list file consisting of individual lines seperated by
XXnewlines. There must be seven such lines in each record,
XXwith the first being a record separator line. I use .XXX as my
XXseparator line (I'm going to build a sorting function around
XXthis), but anything will do. The list thus has room for name,
XXtitle, address, city-state-zip, and two auxiliary lines that
XXmight hold some other information. The list file looks like this:
XXSEPARATOR LINE
XXname
XXtitle
XXaddress
XXcity, state zipcode
XXaux 1
XXaux 2
XXSEPARATOR LINE
XXname
XXetc...
XXNote that even if aux 1 and aux 2 are not used, there must at
XXleast be blank lines in their place. The document to be merged
XXcan be any kind of text. The function mergit() reads the
XXdocument character by character until it encounters an '@'
XXsymbol. It then saves that character and reads the next
XXcharacter. If this next character is a number in the range 1 -
XX6, the appropriate line from the list record will be substituted
XXfor the '@1' or '@2' etc. If the character immediately following
XXthe '@' is not a number in the expected range, the '@', and the
XXfollowing character are simply printed to the stdout. Thus
XXnormal use can be made of the '@' symbol in the document.
XXA typical letter might look like:
XXDate here
XX@1
XX@2
XX@3
XX@4
XX@5
XXdear @6
XXIf lines one thru five of the list record contain the usual name,
XXtitle, address, city-state-zip, aux 1 and the sixth line or aux 2
XXis the first name, then the program would substitute these values
XXappropriately in their respective places. The merged document is
XXsent (character by character) to the standard output.
XXThus the merged documents can be sent anywhere the user desires
XXby redirecting in the command line. A typical use would be:
XX(cpm) mmerge listfile letterfile >lst:
XX(unix) mmerge listfile letterfile | lpr
XXIf six lines are not enough for some needs, one can always add
XXmore descriptions to the structure 'record', and extend the
XXswitch-case in mergit() appropriately. Also remember to include
XXthe new structure elements in the forever loop in main().
XXHope you like it, if there are any questions, please drop me a
XXnote via CIS or my business address:
XXMatthew Rapaport
XXSCAETRIX Co.
XX222 Fifth St.
XXPetaluma, CA 94952
XX(707) 778-7758
XXCIS [70371,255]
@//E*O*F mmerge.doc//
chmod u=rw,g=r,o=r mmerge.doc
echo Inspecting for damage in transit...
temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
15 26 143 letter
14 29 168 list
161 361 2885 mmerge.c
75 427 2574 mmerge.doc
265 843 5770 total
!!!
wc letter list mmerge.c mmerge.doc | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if test -s $dtemp
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0