v13i046: Program to make mailing labels

Rich Salz rsalz at bbn.com
Wed Feb 17 11:28:31 AEST 1988


Submitted-by: Joe Chen <joec%wasat.usc.edu at OBERON.USC.EDU>
Posting-number: Volume 13, Issue 46
Archive-name: labels


LABELS is a label formatting program.  It formats labels/mailing lists
according to user-defined label forms.  This program has been fully
tested under Sun Unix 3.2 (BSD UNIX) and should work on any BSD UNIX
systems.  It should also work under other UNIX systems with little
changes.  As for non-Unix systems, like MS-DOS, you would need lex
and yacc for the PC, or obtain lex.yy.c and y.tab.* from an UNIX system.

						Joe S. Chen

---------------------------------------------------------------------------
Phones at work: (213) 743-5363, (213) 743-5935; at home: (818) 571-5304
University Computing Services, University of Southern California
UUCP: {sdcrdcf, uscvax}!oberon!wasat!joec
ARPA: joec at wasat.usc.edu, joec at ecla.usc.edu
---------------------------------------------------------------------------

----------CUT HERE----------CUT HERE----------CUT HERE----------CUT HERE------
#!/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:
#	INSTALL
#	Makefile
#	main.c
#	labels.l
#	labels.y
#	labels.man
#	1083.lbl
#	1083f.lbl
#	1083t.lbl
#	6080.lbl
#	6080f.lbl
#	6080t.lbl
#	6083.lbl
#	6083f.lbl
#	6083t.lbl
export PATH; PATH=/bin:$PATH
echo shar: extracting "'INSTALL'" '(891 characters)'
if test -f 'INSTALL'
then
	echo shar: over-writing existing file "'INSTALL'"
fi
cat << \SHAR_EOF > 'INSTALL'
Installation Procedure:

After extracting files from the shell archive, modify the following
variables in Makefile:

	DESTDIR		Destination directory, where the program
			will be installed.

	FRMDIR		Directory (doesn't have to exist) where
			pre-defined forms will reside.

	LNAME		Name of the program.

	CFLAGS		Define System where this program will
			run under.


If you want to set a default form, you must edit the beginning
section of main.c.

To compile LABELS, type:

%make

and press carriage return.  To install LABELS, type

%make install

and press carriage return, and the program and preset forms
will be installed in the proper directories.  To install
the man page, you can simply copy the file 'labels.1' to
your man directory (e.g. /usr/man/man1).


To re-package labels, type

%make shar

and press return.  The archived file 'labels.shar' will be the
new shell archive.
SHAR_EOF
echo shar: extracting "'Makefile'" '(2809 characters)'
if test -f 'Makefile'
then
	echo shar: over-writing existing file "'Makefile'"
fi
cat << \SHAR_EOF > 'Makefile'
#			    -- MAKEFILE (UNIX) --
#
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@                                                                         @@
# @@                    Mailing List Label Formatter                         @@
# @@                  Program Maintenance Specification                      @@
# @@                    (C) Copyright 1987 by Joe Chen                       @@
# @@                         All Rights Reserved                             @@
# @@                                                                         @@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#
# Program created by Joe Chen - Jul 24, 1987
#
# *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

# Directory where LABELS is to be installed (please specify the full path)
DESTDIR = /usr/pollux/jchen/bin

# Directory where label forms can be found (please specify the full path)
FRMDIR = /usr/pollux/jchen/bin/lib

# Program name
LNAME = labels

# Compiling flags UNIX, BSD (USG and MSDOS are valid, but not fully supported)
# NOTE: This program has been fully tested on Sun UNIX only.
CFLAGS = -DBSD -DUNIX

CC = cc -c -g $(CFLAGS)
YACC = yacc
LEX = lex
LINK = cc

# *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

OBJS = y.tab.o lex.yy.o main.o


labels: $(OBJS)
	@echo char \*rev_date = \"`date`\"\; > revdate.c
	@echo Linking $(LNAME)...
	@${LINK} $(OBJS) revdate.c -o $(LNAME)
	@rm -f revdate.c revdate.o
	@echo 
	@echo \`$(LNAME)\' Compiled.

y.tab.c: labels.y
	@echo Running Yacc...
	@${YACC} -d labels.y

y.tab.o: y.tab.c
	@echo Compiling: y.tab.c
	@${CC} y.tab.c

lex.yy.c: labels.l
	@echo Running Lex...
	@${LEX} labels.l

lex.yy.o: lex.yy.c y.tab.h
	@echo Compiling: lex.yy.c
	@${CC} lex.yy.c

main.o: main.c Makefile
	@echo Compiling: main.c
	@${CC} -DFDIR=\"$(FRMDIR)\" main.c

install:
	@echo Installing \`$(LNAME)\' in $(DESTDIR)...
	@rm -f $(DESTDIR/$(LNAME)
	@cp $(LNAME) $(DESTDIR)/$(LNAME)
	@strip $(DESTDIR)/$(LNAME)
	@chmod 755 $(DESTDIR)/$(LNAME)
	@echo
	@echo Placing Form Definitions in $(FRMDIR)...
	@echo mkdir $(FRMDIR) 2\> /dev/null \; exit 0 > mklib
	@chmod u+x mklib
	@./mklib
	@rm -f mklib
	@chmod 755 $(FRMDIR)
	@cp *.lbl $(FRMDIR)
	@chmod 644 $(FRMDIR)/*.lbl
	@make man
	@echo 
	@echo \`$(LNAME)\' installed.

clean:
	@echo Cleaning Directory...
	@rm -f *.o *\~ y.tab.* lex.yy.c $(LNAME)
	@echo 
	@echo Done!

man:
	@echo
	@echo Processing a raw man page: $(LNAME).1
	@/lib/cpp -P -DLIBDIR=$(FRMDIR) -DLNAME=$(LNAME) -DPROGDIR=$(DESTDIR) \
		$(LNAME).man > $(LNAME).1


shar:
	@echo Shell Archiving \($(LNAME)\.shar\)...
	@shar INSTALL Makefile main.c labels.l labels.y labels.man \
		*.lbl > $(LNAME).shar
	@echo 
	@echo Done!
SHAR_EOF
echo shar: extracting "'main.c'" '(17102 characters)'
if test -f 'main.c'
then
	echo shar: over-writing existing file "'main.c'"
fi
cat << \SHAR_EOF > 'main.c'
/*			         -- MAIN.C --

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@                                                                           @@
@@                       Mailing List Label Formatter                        @@
@@                                Main Module                                @@
@@                      (C) Copyright 1987 by Joe Chen                       @@
@@                           All Rights Reserved                             @@
@@                                                                           @@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

You may freely distribute this software to others.  But there are
few rules you must follow:

1. You don't profit from it.  You may however ask for minimal fees to
   cover shipping and handling.

2. This program is copyrighted, meaning you may not modify or enhance
   this software and market it.  You may make changes to suit your
   local needs.  Any enhancements are welcomed.

3. Please honor the author by not removing or replacing his name from
   the source codes.


Feel free to contact me if you have any questions.

					Joe Chen

---------------------------------------------------------------------------
Phones at work: (213) 743-5363, (213) 743-5935; at home: (818) 571-5304
University Computing Services, University of Southern California
UUCP: {sdcrdcf, uscvax}!oberon!wasat!joec
ARPA: joec at wasat.usc.edu, joec at ecla.usc.edu
---------------------------------------------------------------------------

Program created by Joe Chen - Jul 24, 1987

*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

*/

/* Internal default form: 32x11x3 */

#define DEF_FORM "1083"		/* form name here at USC        */

#define ISTRING	NULL		/* initial escape sequence	*/
#define IFILL	12		/* fill n rows for adjustments	*/
#define FOFFS	 0		/* form offset (from top)	*/
#define POFFS	 0		/* page offset (from left)	*/

#define LWIDTH	32		/* width (in chars) of each label */
#define LHGAP	 4		/* horizontal gap (in chars) between labels */
#define LVGAP	 1		/* vertical gap (# of lines) between labels */
#define LCROSS	 3		/* number of labels accross */
#define LMLINES	11		/* Maximum lines per label  */
#define LOFFSET	 4		/* offset (in chars) from left edge */
				/* of each label */
#define LROWS	 0		/* labels per page, 0=don't care*/


/*****************************************************************************/
#include <stdio.h>

#define QUIT		(perror(argv[0]),dsp_usg(argv[0]),exit(-1))
#define FEXT		".lbl"	/* file extension for form definition file  */
#define GETC(x)		(((ch=getc(x))=='\n')?line_num++,ch:ch);

#ifdef BSD
#include <sys/types.h>
#include <sys/dir.h>
#endif BSD

char *def_form = DEF_FORM;	/* default label form			    */

char *def_istring = ISTRING;	/* initial string/escape sequence           */

char *l_istring;

int l_ifill = IFILL;		/* Initial label fill for manual adjustments*/

int l_foffs = FOFFS;		/* form offset (from top)		    */
int l_poffs = POFFS;		/* page offset (from left)		    */
int l_width = LWIDTH;		/* width of one label (in characters)       */
int l_hgap  = LHGAP;		/* horizontal gap between labels (in chars) */
int l_vgap  = LVGAP;		/* vertical gap between labels (in chars)   */
int l_cross = LCROSS;		/* number of labels across one row          */
int l_mlines= LMLINES;		/* maximum printable lines per label        */
int l_offset= LOFFSET;		/* offset printing of data (in chars)       */
int l_lrows = LROWS;		/* rows of labels per page                  */

FILE *infile = stdin, *outfile = stdout;
int line_num = 1;

#define T	1
#define F	0

extern char *malloc(), *getcwd();
extern char *rev_date;			/* supplied by Makefile		    */
extern FILE *yyin;			/* from lex			    */

char *inpf = NULL, *outf = NULL;	/* pointer to file names            */
char *form = NULL;			/* pointer to form name             */

char **fmt_arry;			/* line formatter		    */

char *version = "1.1";

#ifdef UNIX
#ifdef BSD
static char *os_title = "BSD UNIX Version";
#else
#ifdef USG
static char *os_title = "AT&T UNIX Version";
#endif USG
#endif BSD
#endif UNIX

#ifdef MSDOS
static char *os_title = "MS-DOS Verson";
#endif MSDOS

/****************************************************************************
  dsp_usg() [Private function] - Display a brief usage info

  parameters:	name			Name of this program

  exit flags:	none
****************************************************************************/

static void dsp_usg(name)
     char *name;
{
  printf("\nUsage: %s [-f <label form>] [<input file> [output file]]\n",
	 name);
  printf("   or: %s -h\n", name);
#ifdef BSD
  printf("   or: %s -l\n", name);	/* list predefined forms */
#endif BSD
  printf("\nWhere: <label form>  is defined in %s,\n",FDIR);
  printf("                     or defined by user in the current directory.");
  printf("\n       <input file>  is a text file containing raw labels.\n");
  printf("       <output file> is the formatted label output.\n");
  printf("       -h            displays this help.\n");
  printf("       -l            lists all predefined forms.\n\n");
} /* dsp_usg() */

/****************************************************************************
  list_forms() [Private function] - List predefined forms (BSD Unix only)

  parameters:	name		program name (for error display purpose)

  exit flags:	none
****************************************************************************/

static void list_forms(name)
     char *name;
{
#ifdef UNIX
#ifdef BSD
  DIR *dirp;			/* directory pointer */
  struct direct *dp;		/* pointer to a directory record */
  char *ext_ptr;		/* extension pointer */
  char tmp[MAXNAMLEN+1], ch, *cur_dir;
  int header = F;
  FILE *f;

  if ((dirp = opendir(FDIR)) == (DIR *)NULL) {
    fprintf(stderr,"%s: Cannot Open Directory: %s\n",name, FDIR);
    return;
  }

  if ((cur_dir = getcwd(NULL, 100)) == (char *)NULL) {
    fprintf(stderr,"FATAL ERROR: Insufficient Memory\n");
    exit(-1);
  }
  chdir(FDIR);		/* change to directory containing the form defs */

  for (dp = readdir(dirp); dp != (struct direct *)NULL; dp = readdir(dirp)) {
    if (strlen(dp->d_name) <= strlen(FEXT))
      continue;
    ext_ptr = &dp->d_name[strlen(dp->d_name)-strlen(FEXT)];
    if (!strcmp(ext_ptr, FEXT)) {	/* must have the same extension */
      (void) strcpy(tmp, dp->d_name);
      /* ignore extension */
      tmp[strlen(tmp)-strlen(FEXT)] = '\0';
      if (!header) {
	fprintf(stderr,"Preset Forms\tRemarks\n");
	fprintf(stderr,"------------\t-------\n");
	header = T;
      }
      /* print out the name of the form */
      fprintf(stderr,"%s\t\t", tmp);

      if ((f=fopen(dp->d_name,"r")) == (FILE *)NULL)
	fprintf(stderr,"(Form Unreadable)\n");
      else {
	/* Display the first line, if it is a remark */
	if (getc(f) != '#')
	  fprintf(stderr,"(No Remark)\n");
	else {
	  while ((ch=getc(f)) == ' ');		/* skip leading spaces */
	  ungetc(ch, f);
	  while ((ch=getc(f)) != '\n') {
	    putc(ch, stderr);			/* print comment       */
	    if (feof(f))
	      break;
	  } /* keep reading info */
	  fprintf(stderr,"\n");
	} /* display a line of info */
	fclose(f);
      } /* query file */
    }
  } /* for all entries */
  chdir(cur_dir);		/* change back the directory */
  free(cur_dir);
#endif BSD

#ifdef USG
  /* System V listing: for now, just use ls */
  char cmd[100];
  (void) sprintf(cmd, "/bin/ls %s/*%s", FDIR, FEXT);
  (void) system(cmd);
#endif USG
#endif UNIX

#ifdef MSDOS
  fprintf(stderr,"Not implemented at this time for MSDOS\n");
#endif MSDOS
} /* list_forms() */

/****************************************************************************
  get_record() [Private function] - Reads one label info into internal buffer

  parameters:	rec		Buffer for holding one label record

  exit flags:	0		end-of-file or no label between periods
		>0		number of lines read for this label
****************************************************************************/

static int get_record(rec)
     char **rec;
{
  char ch, *p;
  int i = 0, j;

  do {
    p = rec[i];		/* next line */
    /* read in one line */
    for (j = 0, p[j] = '\0'; ; j++) {
      if (!feof(infile)) {
	if (j > (l_width-l_offset)) {		/* line too long */
	  fprintf(stderr,"Line %d: Line too long (%d) - Truncated\n",
		  line_num, l_width);
	  p[l_width-l_offset] = '\0';		/* force termination */
	  while (getc(infile) != '\n')
	    if (feof(infile))
	      return i;
	  line_num++;
	  break;
	} /* line too long */

	if ((p[j]=getc(infile)) == '\n') {	/* read in next char */
	  line_num++;
	  p[j] = '\0';
	  break;
	} /* if end-of-line, go read next line */

	if ((!j)&&(p[j]=='.')) {		/* end of label */
	  while (getc(infile) != '\n')
	    if (feof(infile))
	      break;				/* end of file */
	  line_num++;
	  return i;				/* return lines read */
	} /* end of label detected */
      }
      else
	return i;
    } /* for */
  } while (++i < l_mlines);    

  if ((ch=getc(infile)) != '.')
    fprintf(stderr,"Line %d: Lines Exceeded Limit (%d) - Ignoring the Rest\n",
	    line_num,l_mlines);
  ungetc(ch, infile);

  /* truncating... */
  while (1) {
    if (getc(infile) == '.') {	/* at the end already */
      while(getc(infile) != '\n')
	if (feof(infile))
	  break;
      line_num++;
      return i;
    } /* skip to next label */
    while(getc(infile) != '\n')
      if (feof(infile))
	return i;
    line_num++;
  }
} /* get_record() */

/****************************************************************************
  main() [Public function] - Startup routine

  parameters:	argc		Number of command-line arguments
		argv		argument array

  exit flags:	0		Program terminate normally
		<>0		Error (of some sort) occurred, program aborted
****************************************************************************/

main(argc, argv)
     int argc;
     char **argv;
{
  char **row, **rec, *p, *tmpbuf;
  int arg_limit = 3;	/* argument handler (too hard to explain) */
  register i, j, k, l;
  int cur_col, lines, started = F, row_count;
  FILE *ffile;			/* to read form file */

  l_istring = def_istring;

  if (argc > 1) {
    /* get brief usage */
    if ((!strcmp(argv[1], "help"))||(!strcmp(argv[1], "-h"))) {
      dsp_usg(argv[0]);
      exit(0);
    }

    /* list defined forms in FDIR */
    if (!strcmp(argv[1], "-l")) {
      list_forms(argv[0]);
      exit(0);
    }
  } /* check for single argument */

  fprintf(stderr,
	  "LABELS: Label/Mailing List Formatter - %s\n", os_title);
  fprintf(stderr,"Release %s - Compiled %s\n\n", version, rev_date);

  form = def_form;


  /* allocate space to hold data format for each line */
  if ((fmt_arry = (char **) malloc(l_mlines*sizeof(char *))) ==(char **)NULL)
    QUIT;
  for (i=l_mlines; i ; i--) {
    fmt_arry[i-1] = malloc(l_width+1);
    if (fmt_arry[i-1] == (char *)NULL)
      QUIT;
    (void) strcpy(fmt_arry[i-1], "%s");	/* default format, data only */
  }

  if (argc < 2)
    goto ckarg;

  /* Check if user specified his/her own form */
  if (!strcmp(argv[1], "-f")) {
    char *frm_name;

    if (argc == 2) {
      fprintf(stderr,"%s: Form name is missing!\n",argv[0]);
      exit(-1);
    }

    /* Make a complete file name for form */;
    frm_name = malloc(strlen(FDIR)+strlen(argv[2]+strlen(FEXT)+2));
    if (frm_name == (char *)NULL)
      QUIT;
    arg_limit += 2;

    form = argv[2];

    /* create a path to open the label form file */
    (void) strcpy(frm_name, FDIR);
#ifdef MSDOS
    (void) strcat(frm_name, "\\");
#else
    (void) strcat(frm_name, "/");
#endif MSDOS
    (void) strcat(frm_name, form);
    (void) strcat(frm_name, FEXT);	/* form extension */

    /* open file */
    if ((ffile=fopen(frm_name, "r")) == (FILE *)NULL) {
      /* trouble opening file from library directory, try current directory */
      (void) strcpy(frm_name, ".");
#ifdef MSDOS
      (void) strcat(frm_name, "\\");
#else
      (void) strcat(frm_name, "/");
#endif MSDOS
      (void) strcat(frm_name, form);
      (void) strcat(frm_name, FEXT);	/* form extension */
      if ((ffile=fopen(frm_name, "r")) == (FILE *)NULL) {
	/* cannot open file in current directory either, give up */
	fprintf(stderr,"%s: Cannot read form: %s\n",*argv,form);
	exit(-1);
      }
    } /* open form */

    yyin = ffile;

    /* now parse the file */
    if (yyparse()) {
      fprintf(stderr,"%s: Error reading form: %s\n",*argv,form);
      exit(-1);
    }
    free(frm_name);
  } /* reading form definitions */

 ckarg:
  /* Check if there are too many arguments */
  if (argc > arg_limit) {
    fprintf(stderr,"%s: Too many arguments\n", argv[0]);
    exit(-1);
  }

  /* Check if output file is given (has to be the last argument) */
  if (argc > arg_limit-1) {
    if ((outfile = fopen(argv[arg_limit-1], "w")) == (FILE *)NULL)
      QUIT;
    outf = argv[arg_limit-1];
  }

  /* Check if input file is given (second to the last argument) */
  if (argc > arg_limit-2) {
    if ((infile = fopen(argv[arg_limit-2],"r")) == (FILE *)NULL)
      QUIT;
    inpf = argv[arg_limit-2];
  }

  /* allocate space to hold a row of labels of n across */
  if ((row = (char **) malloc(l_mlines*sizeof(char *))) == (char **)NULL)
    QUIT;
  for (i=l_mlines; i ; i--) {
    row[i-1] = malloc(l_width*l_cross+l_hgap*(l_cross-1)+100);
    if (row[i-1] == (char *)NULL)
      /* insufficient memory */
      QUIT;
  } /* for */

  fprintf(stderr,"[Input: %s, Output: %s, Form: %s]\n",
	 (inpf!=(char *)NULL)?inpf:"(stdin)",
	 (outf!=(char *)NULL)?outf:"(stdout)", form);

  /* allocate space to hold one label of n lines */
  if ((rec = (char **) malloc((l_mlines+1)*sizeof(char *))) == (char **)NULL)
    QUIT;
  for (i=l_mlines+1; i ; i--)		/* buffer space should be big */
    if ((rec[i-1] = malloc(l_width*2)) == (char *)NULL)
      QUIT;

  /* for formatting purpose */
  if ((tmpbuf = malloc(l_width*2)) == (char *)NULL)
    QUIT;

  row_count = l_lrows + 1;		/* ensure checking for form offset */

  /* main loop */
  while(T) {
    /* clear one row of labels*/
    for (i = 0; i <  l_mlines; i++)
      for (j = 0, k = (l_width*l_cross+l_hgap*(l_cross-1)); j < k ; j++)
	row[i][j] = ' ';

    for (cur_col=0; cur_col < l_cross; cur_col++) {

      while (!(lines=get_record(rec)))	/* get one label from input         */
	if (feof(infile)) {		/* if no lines read, probably eof   */
	  if (cur_col)
	    goto f;			/* flush output                     */
	  goto d;			/* quit                             */
	}

      /* Check each input line with format string */
      for (i = 0; i < lines; i++) {
	if (!strcmp(fmt_arry[i], "%s"))
	  continue;			/* no need to format, use default   */

	(void) strcpy(tmpbuf,rec[i]);
	(void) sprintf(rec[i],fmt_arry[i],tmpbuf);

	/* truncate if string too long after formatting */
	if (strlen(rec[i]) > (l_width-l_offset)) {
	  rec[i][(l_width-l_offset)] = '\0';
	  fprintf(stderr,
		  "Line %d: Line too long after formatting (%d) - Truncated\n",
		  line_num-lines-1+i, l_width);
	} /* string too long after formatting */
      }

      for (i = j = (l_mlines-lines)/2, k = 0; i < (j+lines); i++, k++) {
	p = (char *) ((int)row[i] + cur_col*(l_width+l_hgap) + l_offset);
	for (l = 0; rec[k][l]; l++)
	  p[l] = rec[k][l];
      } /* fill n lines for one label */

    } /* for one row */

  f:
    if (!started) {
      /* Output initial string or escape sequence to printer */
      started = T;
      if (l_istring != (char *)NULL)
	fprintf(outfile, l_istring);
      if (l_ifill) {
	int kk;
	/* fills n rows for manual adjustment purposes */
	for (i = 0; i < l_ifill; row_count++, i++) {

	  if ((row_count < l_lrows)||(!l_lrows))
	    kk = 0;
	  else {
	    kk = l_foffs;
	    row_count = 0;
	  }

	  for (; kk < l_mlines; putc('\n', outfile), kk++) {
	    for (j = 0; j < l_cross; j++) {
	      for (k = l_poffs; k < l_width; k++)
		putc('#', outfile);		/* fill one line of a label */
	      if (j < l_cross-1)
		for (k = 0; k < l_hgap; k++)
		  fprintf(outfile," ");		/* make horizontal gaps     */
	    } /* for one line in label */
	  } /* for one row of label */
	  for (k = 0; k < l_vgap; putc('\n', outfile), k++);
	} /* for n rows */
      } /* if need to adjust */
    } /* if initial output */

    /* print row to output file */
    if ((row_count < l_lrows)||(!l_lrows))
      i = 0;				/* print entire label */
    else {
      /* if there's a form offset, the first row of labels maybe truncated */
      i = l_foffs;
      row_count = 0;
    }

    for (k = (l_width*l_cross+l_hgap*(l_cross-1)); i < l_mlines; i++) {
      /* set an absolute length for output */
      row[i][k] = '\0';

      /* if there's a page offset, we better look out */
      fprintf(outfile,"%s\n", &row[i][l_poffs]);
    }

    /* fill vertical gap */
    for (i = 0; i < l_vgap; i++)
      putc('\n', outfile);
    row_count++;
  } /* process entire file - while() */

 d:
  if (infile != stdin)
    fclose(infile);
  if (outfile != stdout)
    fclose(outfile);

  fprintf(stderr,"\n%s: Formatting Complete\n",argv[0]);
} /* main() */
SHAR_EOF
echo shar: extracting "'labels.l'" '(3284 characters)'
if test -f 'labels.l'
then
	echo shar: over-writing existing file "'labels.l'"
fi
cat << \SHAR_EOF > 'labels.l'
%{
/*			       -- LABELS.L --

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@                                                                           @@
@@                       Mailing List Label Formatter                        @@
@@                    Lexical Analyzer for Form Parsing                      @@
@@                      (C) Copyright 1987 by Joe Chen                       @@
@@                           All Rights Reserved                             @@
@@                                                                           @@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

You may freely distribute this software to others.  But there are
few rules you must follow:

1. You don't profit from it.  You may however ask for minimal fees to
   cover shipping and handling.

2. This program is copyrighted, meaning you may not modify or enhance
   this software and market it.  You may make changes to suit your
   local needs.  Any enhancements are welcomed.

3. Please honor the author by not removing or replacing his name from
   the source codes.


Feel free to contact me if you have any questions.

					Joe Chen

---------------------------------------------------------------------------
Phones at work: (213) 743-5363, (213) 743-5935; at home: (818) 571-5304
University Computing Services, University of Southern California
UUCP: {sdcrdcf, uscvax}!oberon!wasat!joec
ARPA: joec at wasat.usc.edu, joec at ecla.usc.edu
---------------------------------------------------------------------------

Program created by Joe Chen - Jul 24, 1987

*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

*/

#include <stdio.h>

#ifdef UNIX
#include "y.tab.h"
#else
#include "ytab.h"
#endif

int value, line_no = 1;
extern char *form;
%}

cr		\n
tab		\t
space		" "
white_space	({space}|{tab})
spcs		{white_space}*

digit		[0-9]
number		{digit}+

letter		[A-Za-z_]
word		{letter}({letter}|{digit})*

%%

{spcs}			;

#.*			;

{cr}			{	line_no++;		}

initial			{	return(_INITIAL);	}

string			{	return(_KSTRING);	}

fill			{	return(_FILL);		}

form			{	return(_FORM);		}

page			{	return(_PAGE);		}

width			{	return(_WIDTH);		}

hgap			{	return(_HGAP);		}

vgap			{	return(_VGAP);		}

columns			{	return(_COLUMNS);	}

column			{	return(_COLUMNS);	}

format			{	return(_FORMAT);	}

offset			{	return(_OFFSET);	}

of			{	return(_OF);		}

for			{	return(_OF);		}

lines			{	return(_LINES);		}

line			{	return(_LINE);		}

rows			{	return(_ROWS);		}

is			{	return(_IS);		}

","			{	return(_DELIM);		}

";"			{	return(_DELIM);		}

"="			{	return(_ASSIGN);	}

":"			{	return(_ASSIGN);	}


{number}		{
				value = atoi(yytext);
				return(_VALUE);
			}

{word}			{	return(_WORD);		}


\"[^\"]*\"		{	return(_STRING);	}

.			{
			  fprintf(stderr,
			    "Line %d in %s: Illegal Character: '%s'\n",
				  line_no, yytext);
			}

%%

/****************************************************************************
  yywrap() [Public function] - lex's function when EOF is detected from yyin

  parameters:	none

  exit flags:	1		Done matching tokens from input file
****************************************************************************/

yywrap()
{
  return 1;
} /* yywrap() */
SHAR_EOF
echo shar: extracting "'labels.y'" '(5508 characters)'
if test -f 'labels.y'
then
	echo shar: over-writing existing file "'labels.y'"
fi
cat << \SHAR_EOF > 'labels.y'
%{
/*			       -- LABELS.Y --

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@                                                                           @@
@@                       Mailing List Label Formatter                        @@
@@                     Syntax Analyzer for Form Parsing                      @@
@@                      (C) Copyright 1987 by Joe Chen                       @@
@@                           All Rights Reserved                             @@
@@                                                                           @@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

You may freely distribute this software to others.  But there are
few rules you must follow:

1. You don't profit from it.  You may however ask for minimal fees to
   cover shipping and handling.

2. This program is copyrighted, meaning you may not modify or enhance
   this software and market it.  You may make changes to suit your
   local needs.  Any enhancements are welcomed.

3. Please honor the author by not removing or replacing his name from
   the source codes.


Feel free to contact me if you have any questions.

					Joe Chen

---------------------------------------------------------------------------
Phones at work: (213) 743-5363, (213) 743-5935; at home: (818) 571-5304
University Computing Services, University of Southern California
UUCP: {sdcrdcf, uscvax}!oberon!wasat!joec
ARPA: joec at wasat.usc.edu, joec at ecla.usc.edu
---------------------------------------------------------------------------

Program created by Joe Chen - Jul 24, 1987

*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

*/
#include <stdio.h>

extern char *malloc(), *realloc();

extern int value, line_no;
extern char yytext[], **fmt_arry, *l_istring;
extern int l_width, l_hgap, l_vgap, l_columns, l_mlines, l_offset, l_cross;
extern int l_ifill, l_foffs, l_poffs, l_lrows;
extern FILE *form;
%}

%union {
  int vars;
};

%token _INITIAL
%token _KSTRING
%token _FORM
%token _PAGE
%token _FILL
%token _WIDTH
%token _HGAP
%token _VGAP
%token _COLUMNS
%token _LINES
%token _ROWS
%token _OFFSET
%token _FORMAT
%token _OF
%token _LINE
%token _IS
%token _ASSIGN
%token _DELIM
%token _VALUE
%token _STRING
%token _WORD

%type <vars> variable

%%

cmd		: stmts
		;

stmts		: stmts delim stmt
		| stmt
		;

delim		: _DELIM delim
		|
		;

stmt		: param_stmt_val
		| fmt_stmt
		| init_stmt
		;

param_stmt_val	: variable is _VALUE
		{
		  switch($1) {
		  case _WIDTH:
		    l_width = value;
		    break;
		  case _HGAP:
		    l_hgap = value;
		    break;
		  case _VGAP:
		    l_vgap = value;
		    break;
		  case _COLUMNS:
		    l_cross = value;
		    break;
		  case _LINES: {
		    if (l_mlines < value) {
		      int i;		/* need to adjust format buffer */
		      fmt_arry=(char **)realloc(fmt_arry,value*sizeof(char *));
		      if (fmt_arry == (char **)NULL)
			goto e;
		      /* add new format lines */
		      for (i=l_mlines; i < value; i++) {
			fmt_arry[i] = malloc(l_width+1);
			if (fmt_arry[i] == (char *)NULL)
			  goto e;
			(void) strcpy(fmt_arry[i], "%s");
		      }
		    } /* adjust the format buffer */
		    l_mlines = value;
		    break;
		  e:
		    fprintf(stderr,"Fatal Error: Insufficient Memory\n");
		    exit(-1);
		  }
		  case _OFFSET:
		    /* label column offset */
		    l_offset = value;
		    break;
		  case _FORM:
		    /* form offset value */
		    l_foffs = value;
		    break;
		  case _PAGE:
		    /* page offset value */
		    l_poffs = value;
		    break;
		  case _ROWS:
		    /* rows per label */
		    l_lrows = value;
		    break;
		  } /* set various variables */
		}
		;

variable	: _WIDTH
		{
		  $$=_WIDTH;
		}
		| _HGAP
		{
		  $$=_HGAP;
		}
		| _VGAP
		{
		  $$=_VGAP;
		}
		| _COLUMNS
		{
		  $$=_COLUMNS;
		}
		| _LINES
		{
		  $$=_LINES;
		}
		| _LINE
		{
		  $$=_LINES;
		}
		| _ROWS
		{
		  $$=_ROWS;
		}
		| _OFFSET
		{
		  $$=_OFFSET;
		}
		| _FORM _OFFSET
		{
		  $$=_FORM;
		}
		| _PAGE _OFFSET
		{
		  $$=_PAGE;
		}
		| _WORD
		{
		  $$=0;
		  fprintf(stderr,"Line %d in %s: Unknown variable: %s\n",
			  line_no, form, yytext);
		}
		;

fmt_stmt	: _FORMAT _OF line _VALUE is _STRING
		{
		  if (value > l_mlines) {
		    fprintf(stderr,"Line %d in %s: Line Number Execeeded ",
			    line_no, form);
		    fprintf(stderr,"Maximum (%d); Format Ignored\n",l_mlines);
		  }
		  else {
		    /* supercede format */
		    (void) strcpy(fmt_arry[value-1], &yytext[1]);
		    /* remove quotes */
		    fmt_arry[value-1][strlen(fmt_arry[value-1])-1] = '\0';
		  }
		}
		;

init_stmt	: _INITIAL _KSTRING is _STRING
		{
		  if ((l_istring = malloc(strlen(yytext))) == (char *)NULL) {
		    fprintf(stderr,"Fatal Error: Insufficient Memory\n");
		    exit(-1);
		  }
		  /* remove the quotations */
		  (void) strcpy(l_istring, &yytext[1]);
		  l_istring[strlen(l_istring)-1] = '\0';
		}
		| _INITIAL _FILL is _VALUE
		{
		  /* initial fill value */
		  l_ifill = value;
		}
		;

line		: _LINE
		|
		;

is		: _IS
		| _ASSIGN
		|
		;

%%

/****************************************************************************
  yyerror() [Public function] - Yacc error trap function

  parameters:	s		Error message from yacc's LR driver

  exit flags:	none
****************************************************************************/

yyerror(s)
     char *s;
{
  if (strcmp(s, "syntax error"))
    fprintf(stderr,"Line %d in %s: %s\n",line_no,form,s);
} /* yyerror() */

SHAR_EOF
echo shar: extracting "'labels.man'" '(7344 characters)'
if test -f 'labels.man'
then
	echo shar: over-writing existing file "'labels.man'"
fi
cat << \SHAR_EOF > 'labels.man'
.pl 60
.\" Man Page for LABELS
.TH LABELS 1 "2 Aug 1987"
.SH NAME
labels \- produce formatted output for label printing
.SH SYNOPSIS
.B LNAME
[
.B \-f <form>
] 
[
.B <input file>
[
.B <output file>
] ]
.br
.B LNAME
.B \-h
.br
.B LNAME
.B \-l
.SH DESCRIPTION
.B LNAME accepts a raw
.B <input file>
and produces a formatted
.B <output file>.
If
.B <output file>
is not specified, then formatted output will
go to standard output
.I (stdout).
If
.B <input file>
is not specified in addition to the omission of
.B <output file>,
then input will be taken from the standard input
.I (stdin).
.sp
.\" describe the format of the input file
The format of an input file is simple and straight forward.  The
following is an example:
.nf
.sp
        John Doe
        123 Main St.
        City of DownUnder, AU 9999
        .
        Susan Smith
        Label Products, Inc.
        1000 Broadway Blvd.
        Space City, DD 00001
        .
.sp
.fi
A period "." must be placed at the beginning of a new line
after completing data input for each label.
.\" describe the format of label forms
.sp
By default,
.B LNAME
prepares the output for USC-UCC standard label form (1083), which is 32 characters
wide and 11 lines long per label, and 3 labels across. The optional
.B \-f <form>
can be used to overcome the default label format.  A directory
of preset label formats can be listed by specifying the
.B \-l
parameter alone.  If a desired form is not available, the user
can define one, like the following:
.sp
.nf
        # Standard label size (32 char x 6 lines, 3 columns)

        width = 32, lines = 6, columns = 3

        # other alignments
        hgap = 4, vgap = 1, offset = 4
.fi
.sp
A line that starts with # is treated as a comment.  Various
parameters can be set by specifying the variable name, like
.I width,
and assign it to the a value, like 32.  The above form file
defines the following:
.sp
.nf
        \- Each label has maximum width of 32 characters (width=32).
        \- Each label has maximum lines of 6 (lines=6).
        \- Format for 3 labels across (columns=3).
        \- Set horizontal gap between labels to be 4 characters (hgap=4).
        \- Set vertical gap between labels to be 1 line (vgap=1).
        \- Set data offset to be 4 characters from the left (offset=4).
.fi
.sp
You may also use the
.B :
or a space in the place of
.B =.
In other words, you can use any one of the variations:
.sp
.nf
        width:32        width 32        or width = 32.
.fi
.sp
Also, you may use a semicolon in place of a comma.
.sp
There is a naming convention for such file.  Each form definition
file
.B must
have the extension
.B .lbl
and must be in the current directory in order for it to be
recognized by
.B LNAME.
For example, the above definition may be placed in
a file called
.I myform.lbl.
To format labels from an input file
.I labels.in
and save the formatted output to
.I labels.out
using
.I myform.lbl,
type:
.sp
.nf
        LNAME -f myform labels.in labels.out
.fi
.sp
.B LNAME
will search for
.I myform
from a set of preset forms.  If such form does not exist, it
will then search in user's current directory.
.sp
Many people prefer to print mailing list labels with a "To:"
attached to the first line, and the rest of the lines must
align properly.  The user may create the following form:
.sp
.nf
        # Standard label size (32 char x 6 lines, 3 columns) with "To:"

        lines:6; width:32
        columns:2

        # other alignments
        hgap:4; vgap:1; offset:0

        # format definition for each of the 6 lines in a label
        format for line 1 is " To: %s"
        format for line 2 is "     %s"
        format for line 3 is "     %s"
        format for line 4 is "     %s"
        format for line 5 is "     %s"
        format for line 6 is "     %s"
.fi
.sp
If the sample input data file on page 1 is used, along with the above
form, this is the result:
.nf
.sp
-----------------------------------------------------------------------
|                                |   |                                |
| To: John Doe                   |   | To: Susan Smith                |
|     123 Main St.               |   |     Label Products, Inc.       |
|     City of DownUnder, AU 9999 |   |     1000 Broadway Blvd.        |
|                                |   |     Space City, DD 00001       |
|                                |   |                                |
-----------------------------------------------------------------------
.fi
.sp
The string
.I %s
is substituted with the input data.  Thus by default, each line has
the format of "%s".
If "To:" is desired to be added to the first line, like to above example,
then the format for the first line can be defined as "To: %s".
.sp
Customized printing of labels can also be done.  Initial string of
escape sequences can be sent via the
.I "initial string"
command:
.sp
.nf
        initial string = "^[B"
.fi
.sp
where
.I "^[B"
could be an escape sequence to enable bold printing on a particular
printer.
.sp
Another useful parameter is
.I "initial fill."
Before printing labels on a line printer, the operator often needs
to re-adjust the printer.  By printing the dimensions of the label
forms, the printer can be adjusted properly before printing the
first valid label.  To fill ten rows of labels initially, the
following parameter is specified in the form definition:
.sp
.nf
        initial fill = 10
.fi
.sp
Finally, if you need a quick reminder about the program parameters,
a brief command usage can be reviewed by specifying the
.I \-h
parameter alone.
.SH LIMITATIONS
LNAME assumes that the printer to be used is using a font with
constant widths for all characters.
.SH FILES
PROGDIR/LNAME
.sp
All .lbl files in LIBDIR are predefined label form definitions.
A listing can be obtained by specifying the
.B \-l
parameter.
.SH DIAGNOSIS
Below is a list of common error messages and their descriptions.
.sp
.B "Line xxxx: Line too long (x) - Truncated"
.sp
Length of the input data at line xxxx is longer than the maximum
defined width of x.  The rest of the input on that line is truncated.
.sp
.B "Line xxxx: Line too long after formatting (x) - Truncated"
.sp
The length of the formatted string at line xxxx is longer than the
maximum width permitted, which is x.
.sp
.B "Line xxxx: Lines Exceeded Limit (x) - Ignoring the Rest"
.sp
Number of lines per label is greater than the maximum of x lines.
.sp
.B LNAME
.B ": Cannot read form:"
.I form
.sp
The form you specified with
.B \-f
is not found.  The file name must have the extension .lbl.
.sp
.B LNAME
.B ": Error reading form:"
.I form
.sp
User defined form has improper syntax, which resulted in parsing
errors.  Various parsing errors are also displayed.
.sp
.B LNAME
.B ": Too many arguments"
.sp
Too many arguments specified.  A brief program usage is displayed.
.sp
.B LNAME
.B ": Cannot Open Directory:"
.I dir
.sp
Cannot list preset forms because the directory containing form files
does not exist.
.sp
.SH BUGS
None discovered so far. Please report any bugs you may find
to the author by electronic mail.
.SH AUTHOR
.nf
Joe S. Chen, Consultant, UNIX, VMS, and TOPS-20
Phones: (213) 743-5363, (213) 743-5935
University Computing Services, University of Southern California
UUCP: {sdcrdcf, uscvax}!oberon!wasat!joec
ARPA: joec at wasat.usc.edu, joec at ecla.usc.edu
.fi
SHAR_EOF
echo shar: extracting "'1083.lbl'" '(259 characters)'
if test -f '1083.lbl'
then
	echo shar: over-writing existing file "'1083.lbl'"
fi
cat << \SHAR_EOF > '1083.lbl'
# Form 1083 (32 chars x 11 lines, 3 cols) for line printing
# Last changed: 8/3/87 by Joe. Chen, USC-UCC

initial fill = 12		# our operators need a lot of time to adjust!

width = 32, lines = 11, columns = 3

# other alignments
hgap = 4; vgap = 1, offset = 4
SHAR_EOF
echo shar: extracting "'1083f.lbl'" '(548 characters)'
if test -f '1083f.lbl'
then
	echo shar: over-writing existing file "'1083f.lbl'"
fi
cat << \SHAR_EOF > '1083f.lbl'
# Same as Form 1083 with "From:"
# Last changed: 8/3/87 by Joe. Chen, USC-UCC

initial fill = 12

width = 32, lines = 11, columns = 3

# other alignments
hgap = 4, vgap = 1, offset = 0

# Reformat each line
format of line  1 : "From: %s"
format of line  2 : "      %s"
format of line  3 : "      %s"
format of line  4 : "      %s"
format of line  5 : "      %s"
format of line  6 : "      %s"
format of line  7 : "      %s"
format of line  8 : "      %s"
format of line  9 : "      %s"
format of line 10 : "      %s"
format of line 11 : "      %s"
SHAR_EOF
echo shar: extracting "'1083t.lbl'" '(524 characters)'
if test -f '1083t.lbl'
then
	echo shar: over-writing existing file "'1083t.lbl'"
fi
cat << \SHAR_EOF > '1083t.lbl'
# Same as Form 1083 with "To:"
# Last changed: 8/3/87 by Joe. Chen, USC-UCC

initial fill : 12

width : 32, lines : 11, columns : 3

# other alignments
hgap : 4, vgap : 1, offset : 1

# Reformat each line
format of line  1 : "To: %s"
format of line  2 : "    %s"
format of line  3 : "    %s"
format of line  4 : "    %s"
format of line  5 : "    %s"
format of line  6 : "    %s"
format of line  7 : "    %s"
format of line  8 : "    %s"
format of line  9 : "    %s"
format of line 10 : "    %s"
format of line 11 : "    %s"
SHAR_EOF
echo shar: extracting "'6080.lbl'" '(209 characters)'
if test -f '6080.lbl'
then
	echo shar: over-writing existing file "'6080.lbl'"
fi
cat << \SHAR_EOF > '6080.lbl'
# Xerox 6080 (34 chars x 6 lines, 3 cols) for laser printing
# Last changed: 8/2/87 by Joe. Chen, USC-UCC

initial fill = 0

width = 34, lines = 6, columns = 3

# other alignments
hgap 0; vgap : 0, offset = 2
SHAR_EOF
echo shar: extracting "'6080f.lbl'" '(391 characters)'
if test -f '6080f.lbl'
then
	echo shar: over-writing existing file "'6080f.lbl'"
fi
cat << \SHAR_EOF > '6080f.lbl'
# Same as Form 6080 with "From:"
# Last changed: 8/2/87 by Joe. Chen, USC-UCC

initial fill = 0

width = 34, lines = 6, columns = 3

# other alignments
hgap = 0, vgap = 0, offset = 0

# Reformat each line
format of line  1 : "From: %s"
format of line  2 : "      %s"
format of line  3 : "      %s"
format of line  4 : "      %s"
format of line  5 : "      %s"
format of line  6 : "      %s"
SHAR_EOF
echo shar: extracting "'6080t.lbl'" '(377 characters)'
if test -f '6080t.lbl'
then
	echo shar: over-writing existing file "'6080t.lbl'"
fi
cat << \SHAR_EOF > '6080t.lbl'
# Same as Form 1083 with "To:"
# Last changed: 8/2/87 by Joe. Chen, USC-UCC

initial fill : 0

width : 34, lines : 6, columns : 3

# other alignments
hgap : 0, vgap : 0, offset : 0

# Reformat each line
format of line  1 : "To: %s"
format of line  2 : "    %s"
format of line  3 : "    %s"
format of line  4 : "    %s"
format of line  5 : "    %s"
format of line  6 : "    %s"
SHAR_EOF
echo shar: extracting "'6083.lbl'" '(209 characters)'
if test -f '6083.lbl'
then
	echo shar: over-writing existing file "'6083.lbl'"
fi
cat << \SHAR_EOF > '6083.lbl'
# Xerox 6083 (34 chars x 9 lines, 3 cols) for laser printing
# Last changed: 8/3/87 by Joe. Chen, USC-UCC

initial fill = 0

width = 34, lines = 9, columns = 3

# other alignments
hgap 0; vgap : 0, offset = 2
SHAR_EOF
echo shar: extracting "'6083f.lbl'" '(453 characters)'
if test -f '6083f.lbl'
then
	echo shar: over-writing existing file "'6083f.lbl'"
fi
cat << \SHAR_EOF > '6083f.lbl'
# Same as Form 6083 with "From:"
# Last changed: 8/2/87 by Joe. Chen, USC-UCC

initial fill = 0

width = 34, lines = 9, columns = 3

# other alignments
hgap = 0, vgap = 0, offset = 0

# Reformat each line
format of line  1 : "From: %s"
format of line  2 : "      %s"
format of line  3 : "      %s"
format of line  4 : "      %s"
format of line  5 : "      %s"
format of line  6 : "      %s"
format of line  7 : "      %s"
format of line  8 : "      %s"
SHAR_EOF
echo shar: extracting "'6083t.lbl'" '(435 characters)'
if test -f '6083t.lbl'
then
	echo shar: over-writing existing file "'6083t.lbl'"
fi
cat << \SHAR_EOF > '6083t.lbl'
# Same as Form 6083 with "To:"
# Last changed: 8/2/87 by Joe. Chen, USC-UCC

initial fill : 0

width : 34, lines : 9, columns : 3

# other alignments
hgap : 0, vgap : 0, offset : 0

# Reformat each line
format of line  1 : "To: %s"
format of line  2 : "    %s"
format of line  3 : "    %s"
format of line  4 : "    %s"
format of line  5 : "    %s"
format of line  6 : "    %s"
format of line  7 : "    %s"
format of line  8 : "    %s"
SHAR_EOF
#	End of shell archive
exit 0
-- 
For comp.sources.unix stuff, mail to sources at uunet.uu.net.



More information about the Comp.sources.unix mailing list