perlman@wanginst.UUCP (Gary Perlman) (11/08/85)
Enclosed is a label making program. It is really useful if you want to do mass mailings, or for making sheets of all the same label, like for products. There is a simpe program included to zipsort labels. It is designed to adapt to any format label copying sheet. I have found it best to get some photocopier labels sheets from an office supply store and then tailer a shell script to fit that label. Two local shell scripts, big_label and small_label are examples of this. The shell scripts make it pretty easy for secretarial staff to use the program, otherwise, you have to explain UNIX options. Here is a quick example. The defaults print 3 labels across a sheet, each with six lines, the first of which is blank. Everything is programmable. The options in the exampple change the label width and the number of copies of each label requested. label -w 25 -n 2 << 'EOF' John Doe:123 Maple Lane:Anytown, USA Jane Doe:1600 Penn. Ave.:Washington, DC EOF ------------output John Doe John Doe Jane Doe 123 Maple Lane 123 Maple Lane 1600 Penn. Ave. Anytown, USA Anytown, USA Washington, DC Jane Doe 1600 Penn. Ave. Washington, DC ------------end of output #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # label.1 # intro # zipsort.1 # makefile # label.c # number.c # filter.c # big_label # small_label # zipsort.c # This archive created: Thu Nov 7 18:38:24 1985 # By: Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'label.1'" '(2121 characters)' if test -f 'label.1' then echo shar: "will not over-write existing file 'label.1'" else sed 's/^ X//' << \SHAR_EOF > 'label.1' X.TH LABEL "1WI" "November 1985" "Wang Institute" "UNIX User's Manual" X.SH NAME Xlabel \- print label sheet X.SH USAGE X.I label X[-cU] [-d\ delim] [-h\ height] [-i\ indent] [-l\ count] [-n\ repeat] X.ti +.5i X[-s\ skip] [-w\ width] [-] [files] X.SH OPTIONS X.I label Xoptions adjust to different label page formats by Xcontrolling the number of labels across a page, Xthe label height and width, and so on.. X.de OP\" option-letter [optional value] X.TP X.B -\\$1 \\$2 X.. X.OP c XCenter text on each line in the label. XThis option resets the label indent to 0. X.OP d delim XThe label line field delimiter (default: `:' the colon) tells X.I label Xhow to separate fields in a line. XThis character should not appear in the fields you want to print. XSeveral field delimiters in a row (blank fields) are skipped. XIf you really want a blank line inside a label, use a space. X.OP h height XThe height of a label (default: 6 lines). X.OP i indent XThe number of spaces to indent before each label (default: 2). X.OP l labels XThe number of labels to fit across a page (default: 3). X.OP n number XThe number of times to repeat each label (default: 1). X.OP s skip XThe number of lines to skip at the top of each label (default: 1). X.OP U XPrint a usage summary and exit. X.OP w width XThe label width in spaces (default 33). X.SH DESCRIPTION X.PP X.I label Xprints a series of labels in a matrix on a page Xthat is then suitable to use as a copy master for a page of stick on labels. XIf the labels are read in order: 1 2 3 4 5 6, Xand printed three across a page, Xthen the output is arranged like: X.nf X 1 2 3 X 4 5 6 X.fi X.SS Input X.I label Xreads non-blank lines that contain a series of delimited fields. XThe delimiter is a single character that separates the fields. XEach field is used as one line in a label. XExample labels: X.ce 2 XGary Perlman:Wang Institute:Tyng Road:Tyngsboro, MA 01879 XCopyright (c) 1985:Wang Institute:All Rights Reserved X.SS Output X.I label Xreads label lines until it has enough to print a row of labels. X.SH EXAMPLE X.nf XPrint six-high labels, four across, for 12 pitch print (100 wide): X label -h 6 -l 4 -w 25 X.fi X.SH AUTHOR XGary Perlman SHAR_EOF if test 2121 -ne "`wc -c < 'label.1'`" then echo shar: "error transmitting 'label.1'" '(should have been 2121 characters)' fi fi echo shar: "extracting 'intro'" '(7110 characters)' if test -f 'intro' then echo shar: "will not over-write existing file 'intro'" else sed 's/^ X//' << \SHAR_EOF > 'intro' X Making Labels X Gary Perlman X XI am pleased to announce public release of my new label Xprogram. This program takes label-lines and lays them out Xfor transfer onto label master sheets. Although hard to Xbelieve, there is a lot of technical information behind Xprinting labels, and this document will help you. X X Definitions X XLabel Master Sheets: These are 8.5 X 11 inch sheets with Xself-adhesive labels. The sheets are designed for jam-free Xphotocopy transfer from printed sheets. There are many Xsizes of label master sheet layouts. Here at the Wang XInstitute, we have two: X X Across Sheet Top-to-Bottom X #labels #characters #labels #lines X small 3 33 11 6 X big 2 50 5 12 X XThe number of available characters assumes 12-pitch Xprinting, or 100 characters per line. This is how our XDiablo printer is set up. For small labels, there is a Xcharacter not accounted for (3 labels times 33 characters is X99, not 100 characters). This missing character is cleaned Xup in a shell script, small_label, that sets all the options Xneeded for small-label master sheets. For big labels, there Xare three lines at the top of the page, and three lines at Xthe bottom (5 labels times 12 lines is 60, not 66 lines). XThese extra lines are cleaned up in a shell script, Xbig_label, that sets all the options needed for big-label Xmaster sheets. X XLabel Layout: A label master sheet is a matrix of labels, Xwhile a set of label description lines comes in Xline-by-line. The goal of the label program is to arrange Xthe labels so that they fit on the labels on the master Xsheet. For labels numbered 1 to 9 to fit on a small-label Xmaster sheet, that means the labels should be arranged like Xthis: X 1 2 3 X 4 5 6 X 7 8 9 X XLabel-Lines: The input to the label program is a series of Xlines, each with one label per line. But because each label Xis several lines, a special character, the field delimiter, Xmust be used to separate different lines within a label, Xcalled fields. By default, this character is the colon (:), Xbut it can be changed to another character if a colon must Xappear in a label line. An example label-line is: X X G. Perlman:Wang Institute:Tyng Road:Tyngsboro, MA 01879 X XThere are four fields in this label. Two copies of this Xlabel, spanning this page width, would look like this: X X G. Perlman G. Perlman X Wang Institute Wang Institute X Tyng Road Tyng Road X Tyngsboro, MA 01879 Tyngsboro, MA 01879 X XNote that there is a blank line at the top of the labels, Xand that each label is indented two spaces. X X Aesthetics X XAlthough small labels have 6 lines and 33 characters, and Xbig labels have 12 lines and 50 characters, not all the Xlabel is usable. It is common practice to leave the first X(few) and last (few) lines of a label clear, and to indent Xthe text on labels at least one or two spaces. This looks Xbetter, and it makes the alignment of text on the labels Xless critical. The big_label and small_label shell scripts Xassume that upper and left margins are wanted on all labels. X X Pragmatics X XTo make some labels, here is what you do, step by step. X XFirst, you must type in your labels, one per line, in the Xformat described above. Let's assume your labels are in a XUNIX file called "mylabels". X XSecond, you must decide what sort of labels you want, big or Xsmall. For most address labels, the small labels are too Xsmall, so the big ones should be used. For labels like name Xtags, the small labels are okay. X XThird, you put your labels through the label program, or, Xmore likely, through one of the convenient shell scripts: Xsmall_label or big_label. Let's assume you will use the Xbig-label master sheets. The call to big_label (that is an Xunderscore between big and label) would look like this: X big_label mylabels X XBut that would just print the labels out on your screen, Xwhich is not very useful. So you can save the output from Xthe label program in a file, which we'll assume is called X"mysheet": X big_label mylabels > mysheet X XFourth, print the formatted label sheet on a printer, like Xthe Diablo printer. The printer should be set up so that Xprinting will start in the extreme upper left hand corner of Xthe page. The print command would look like this: X lpr -Pdiablo mysheet X XNote that the steps to make the labels and print them can be Xcombined using UNIX pipes. This also avoids creating the Xfile "mysheet" which serves no useful purpose. The combined Xcommand would be: X big_label mylabels | lpr -Pdiablo X XFifth, take the printed label sheet and transfer it onto a Xsheet of self-adhesive labels. These can be hand fed in a Xphotocopy machine, or stacked into the paper feed bin. The Xsheets are specially made to not jam up the copy machine. XBecause the Diablo printer often has alignment problems, the Xprinted sheet may have to be adjusted a bit to match up with Xthe self-adhesive label master sheet. X X Frills X XThe label program has several options, many of which are Xused in the shell scripts big_label and small_label. In Xthis section, I will discuss the options you may are most Xlikely to use. All these options can be used with the shell Xscripts, or with the label program directly. First, there Xis a -U option, that will give you a usage summary of the Xprogram (with the current options) so that: X small_label -U Xwill print: X label: format label sheet X -c center fields on each label line X -d C field delimiter character (:) X -h N height in lines of labels (6 lines) X -i N indent before each label (2 spaces) X -l N number of label across page (3) X -n N repeat each label N times (1 times) X -s N skip lines at label top (1 lines) X -U print this usage message X -w N label width (33 spaces) X XThe center option (-c) will center all the fields on each Xline of the printed labels. This is pretty on labels other Xthan address labels. The -n option tells label the number Xof times to print each label. By default, label prints one Xcopy, but sometimes more than one is wanted, such as when Xyou want to fill a sheet with one label to have a stock. XHere is an example using the -c and the -n options: X X small_label -c -n 33 copyright X Xwhere the file "copyright" contains one label: X X Copyright (c) 1985:Wang Institute:All Rights Reserved X XA two-column two copy version of this label to fit this page Xwould look like this: X label -l 2 -w 30 -c -n 2 X X Copyright (c) 1985 Copyright (c) 1985 X Wang Institute Wang Institute X All Rights Reserved All Rights Reserved SHAR_EOF if test 7110 -ne "`wc -c < 'intro'`" then echo shar: "error transmitting 'intro'" '(should have been 7110 characters)' fi fi echo shar: "extracting 'zipsort.1'" '(538 characters)' if test -f 'zipsort.1' then echo shar: "will not over-write existing file 'zipsort.1'" else sed 's/^ X//' << \SHAR_EOF > 'zipsort.1' X.TH ZIPSORT "1WI" "November 1985" "Wang Institute" "UNIX User's Manual" X.SH NAME Xzipsort \- sort lines by zipcode X.SH USAGE X.I zipsort X[-] [files] X.SH DESCRIPTION X.I zipsort Xreads a series of lines from the named files or the standard input Xand sorts them by zipcode (a five long series of digits). XIf there are more than one number on a line that looks like Xa zipcode, the last is used. X.SH "SEE ALSO" Xlabel(1W) X.SH AUTHOR(S) XGary Perlman X.SH WARNING X.I zipsort Xassumes that the X.I sort Xand X.I sed Xutilities are available on the system. SHAR_EOF if test 538 -ne "`wc -c < 'zipsort.1'`" then echo shar: "error transmitting 'zipsort.1'" '(should have been 538 characters)' fi fi echo shar: "extracting 'makefile'" '(768 characters)' if test -f 'makefile' then echo shar: "will not over-write existing file 'makefile'" else sed 's/^ X//' << \SHAR_EOF > 'makefile' XMAIN=label XHDRS= XSRCS=number.c filter.c XOBJS=number.o filter.o XDOCS=label.1 intro zipsort.1 XLIBS= XDESTDIR=. XCFLAGS=-O XTEXT=$(HDRS) $(MAIN).c $(SRCS) X XLINT =/usr/bin/lint -hp XPR =@cpr XSPELL =sp XSHAR =shar -a XRCS =ci -l XCC =/bin/cc X X$(MAIN): $(MAIN).o $(OBJS) X $(CC) $(CFLAGS) -o $(MAIN) $(MAIN).o $(OBJS) X Xzipsort: zipsort.o X $(CC) *(CFLAGS) -o zipsort zipsort.o X Xinstall: $(MAIN) zipsort X cp -i $(MAIN) zipsort $(DESTDIR)/$(MAIN) X Xprint: X $(PR) $(MAIN).c X Xlint: X $(LINT) $(TEXT) X Xspell: X seec -cqe $(TEXT) | $(SPELL) X Xarchive: X $(SHAR) $(DOCS) [Mm]akefile $(TEXT) *_label zipsort.c > archive X Xclean: X rm -f *.o core a.out mon.out gmon.out scmon.out X X$(MAIN).1: $(MAIN).c X @seec -t MANUAL $(MAIN).c > $(MAIN).1 X X.PRECIOUS: $(TEXT) $(DOCS) zipsort.c zipsort.1 SHAR_EOF if test 768 -ne "`wc -c < 'makefile'`" then echo shar: "error transmitting 'makefile'" '(should have been 768 characters)' fi fi echo shar: "extracting 'label.c'" '(9423 characters)' if test -f 'label.c' then echo shar: "will not over-write existing file 'label.c'" else sed 's/^ X//' << \SHAR_EOF > 'label.c' X/*MANUAL.TH LABEL "1WI" "November 1985" "Wang Institute" "UNIX User's Manual" X*/ X X/*MANUAL.SH NAME Xlabel \- print label sheet X*/ X X/*MANUAL.SH USAGE X.I label X[-cU] [-d\ delim] [-h\ height] [-i\ indent] [-l\ count] [-n\ repeat] X.ti +.5i X[-s\ skip] [-w\ width] [-] [files] X*/ X X#include <stdio.h> X#include <ctype.h> X X#define MAXFIELDS 30 /* max number of labels across */ X Xtypedef int Status; /* return/exit status of functions */ X#define SUCCESS ((Status) 0) X#define FAILURE ((Status) 1) Xtypedef int Boole; /* no Boolean type in C */ X#define TRUE ((Boole) 1) X#define FALSE ((Boole) 0) X#define EOS '\0' X Xchar *Argv0; /* program name */ Xchar *File; /* current file name */ Xint Labelcount; /* current label number in File */ Xint Linecount; /* current line number in File */ X X/*MANUAL.SH OPTIONS X.I label Xoptions adjust to different label page formats by Xcontrolling the number of labels across a page, Xthe label height and width, and so on.. X.de OP\" option-letter [optional value] X.TP X.B -\\$1 \\$2 X.. X*/ X XBoole Center = FALSE; /*MANUAL.OP c XCenter text on each line in the label. XThis option resets the label indent to 0. X*/ X Xchar Delim = ':'; /*MANUAL.OP d delim XThe label line field delimiter (default: `:' the colon) tells X.I label Xhow to separate fields in a line. XThis character should not appear in the fields you want to print. XSeveral field delimiters in a row (blank fields) are skipped. XIf you really want a blank line inside a label, use a space. X*/ X Xint Realheight; /* Labheight - Labskip */ Xint Labheight = 6; /*MANUAL.OP h height XThe height of a label (default: 6 lines). X*/ X Xint Labindent = 2; /*MANUAL.OP i indent XThe number of spaces to indent before each label (default: 2). X*/ X Xint Nlabels = 3; /*MANUAL.OP l labels XThe number of labels to fit across a page (default: 3). X*/ X Xint Repeat = 1; /*MANUAL.OP n number XThe number of times to repeat each label (default: 1). X*/ X Xint Labskip = 1; /*MANUAL.OP s skip XThe number of lines to skip at the top of each label (default: 1). X*/ X X/*MANUAL.OP U XPrint a usage summary and exit. X*/ X Xint Realwidth; /* usable width of label (Labwidth - Labindent) */ Xint Labwidth = 33; /*MANUAL.OP w width XThe label width in spaces (default 33). X*/ X X/*FUNCTION printusage: on-line help */ Xvoid Xprintusage () X { X fprintf (stderr, "%s: format label sheet\n", Argv0); X fprintf (stderr, "-c center fields on each label line\n"); X fprintf (stderr, "-d C field delimiter character (%c)\n", Delim); X fprintf (stderr, "-h N height in lines of labels (%d lines)\n", Labheight); X fprintf (stderr, "-i N indent before each label (%d spaces)\n", Labindent); X fprintf (stderr, "-l N number of label across page (%d)\n", Nlabels); X fprintf (stderr, "-n N repeat each label N times (%d times)\n", Repeat); X fprintf (stderr, "-s N skip lines at label top (%d lines)\n", Labskip); X fprintf (stderr, "-U print this usage message\n"); X fprintf (stderr, "-v verbose information printed\n"); X fprintf (stderr, "-w N label width (%d spaces)\n", Labwidth); X } X X/*FUNCTION getint: set integer, checking type and range */ XStatus Xgetint (flag, string, varptr, min, max) Xint flag; Xchar *string; Xint *varptr; Xint min; Xint max; X { X int retval = FAILURE; X if (number (string) == 1) /* an integer */ X { X int value = atoi (string); X if (value >= min && value <= max) X { X *varptr = value; X retval = SUCCESS; X } X else X { X fprintf (stderr, "\007%s: -%c value (%s) must be between %d and %d\n", X Argv0, flag, string, min, max); X } X } X else X fprintf (stderr, "\007%s: -%c value (%s) must be an integer\n", X Argv0, flag, string); X return (retval); X } X Xvoid Xnputchar (c, n) X { X while (n-- > 0) X putchar (c); X } X X/*FUNCTION initial: returns local version of optind, index to first operand */ Xint Xinitial (argc, argv) char **argv; X { X extern char *optarg; /* option value accessed through this by getopt */ X extern int optind; /* will be index to first operand */ X int opterr = 0; /* count of number of errors */ X int flag; /* option flag characters read in here */ X char *optstring = /* getopt string */ X "cd:h:i:l:n:s:Uw:"; X char *usage = /* variable part of usage summary */ X "[-cU] [-d delim] [-h height] [-i indent] [-l count] [-n repeat]\n\t[-s skip] [-w width] [-] [files]"; X X Argv0 = argv[0]; X X while ((flag = getopt (argc, argv, optstring)) != EOF) X switch (flag) /* put option cases here */ X { X default: X opterr++; X break; X case 'U': X printusage (); X exit (0); X case 'c': X Center = TRUE; X Labindent = 0; X break; X case 'd': X Delim = *optarg; X break; X case 'h': X if (getint (flag, optarg, &Labheight, 0, 100) == FAILURE) X opterr++; X break; X case 'i': X if (getint (flag, optarg, &Labindent, 0, 100) == FAILURE) X opterr++; X break; X case 'l': X if (getint (flag, optarg, &Nlabels, 1, MAXFIELDS) == FAILURE) X opterr++; X break; X case 'n': X if (getint (flag, optarg, &Repeat, 1, 100) == FAILURE) X opterr++; X break; X case 's': X if (getint (flag, optarg, &Labskip, 0, 100) == FAILURE) X opterr++; X break; X case 'w': X if (getint (flag, optarg, &Labwidth, 10, 150) == FAILURE) X opterr++; X break; X } X X if (opterr) X { X fprintf (stderr, "\007Usage: %s %s\n", argv[0], usage); X exit (1); X } X X Realwidth = Labwidth - Labindent; X Realheight = Labheight - Labskip; X X return (optind); X } X X/*FUNCTION main: loop through files in classic UNIX filter style */ Xvoid Xmain (argc, argv) Xint argc; /* argument count */ Xchar **argv; /* argument vector */ X { X Status label (); /* label (file, ioptr) will filter files */ X Status status; /* return status of filter () */ X int firstfile; /* first file name index returned by initial */ X firstfile = initial (argc, argv); X status = filter (argc, argv, firstfile, label); X exit (status); X } X X/*FUNCTION geline: get non-blank input line and duplicate as needed */ Xchar * Xgetline (line, size, ioptr) Xchar *line; XFILE *ioptr; X { X static char buf[BUFSIZ]; X static int nrepeat = 0; X char *ptr = buf; X X if (nrepeat == 0) X { X do X { X if (fgets (ptr = buf, size, ioptr) == NULL) X return (NULL); X Linecount++; X while (isspace (*ptr)) X ptr++; X } while (*ptr == '\0'); X Labelcount++; X checklabel (buf); X } X strncpy (line, buf, size); X if (++nrepeat == Repeat) X nrepeat = 0; X return (line); X } X X/*FUNCTION fieldprint: print a field in a label */ Xchar * Xfieldprint (lptr) Xchar *lptr; X { X char *eptr = lptr; X int len; /* field length */ X int pad; /* pad needed for field */ X X while (*eptr && *eptr != Delim && *eptr != '\n') eptr++; X while (*eptr == Delim) X *eptr++ = EOS; X if (*eptr == '\n') X *eptr = EOS; X X nputchar (' ', Labindent); X len = strlen (lptr); X if (len > Realwidth) X { X lptr[Realwidth] = '\0'; X pad = 0; X } X else X pad = Realwidth - len; X X if (Center) X { X nputchar (' ', pad / 2); X pad -= pad / 2; X } X printf (lptr); X nputchar (' ', pad); X X return (eptr); X } X X/*MANUAL.SH DESCRIPTION X.PP X.I label Xprints a series of labels in a matrix on a page Xthat is then suitable to use as a copy master for a page of stick on labels. XIf the labels are read in order: 1 2 3 4 5 6, Xand printed three across a page, Xthen the output is arranged like: X.nf X 1 2 3 X 4 5 6 X.fi X.SS Input X.I label Xreads non-blank lines that contain a series of delimited fields. XThe delimiter is a single character that separates the fields. XEach field is used as one line in a label. XExample labels: X.ce 2 XGary Perlman:Wang Institute:Tyng Road:Tyngsboro, MA 01879 XCopyright (c) 1985:Wang Institute:All Rights Reserved X.SS Output X.I label Xreads label lines until it has enough to print a row of labels. X*/ X X/*MANUAL.SH EXAMPLE X.nf XPrint six-high labels, four across, for 12 pitch print (100 wide): X label -h 6 -l 4 -w 25 X.fi X*/ X X/*MANUAL.SH AUTHOR XGary Perlman X*/ X X/*FUNCTION checklabel: print warnings about problems with label */ Xchecklabel (line) Xchar *line; X { X char *ptr; X int nfields = 0; /* number of fields in label */ X Boole truncate = FALSE; /* are fields truncated? */ X X for (;;) X { X for (ptr = line; *ptr && *ptr != '\n' && *ptr != Delim; ptr++); X if (ptr - line > Realwidth) X truncate = TRUE; X while (*ptr == Delim) X ptr++; X nfields++; X if (*ptr == EOS || *ptr == '\n') X break; X line = ptr; X } X X if (nfields > Realheight) X fprintf (stderr, "\007%s: Field ignored in label %d on line %d in %s\n", X Argv0, Labelcount, Linecount, File); X X if (truncate == TRUE) X fprintf (stderr, "\007%s: Field truncated in label %d on line %d in %s\n", X Argv0, Labelcount, Linecount, File); X } X X/*FUNCTION label: main routine */ XStatus Xlabel (file, ioptr) Xchar *file; XFILE *ioptr; X { X char labbuf[MAXFIELDS][BUFSIZ], *lptr[MAXFIELDS]; X int line, col; X X File = file; X Labelcount = 0; X X for (;;) X { X for (col = 0; col < Nlabels; col++) X { X if (getline (labbuf[col], BUFSIZ, ioptr) == NULL) X if (col == 0) /* no labels read in, just quit */ X return (SUCCESS); X else /* at least one label read in, use blanks to pad */ X labbuf[col][0] = EOS; X lptr[col] = labbuf[col]; X } X nputchar ('\n', Labskip); X for (line = 0; line < Labheight-Labskip; line++) X { X for (col = 0; col < Nlabels; col++) X lptr[col] = fieldprint (lptr[col]); X putchar ('\n'); X } X } X } SHAR_EOF if test 9423 -ne "`wc -c < 'label.c'`" then echo shar: "error transmitting 'label.c'" '(should have been 9423 characters)' fi fi echo shar: "extracting 'number.c'" '(4039 characters)' if test -f 'number.c' then echo shar: "will not over-write existing file 'number.c'" else sed 's/^ X//' << \SHAR_EOF > 'number.c' X/* Copyright (c) 1982, 1985 Gary Perlman */ X/* Copies can be made if not for material gain */ X X/* X number: report if a string is a UNIX formatted number X X notes: X a number in UNIX is one that can be converted from X a string to an integer or real with no loss of information X due to bad format X all numbers can be surrounded by whitespace X an integer has an optional minus sign, followed by digits X a real number has an optional minus sign followed by digits X if a string has a decimal point, followed by zeros, it is real, not int X X value: X 1 is string is an integer [-] 0-9+ X 2 is string is a real number (as seen by atof) X 0 for non-numbers X X compilation flags: X -DSTANDALONE includes test main program X $Compile: cc -DSTANDALONE -O -o %F %f X X deficiencies: X does not check to see if significant digits will be ignored X X author: X Gary Perlman X X date: X Wed May 22 13:30:40 EDT 1985 X Sun Sep 1 14:53:51 EDT 1985 (modified test module) X X*/ X#include <ctype.h> X X#ifndef lint Xstatic char sccsfid[] = "@(#) number.c 5.2 (unix|stat) 9/1/85"; X#endif X X#define IS_NOT 0 /* not a number */ X#define IS_INT 1 /* an integer */ X#define IS_REAL 2 /* a real number */ X X#define EOS '\0' X X/*LINTLIBRARY*/ X Xnumber (string) Xchar *string; /* the string to be tested */ X { X int answer = IS_INT; /* start by assuming it is an integer */ X int before = 0; /* anything before the decimal? */ X int after = 0; /* anything after the decimal? */ X while (isspace (*string)) /* skip over blank space */ X string++; X if (*string == EOS) /* empty string not allowed */ X return (IS_NOT); X if (*string == '+' || *string == '-') /* old atoi didn't allow '+' */ X { X string++; X if (!isdigit (*string) && *string != '.') X return (IS_NOT); X } X if (isdigit (*string)) /* note that there was a digit before . */ X { X before = 1; X while (isdigit (*string)) X string++; X } X if (*string == '.') /* found a decimal point, parse for real */ X { X answer = IS_REAL; X string++; X if (isdigit (*string)) /* note that there was a digit after . */ X { X after = 1; X while (isdigit (*string)) X string++; X } X } X if (!before && !after) /* must be digit somewhere */ X return (IS_NOT); X if (*string == 'E' || *string == 'e') /* exponent */ X { X answer = IS_REAL; X string++; X if (*string == '+' || *string == '-') /* optional sign */ X string++; X if (!isdigit (*string)) /* missing exponent */ X return (IS_NOT); X while (isdigit (*string)) X string++; X } X while (isspace (*string)) /* skip optional spaces */ X string++; X /* should now have exhausted the input string */ X return (*string == EOS ? answer : IS_NOT); X } X X#ifdef STANDALONE X X#include <stdio.h> X/* X exits with status = the number of args not numerical X Shell Example: X if number -i $* X then X echo processing $* X else X echo $0: arguments must be integers X fi X Options: X -i arguments must be integer X -n arguments must be non-negative X*/ Xint NoNegative; /* do the values have to be non-negative? */ Xint Integer; /* do the values have to be integers? */ X Xstatic Xint Xinitial (argc, argv) char **argv; X { X extern char *optarg; X extern int optind; X int errflg = 0; X int C; X char *optstring = "in"; X char *usage = "[-in] string ..."; X while ((C = getopt (argc, argv, optstring)) != EOF) X switch (C) X { X case 'i': Integer = 1; break; X case 'n': NoNegative = 1; break; X default: errflg++; break; X } X if (errflg) X { X fprintf (stderr, "Usage: %s %s\n", argv[0], usage); X exit (1); X } X return (optind); X } X Xmain (argc, argv) char **argv; X { X int status = 0; X int arg = initial (argc, argv); X char *string; X while (arg < argc) X { X string = argv[arg++]; X if (NoNegative && *string == '-') status++; X else switch (number (string)) X { X case IS_NOT: status++; break; X case IS_REAL: if (Integer) status++; break; X case IS_INT: break; X default: /* CAN'T HAPPEN */ break; X } X } X exit (status); X } X X#endif SHAR_EOF if test 4039 -ne "`wc -c < 'number.c'`" then echo shar: "error transmitting 'number.c'" '(should have been 4039 characters)' fi fi echo shar: "extracting 'filter.c'" '(4306 characters)' if test -f 'filter.c' then echo shar: "will not over-write existing file 'filter.c'" else sed 's/^ X//' << \SHAR_EOF > 'filter.c' X/* X Function: filter "Filter Command Line Files In Classic UNIX Style" X Created: Sat Aug 10 21:57:12 EDT 1985 X By: Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA) X Compilation: nothing unusual X Tester: $Compile: cc -DSTANDALONE -o filter %f X Preconditions: X The index of the first file operand has been determined. X Postconditions: X All files have been opened, processed, and closed. X Returns: X The return status (non-zero is bad) depends on the accessibility X of files, the ability to open them, and the return statuses of X the called function. X Exceptions: X If any file cannot be accessed, then none will be processed. X During processing, if something goes wrong (a file that could X be accessed cannot be opened, or the file processor returns a X non-zero status), processing continues. X Notes: X "-" is the conventional name for the standard input. X It can only be read once. X Fputs and putc are used to print error messages to avoid X loading fat fprintf just because filter used it. X*/ X X X#include <stdio.h> X X#ifdef STANDALONE X Xint Xcat (file, ioptr) Xchar *file; Xregister FILE *ioptr; X { X register int C; X while ((C = getc (ioptr)) != EOF) X putchar (C); X return (0); X } X Xmain (argc, argv) char **argv; X { X int cat (); X X if (filter (argc, argv, 1, cat)) X { X putc ('\007', stderr); /* UNIX friendly error message */ X exit (1); X } X exit (0); X } X X#endif STANDALONE X X X/* LINTLIBRARY */ Xstatic Xvoid Xerrmsg (pgm, file, errorno, dflt) Xchar *pgm; /* name of the program running */ Xchar *file; /* file operand to be mentioned (if any) */ Xint errorno; /* system errno or some bad value */ Xchar *dflt; /* default message for bad error numbers */ X { X extern char *sys_errlist[]; /* list of error messages */ X extern int sys_nerr; /* number of error messages */ X X fputs (pgm, stderr); X putc (':', stderr); X putc (' ', stderr); X if (errorno > 0 && errorno < sys_nerr) X fputs (sys_errlist[errorno], stderr); X else X fputs (dflt, stderr); X if (file) X { X putc (' ', stderr); X putc ('\'', stderr); X fputs (file, stderr); X putc ('\'', stderr); X } X putc ('\n', stderr); X } X X X#define isstdin(file) (file[0] == '-' && file[1] == '\0') X Xint Xfilter (argc, argv, curarg, process) Xint argc; /* real number of command line args */ Xchar **argv; /* command line argument pointer */ Xint curarg; /* first argv to filter */ Xint (*process) (); /* status process (char *name, FILE *ioptr) */ X { X int status = 0; /* return status of this function */ X int arg; /* loop index variable */ X char *file; /* name of the current file */ X char *pgm = argv[0]; /* name of the program */ X FILE *ioptr; /* file pointer for opening */ X int countstdin = 0; /* number of times stdin is processed */ X extern int errno; /* system error number */ X X if (curarg == argc) X status += ((*process) ("-", stdin)); X else X { X /* first check to make sure all files can be opened to read */ X for (arg = curarg; arg < argc; arg++) X { X file = argv[arg]; X if (isstdin (file)) X countstdin++; X else if (access (file, 4)) X { X errmsg (pgm, file, errno, "Can't access file"); X status++; X } X } X if (countstdin > 1) X { X errmsg (pgm, NULL, -1, "Can only read standard input once"); X status++; X } X if (status == 0) X for (arg = curarg; arg < argc; arg++) X { X file = argv[arg]; X if (isstdin (file)) X status += ((*process) (file, stdin) != 0); X else if (ioptr = fopen (file, "r")) X { X status += ((*process) (file, ioptr) != 0); X (void) fclose (ioptr); X } X else X { X errmsg (pgm, file, errno, "Can't open file"); X status++; X } X } X } X return (status); X } X X/*NOTES X Some modifications might be useful but unpopular: X If there is piped input (!isatty (fileno (stdin))), X and the standard input is not read, X then some information may be ignored, X so a warning should be printed. X Unfortunately, this would break things like vi filters. X X If there is not piped input, X and the standard input is being read from the keyboard, X then prompt the user for input with something like: X pgm: reading input from terminal X This would avoid the problem of people forgetting to supply X an input redirection. X*/ SHAR_EOF if test 4306 -ne "`wc -c < 'filter.c'`" then echo shar: "error transmitting 'filter.c'" '(should have been 4306 characters)' fi fi echo shar: "extracting 'big_label'" '(294 characters)' if test -f 'big_label' then echo shar: "will not over-write existing file 'big_label'" else sed 's/^ X//' << \SHAR_EOF > 'big_label' X#!/bin/sh X XPATH=$PATH:/usr/ebin Xexport PATH X X# make label pages for big labels 4.25 (50 spaces) x 2 (12 lines) inches X Xlabel -h 12 -s 2 -l 2 -w 50 -i 3 $* | X ff -b -h "" -f "" -H 3 -F 3 | # put on a three line header/footer X sed "s/ *$//" # remove trailing spaces SHAR_EOF if test 294 -ne "`wc -c < 'big_label'`" then echo shar: "error transmitting 'big_label'" '(should have been 294 characters)' fi chmod +x 'big_label' fi echo shar: "extracting 'small_label'" '(343 characters)' if test -f 'small_label' then echo shar: "will not over-write existing file 'small_label'" else sed 's/^ X//' << \SHAR_EOF > 'small_label' X#!/bin/sh X XPATH=$PATH:/usr/ebin Xexport PATH X X# make label pages for small labels 2.75 (33 spaces) x 1 (6 lines) inch X Xlabel -h 6 -l 3 -w 33 -i 2 $* | X ff -b -i 1 | # indent the lines one space X sed "s/ *$//" # remove trailing spaces X X# you could use X# sed "s/^/ /" instead of the faster ff call SHAR_EOF if test 343 -ne "`wc -c < 'small_label'`" then echo shar: "error transmitting 'small_label'" '(should have been 343 characters)' fi chmod +x 'small_label' fi echo shar: "extracting 'zipsort.c'" '(3999 characters)' if test -f 'zipsort.c' then echo shar: "will not over-write existing file 'zipsort.c'" else sed 's/^ X//' << \SHAR_EOF > 'zipsort.c' X/* X $Compile: cc -O -o %F %f X*/ X#include <stdio.h> X#include <ctype.h> X#include <strings.h> X Xint Special = '\001'; /* magic char after sorting key */ X Xtypedef int Status; /* return/exit status of functions */ X#define SUCCESS ((Status) 0) X#define FAILURE ((Status) 1) Xtypedef int Boole; /* no Boolean type in C */ X#define TRUE ((Boole) 1) X#define FALSE ((Boole) 0) X XFILE *Pioptr; /* will pipe to sort and sed */ X X/*FUNCTION main: loop through files in classic UNIX filter style */ Xmain (argc, argv) Xint argc; /* argument count */ Xchar **argv; /* argument vector */ X { X Status process (); /* process (file, ioptr) will filter files */ X Status status; /* return status of filter () */ X int firstfile; /* first file name index returned by initial */ X FILE *popen (); X char command[BUFSIZ]; X X firstfile = 1; X X sprintf (command, "sort | sed 's/^.*%c//'", Special); X X if (Pioptr = popen (command, "w")) X { X status = filter (argc, argv, firstfile, process); X pclose (Pioptr); X } X else X { X fprintf (stderr, "%s: Can't run sorting pipeline\n", argv[0]); X status = (-1); X } X exit (status); X } X X#define iszipcode(s) \ X (!isdigit (s[-1]) \ X && isdigit (s[0]) \ X && isdigit (s[1]) \ X && isdigit (s[2]) \ X && isdigit (s[3]) \ X && isdigit (s[4]) \ X && !isdigit (s[5])) X Xprocess (file, ioptr) Xchar *file; XFILE *ioptr; X { X char line[BUFSIZ]; X char *ptr; X int zipcode; X X while (fgets (ptr = line, BUFSIZ, ioptr)) X { X zipcode = 0; X for (ptr = line; *ptr; ptr++); X while (ptr > line) X if (iszipcode (ptr)) X { X zipcode = atoi (ptr); X break; X } X else ptr--; X fprintf (Pioptr, "%05d%c%s", zipcode, Special, line); X } X } X Xstatic Xvoid Xerrmsg (pgm, file, errorno, dflt) Xchar *pgm; /* name of the program running */ Xchar *file; /* file operand to be mentioned (if any) */ Xint errorno; /* system errno or some bad value */ Xchar *dflt; /* default message for bad error numbers */ X { X extern char *sys_errlist[]; /* list of error messages */ X extern int sys_nerr; /* number of error messages */ X X fputs (pgm, stderr); X putc (':', stderr); X putc (' ', stderr); X if (errorno > 0 && errorno < sys_nerr) X fputs (sys_errlist[errorno], stderr); X else X fputs (dflt, stderr); X if (file) X { X putc (' ', stderr); X putc ('\'', stderr); X fputs (file, stderr); X putc ('\'', stderr); X } X putc ('\n', stderr); X } X X#define isstdin(file) (file[0] == '-' && file[1] == '\0') X Xint Xfilter (argc, argv, curarg, process) Xint argc; /* real number of command line args */ Xchar **argv; /* command line argument pointer */ Xint curarg; /* first argv to filter */ Xint (*process) (); /* status process (char *name, FILE *ioptr) */ X { X int status = 0; /* return status of this function */ X int arg; /* loop index variable */ X char *file; /* name of the current file */ X char *pgm = argv[0]; /* name of the program */ X FILE *ioptr; /* file pointer for opening */ X int countstdin = 0; /* number of times stdin is processed */ X extern int errno; /* system error number */ X X if (curarg == argc) X status += ((*process) ("-", stdin)); X else X { X /* first check to make sure all files can be opened to read */ X for (arg = curarg; arg < argc; arg++) X { X file = argv[arg]; X if (isstdin (file)) X countstdin++; X else if (access (file, 4)) X { X errmsg (pgm, file, errno, "Can't access file"); X status++; X } X } X if (countstdin > 1) X { X errmsg (pgm, NULL, -1, "Can only read standard input once"); X status++; X } X if (status == 0) X for (arg = curarg; arg < argc; arg++) X { X file = argv[arg]; X if (isstdin (file)) X status += ((*process) (file, stdin) != 0); X else if (ioptr = fopen (file, "r")) X { X status += ((*process) (file, ioptr) != 0); X (void) fclose (ioptr); X } X else X { X errmsg (pgm, file, errno, "Can't open file"); X status++; X } X } X } X return (status); X } SHAR_EOF if test 3999 -ne "`wc -c < 'zipsort.c'`" then echo shar: "error transmitting 'zipsort.c'" '(should have been 3999 characters)' fi fi exit 0 # End of shell archive -- Gary Perlman Wang Institute Tyngsboro, MA 01879 (617) 649-9731 UUCP: decvax!wanginst!perlman CSNET: perlman@wanginst