[comp.os.minix] nrchbar

rosenkra@convex1.convex.com (William Rosencranz) (08/06/90)

---
This is nrchbar, a program to insert changebars in nroff/troff files based
on differences between 2 versions of the file. It works with the nroff I
just posted, v1.10p3. IT WILL ONLY WORK WITH THE NEW NROFF since it needs
the .mc command. I HAVE NOT TESTED THIS WITH MINIX but it works fine under
BSD unix. there are 3 makefiles (sheesh!) so copy Makefile.mnx to Makefile
or use make -f ...

You will need diff(1) to use this program. If you do not have diff, skip
this program. It will be useless. If you do have diff, and have nroff up
to v1.10 p3, then this could be a very handy program, especially with
minix which changes hourly :-). it works with both the -man and -ms
macro packages i just posted.

The version of nrchbar I used was a unix version and had a popen(3) call
to pipe the output of diff to a stream. I have simulated the popen call
in the TOS version. See source file for more info. Note that diff command is
hardwired to /bin/diff (unix,minix) and c:\bin\diff.ttp (TOS) so if your
diff is not that, you need to change the DIFFPROG define in the source.

Enjoy...

-bill rosenkranz
rosenkra%c1yankee@convex.com

------------------------------- cut here ---------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# If this archive is complete, you will see the following message at the end:
#		"End of shell archive."
#
# Contents:
#   MANIFEST README Makefile.mnx Makefile.tos Makefile.unx
#   nrchbar.1 nrchbar.c nrchbar.man tests.uu
#
# Wrapped by rosenkra%c1yankee@convex.com on Sun Aug  5 14:45:12 1990
#
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f MANIFEST -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MANIFEST\"
else
echo shar: Extracting \"MANIFEST\" \(501 characters\)
sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
X-rw-r--r--  1 rosenkra        0 Aug  5 14:44 MANIFEST
X-rw-r--r--  1 rosenkra     1848 Aug  5 14:17 Makefile.mnx
X-rw-r--r--  1 rosenkra     1803 Aug  5 14:02 Makefile.tos
X-rw-r--r--  1 rosenkra     1718 Aug  5 14:07 Makefile.unx
X-rw-r--r--  1 rosenkra     3197 Aug  5 14:42 README
X-rw-r--r--  1 rosenkra     2720 Aug  5 13:43 nrchbar.1
X-rw-r--r--  1 rosenkra    15234 Aug  5 14:00 nrchbar.c
X-rw-r--r--  1 rosenkra     2747 Aug  5 14:26 nrchbar.man
X-rw-r--r--  1 rosenkra     9887 Aug  5 14:21 tests.uu
END_OF_MANIFEST
if test 501 -ne `wc -c <MANIFEST`; then
    echo shar: \"MANIFEST\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(3197 characters\)
sed "s/^X//" >README <<'END_OF_README'
Xbelow is the original README for nrchbar. the install procedure is about
Xthe same, but look at the Makefile to be sure. this is in the archives for
Xcomp.sources.misc, circa 1987.
X
Xthis is a handy little program to put changebars in nroff-style documents,
Xdirectly in the nroff source, based on the diffs between two nroff documents.
Xin invokes /bin/diff directly or will read diff output from stdin. i have
Xused it successfully (under TOS) to generate a large-ish -ms paper with
Xchangebars (about 20 pages).
X
Xi have tested this under TOS and 4.{23}BSD with no problems. i have not
Xtested it under MINIX. it should work fine with the nroff i just posted
X(v1.10p3) and WILL NOT WORK WITH THE ORIGINAL NROFF (0.99) since it did
Xnot have the .mc command. if you do get errors, check the output from
Xminix diff(1) to see that it conforms to real unix. you also need the
Xpopen(3) call to invoke /bin/diff from within nrchbar. if not, you can
Xread the diffs from stdin. see the manpage. look at the makefile for
Xproper target locations for the manpage and executable before you "make
Xinstall". build the executable with "make -f Makefile.mnx all".
X
Xnrchbar.man is nroff source. nrchbar.1 is output of nroff.
X
Xuudecode the tests.uu to get a compressed shar file. unpack this and
Xread the file TESTING. test with:
X
X	% nrchbar f1.man f2.man > f12.man
X	% nroff -man f12.man
X
Xlet me know if there are any problems...
X
X-bill
Xrosenkra%c1yankee@convex.com
X
X----------------------------------------------------------------------------
X
XThe "nrchbar" program effectively inserts n/troff-style change bar commands
Xinto files which are (presumably) n/troff source.  For more information,
Xconsult the man page.
X
XTo install "nrchbar":
X
X1)	Inspect "Makefile" for proper destinations (currently,
X	"/usr/local/bin" for the binary and "/usr/man/manl" for the man
X	page).  Correct these if necessary.  If "diff" on your system isn't
X	"/bin/diff", you'll also need to modify the "DIFFPROG" #define in
X	"nrchbar.c".  "nrchbar" assumes "getopt" is present, so you'll need
X	to contact your friendly neighborhood comp.sources.unix archive if it
X	isn't.
X
X2)	In the source directory:
X		
X		% make install
X
X3)	If everything goes well, still in the source directory:
X
X		% make clean
X
XI claim that this program was written entirely by me, entitling me (with the
Xapproval of my management) to release it into the public domain, which I now
Xdo.  However, I make no warrantees, either express or implied, on "nrchbar"
Xor its associated files and I do not assume responsiblity for any damages
Xresulting from its installation or use.
X
XThe software has only been compiled and tested on a Sun 3/50, but I don't
Xexpect any major problems on other UNIX machines, including System V.
X
XIn spite of the disclaimer above, I'd like to hear about bugs and/or feature
Xrequests.
X
XAcknowledgements and thanks to Robert Reed of Tektronix, who wrote the
Xoriginal shell script; and to Jeff Hahs, Ron Lunde, Charlie Mills, and Bill
Xden Beste of TSSI for encouragement, ideas, and testing.
X
X	- Bob Lewis
X	  Test Systems Strategies, Inc.
X	  8205 SW Creekside Pl.
X	  Beaverton, OR  97005
X	  (503) 643-9281
X
X	  ...!tektronix!tessi!bobl   or   bobl@tessi.UUCP
X
END_OF_README
if test 3197 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile.mnx -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile.mnx\"
else
echo shar: Extracting \"Makefile.mnx\" \(1848 characters\)
sed "s/^X//" >Makefile.mnx <<'END_OF_Makefile.mnx'
X# makefile for nrchbar (minix)
X#
X# date:    Wed Jul 25 12:45:16 1990
X# version: 1.4
X#
X# NOTE: change SECT, BINDIR and MANDIR as you see fit...
X#
XSECT		= l
XO		= s
XEXT		=
XTARGET		= nrchbar$(EXT)
XMANPAGE		= nrchbar.$(SECT)
XCATPAGE		= nrchbar.cat
XMANSRC		= nrchbar.man
XARCFILE		= nrchbar.arc
XSHARFILE	= nrchbar.shr
XUUEFILE		= nrchbar.uue
XHEADERS		=
XSRCS		= $(HEADERS) nrchbar.c
XOTHERS		= README Makefile* $(MANSRC) tests.uu
XDISTFILES	= $(OTHERS) $(SRCS)
XOBJS		= nrchbar.$O
XCFLAGS		= -D_MINIX -D_POSIX_SOURCE
XLDFLAGS		= -i
XLIBS		=
X# you may need to change these locations...
XBINDIR		= /usr/local/bin
XMANDIR		= /usr/man/man1
XRUNPARM		= f1.man f2.man
XRUNOUT		= >test.out
X
X
X# directions...
X#
Xdirections:
X		@echo type "make all" to built $(TARGET)
X		@echo type "make install" to built/install $(TARGET)
X		@echo type "make test" to test $(TARGET)
X		@echo type "make clean" to remove objects
X		@echo type "make clobber" to remove objects and $(TARGET)
X		@echo type "make arc" to make source archive $(ARCFILE)
X		@echo type "make shar" to make source shar file $(SHARFILE)
X		@echo type "make uue" to make uuencoded $(TARGET) $(UUEFILE)
X
X
X# main target...
X#
Xall:		$(TARGET)
X
X$(TARGET):	$(OBJS)
X		$(CC) $(LDFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
X
X
X# manpage (nothing to do, really)
X#
X
X
X# to run it...
X#
Xtest:		$(TARGET)
X		$(TARGET) $(RUNPARM) $(RUNOUT)
X
X
X# to install it...
X#
Xinstall:	install_bin install_man
X
Xinstall_bin:	$(TARGET)
X		cp $(TARGET) $(BINDIR)/$(TARGET)
X
Xinstall_man:
X		cp $(MANSRC) $(MANDIR)/$(MANPAGE)
X
X
X# others...
X#
Xclean:
X		rm $(OBJS) errs $(CATPAGE)
X
Xclobber:	clean
X		rm $(TARGET) $(MANPAGE)
X
Xarc:
X		$(ARC) a $(ARCFILE) $(DISTFILES)
X		@echo done making $(ARCFILE)
X
Xuue:
X		$(UUENCODE) $(TARGET)
X		@echo done making $(UUEFILE)
X
Xshar:
X		$(SHAR) $(DISTFILES) >$(SHARFILE)
X		@echo done making $(SHARFILE)
X
X
X# dependencies...
X#
Xnrchbar.o:	nrchbar.c 
X
END_OF_Makefile.mnx
if test 1848 -ne `wc -c <Makefile.mnx`; then
    echo shar: \"Makefile.mnx\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile.tos -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile.tos\"
else
echo shar: Extracting \"Makefile.tos\" \(1803 characters\)
sed "s/^X//" >Makefile.tos <<'END_OF_Makefile.tos'
X# makefile for nrchbar
X#
X# date:    Wed Jul 25 12:45:16 1990
X# version: 1.4
X#
XSECT		= 1
XTARGET		= nrchbar.ttp
XMANPAGE		= nrchbar.$(SECT)
XCATPAGE		= nrchbar.cat
XMANSRC		= nrchbar.man
XARCFILE		= nrchbar.arc
XSHARFILE	= nrchbar.shr
XUUEFILE		= nrchbar.uue
XHEADERS		=
XSRCS		= $(HEADERS) nrchbar.c
XOTHERS		= readme makefile $(MANSRC)
XDISTFILES	= $(OTHERS) $(SRCS)
XOBJS		= nrchbar.o
XCFLAGS		=
XLDFLAGS		= -s -nf
XLIBS		=
XBINDIR		= c:\bin
XMANDIR		= c:\man\man1
XRUNPARM		= test1.man test2.man
XRUNOUT		= >test.out
X
X
X# directions...
X#
Xdirections:
X		@echo type "make all" to built $(TARGET)
X		@echo type "make install" to built/install $(TARGET)
X		@echo type "make test" to test $(TARGET)
X		@echo type "make clean" to remove objects
X		@echo type "make clobber" to remove objects and $(TARGET)
X		@echo type "make arc" to make source archive $(ARCFILE)
X		@echo type "make shar" to make source shar file $(SHARFILE)
X		@echo type "make uue" to make uuencoded $(TARGET) $(UUEFILE)
X
X
X# main target...
X#
Xall:		$(TARGET)
X
X$(TARGET):	$(OBJS)
X		$(CC) $(LDFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
X
X
X# manpage (use built-in .man.cat rule)...
X#
Xmanpage:	$(MANPAGE)
X
X$(MANPAGE):	$(CATPAGE)
X		entab $(CATPAGE) $(MANPAGE)
X
X$(CATPAGE):	$(MANSRC)
X
X
X
X# to run it...
X#
Xtest:		$(TARGET)
X		$(TARGET) $(RUNPARM) $(RUNOUT)
X
X
X# to install it...
X#
Xinstall:	install_bin install_man
X
Xinstall_bin:	$(TARGET)
X		cp $(TARGET) $(BINDIR)\$(TARGET)
X
Xinstall_man:	$(MANPAGE)
X		cp $(MANPAGE) $(MANDIR)\$(MANPAGE)
X
X
X# others...
X#
Xclean:
X		rm $(OBJS) errs $(CATPAGE)
X
Xclobber:	clean
X		rm $(TARGET) $(MANPAGE)
X
Xarc:
X		$(ARC) a $(ARCFILE) $(DISTFILES)
X		@echo done making $(ARCFILE)
X
Xuue:
X		$(UUENCODE) $(TARGET)
X		@echo done making $(UUEFILE)
X
Xshar:
X		$(SHAR) $(DISTFILES) >$(SHARFILE)
X		@echo done making $(SHARFILE)
X
X
X# dependencies...
X#
Xnrchbar.o:	nrchbar.c 
X
END_OF_Makefile.tos
if test 1803 -ne `wc -c <Makefile.tos`; then
    echo shar: \"Makefile.tos\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile.unx -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile.unx\"
else
echo shar: Extracting \"Makefile.unx\" \(1718 characters\)
sed "s/^X//" >Makefile.unx <<'END_OF_Makefile.unx'
X# makefile for nrchbar (unix)
X#
X# date:    Wed Jul 25 12:45:16 1990
X# version: 1.4
X#
XSECT		= 1
XTARGET		= nrchbar
XMANPAGE		= nrchbar.$(SECT)
XCATPAGE		= nrchbar.cat
XMANSRC		= nrchbar.man
XARCFILE		= nrchbar.arc
XSHARFILE	= nrchbar.shr
XUUEFILE		= nrchbar.uue
XHEADERS		=
XSRCS		= $(HEADERS) nrchbar.c
XOTHERS		= README Makefile* $(MANSRC) tests.uue
XDISTFILES	= $(OTHERS) $(SRCS)
XOBJS		= nrchbar.o
XCFLAGS		=
XLDFLAGS		=
XLIBS		=
XBINDIR		= /sales/rosenkra/bin
XMANDIR		= /sales/rosenkra/man/man1
XRUNPARM		= test1.man test2.man
XRUNOUT		= >test.out
X
X
X# directions...
X#
Xdirections:
X		@echo type "make all" to built $(TARGET)
X		@echo type "make install" to built/install $(TARGET)
X		@echo type "make test" to test $(TARGET)
X		@echo type "make clean" to remove objects
X		@echo type "make clobber" to remove objects and $(TARGET)
X		@echo type "make arc" to make source archive $(ARCFILE)
X		@echo type "make shar" to make source shar file $(SHARFILE)
X		@echo type "make uue" to make uuencoded $(TARGET) $(UUEFILE)
X
X
X# main target...
X#
Xall:		$(TARGET)
X
X$(TARGET):	$(OBJS)
X		$(CC) $(LDFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
X
X
X# manpage (nothing to do, really)
X#
X
X
X# to run it...
X#
Xtest:		$(TARGET)
X		$(TARGET) $(RUNPARM) $(RUNOUT)
X
X
X# to install it...
X#
Xinstall:	install_bin install_man
X
Xinstall_bin:	$(TARGET)
X		cp $(TARGET) $(BINDIR)/$(TARGET)
X
Xinstall_man:
X		cp $(MANSRC) $(MANDIR)/$(MANPAGE)
X
X
X# others...
X#
Xclean:
X		rm $(OBJS) errs $(CATPAGE)
X
Xclobber:	clean
X		rm $(TARGET) $(MANPAGE)
X
Xarc:
X		$(ARC) a $(ARCFILE) $(DISTFILES)
X		@echo done making $(ARCFILE)
X
Xuue:
X		$(UUENCODE) $(TARGET)
X		@echo done making $(UUEFILE)
X
Xshar:
X		$(SHAR) $(DISTFILES) >$(SHARFILE)
X		@echo done making $(SHARFILE)
X
X
X# dependencies...
X#
Xnrchbar.o:	nrchbar.c 
X
END_OF_Makefile.unx
if test 1718 -ne `wc -c <Makefile.unx`; then
    echo shar: \"Makefile.unx\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f nrchbar.1 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"nrchbar.1\"
else
echo shar: Extracting \"nrchbar.1\" \(2720 characters\)
sed "s/^X//" >nrchbar.1 <<'END_OF_nrchbar.1'
XNAME  
X	nrchbar	- insert n/troff-style change bars in a	file 
X
XSYNOPSIS  
X	nrchbar	[-a] [-b] [-d] [oldfile] newfile 
X
XOPTIONS	 
X	-a  	Put  change  bars  around  all changed sections, even if
X		they consist of	nothing	but *roff commands.  
X
X	-b  	Do not insert breaks after changed sections.  
X
X	-d  	Show  deleted  text  by	 preceding  it	with  "[["   and
X		following it with "]]".	 
X
XDESCRIPTION  
X	Nrchbar	 inserts  commands  suitable  for  nroff(1)  or	troff(1)
X	(hereafter,  "*roff")  to   produce   "change	bars"	denoting
X	differences between oldfile and	newfile.  It sends the result to 
X	standard output.  
X
X	If oldfile is defaulted, nrchbar assumes that its standard input 
X	will  contain differences between oldfile and newfile in diff(1)
X	format.	 If oldfile is given, then nrchbar will	run  diff(1)  on
X	both files and use the output generated.  
X
X	By  default,  nrchbar  ignores	changes	 to  sections containing
X	nothing	but *roff commands, which  it  takes  to  be  any  lines
X	beginning with ".".  You can override this with	the -a option.	
X
X	Nrchbar	 inserts  *roff	 ".mc"	commands  to  provide the change
X	bars.  This will place a character to  the  far	 right	of  each
X	changed	section.   This	character is a "+" for added sections, a
X	"|" for	modified sections, and a "-" for deleted sections.  
X
X	By default, the	text of	deleted	sections does  not  appear,  but
X	the  -d	 option	will cause it to be inserted, surrounded by "[["
X	and "]]".  
X
X	Also by	default, nrchbar puts a	break (".br") command after each 
X	changed	section.   This	 is  the  only	way  to	 guarantee  that
X	deletions and  small changes get flagged.  The -b option directs
X	the program not	to insert these	breaks.	 It makes the text  look
X	more like *roffed newfile, but means that some change bars won't 
X	appear where they should.  
X
XSEE ALSO  
X	nroff(1), troff(1) 
X
XBUGS  
X	"." is	always	assumed	to denote *roff	commands.  Nrchbar knows
X	nothing	about the ".cc"	command.  
X
X	The need for the -b hack would disappear if there were a way  to
X	tell  *roff  "Turn  off	 the change bar	character at immediately
X	after you put out this one.".  A horizontal ".wh", perhaps?  
X
X	The  .mc  command   doesn't   always   work,   especially   with
X	diversions.  This is actually a	*roff bug, but you ought to know 
X	about it.  
X
X	Nrchbar	may  mess  up  tables, lists, or displays.  For	a really
X	polished change	bar document, you may want to  edit  its  output
X	before sending it to *roff.  
X
XAUTHOR 
X	Unix version by:
X	
X	Bob Lewis
X	Test Systems Strategies, Inc.
X	8205 SW	Creekside Pl.
X	Beaverton, OR  97005
X	(503) 643-9281
X	...!tektronix!tessi!bobl or bobl@tessi.UUCP
X	
X	Atari ST version by:
X	
X	Bill Rosenkranz
X	rosenkra%c1yankee@convex.com
X
END_OF_nrchbar.1
if test 2720 -ne `wc -c <nrchbar.1`; then
    echo shar: \"nrchbar.1\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f nrchbar.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"nrchbar.c\"
else
echo shar: Extracting \"nrchbar.c\" \(15234 characters\)
sed "s/^X//" >nrchbar.c <<'END_OF_nrchbar.c'
X#undef NO_PIPE		/* def to eliminate diff (read from stdin instead) */
X#undef USE_MALLOC	/* def to malloc space for diff command line */
X
X/*
X *	nrchbar - insert nroff change bar commands into a file
X *
X *	note: original unix version uses popen ("diff file1 file2", "r")
X *	to get diff output. i wrote an ST version of popen(3) to get the
X *	job done. uses system(3) and stdio.
X *
X *	note: to make this, you need getopt(3), diff(1), system(3), popen(3)
X *	and pclose(3) (simulated here for ST), and ungetc(3S). if you use the
X *	popen provided, DON'T #define USE_MALLOC!
X */
X
X#include <stdio.h>
X
X#ifdef ALCYON
X# define DIFFPROG	"c:\\bin\\diff.ttp"
X#else
X# define DIFFPROG	"/bin/diff"
X#endif
X
Xtypedef	int bool;
X
X#ifdef TRUE
X# undef TRUE
X#endif
X#ifdef FALSE
X# undef FALSE
X#endif
X#define	TRUE		1
X#define	FALSE		0
X
X#define	ADD		'a'
X#define	CHANGE		'c'
X#define	DELETE		'd'
X
Xtypedef	struct
X{
X	int	lnOldFrom;
X	int	lnOldTo;
X	int	cmd;
X	int	lnNewFrom;
X	int	lnNewTo;
X}		diffdescr;
X
Xchar	       *progname;
X#ifdef ALCYON
Xchar	       *_progname = "nrchbar";
X#endif
Xbool		flagAll	= FALSE;
Xbool		flagBreakAfter = TRUE;
Xbool		flagDelete = FALSE;
Xbool		debugging = FALSE;
X#ifdef ALCYON
Xchar	       *version = "nrchbar 1.4 (TOS) 90/07/25 04:51:58 rosenkra";
X#else
X# ifdef _MINIX
Xchar	       *version = "nrchbar 1.4 (MINIX) 90/07/25 04:51:58 rosenkra";
X# else
Xchar	       *version = "nrchbar 1.4 (unix) 90/07/25 04:51:58 rosenkra";
X# endif
X#endif
X
X/*
X *	forward	declarations
X */
XFILE	       *fopenOrElse ();
Xvoid		nrchbar	();
Xvoid		skipLinesOrElse	();
Xvoid		userErr	();
Xvoid		beginChbar ();
Xbool		cpLin ();
Xvoid		cpLinOrElse ();
Xvoid		endChbar ();
Xint		getDiff ();
Xbool		isRoffCmd ();
Xvoid		markDiff ();
X#ifndef NO_PIPE
XFILE	       *pipeDiffs ();
X#endif
X
X
X#ifndef	lint
X# ifdef ALCYON
Xchar   *rcsid = "$Header: nrchbar.c,v 1.4(TOS) 90/07/25 04:51:58 rosenkra Exp $";
X# else
Xchar   *rcsid = "$Header: nrchbar.c,v 1.3 87/03/31 16:33:16 bobl Exp $";
X# endif
X#endif
X
X
X
X/*------------------------------*/
X/*	main			*/
X/*------------------------------*/
Xmain (argc, argv)
Xint	argc;
Xchar   *argv[];
X{
X	extern int	optind;
X	extern int	getopt ();
X
X	int		c;
X	FILE	       *fpDiff,
X		       *fpNew;
X	char	       *fnOld,
X		       *fnNew;
X
X#ifdef ALCYON
X	progname = _progname;
X#else
X	progname = argv[0];
X#endif
X
X	while ((c = getopt (argc, argv, "abdv")) != EOF)
X	{
X		switch (c)
X		{
X		case 'a':			/* all changes */
X			flagAll	= TRUE;
X			break;
X
X		case 'b':			/* no breaks after changes */
X			flagBreakAfter = FALSE;
X			break;
X
X		case 'd':			/* show deleted sections */
X			flagDelete = TRUE;
X			break;
X
X		case 'v':
X			printf ("%s\n", version);
X			exit (0);
X
X		case '?':
X		default:
X			fprintf	(stderr, "%s: unknown flag \"-%c\"\n",
X				progname, (int) c);
X			fprintf	(stderr,
X				"Usage: %s [-a] [-b] [-d] [oldfile] newfile\n",
X				progname);
X			exit (1);
X			break;
X		}
X	}
X
X
X	/* 
X	 *   Depending on the number of files on the command line.
X	 */
X	switch (argc - optind)
X	{
X	case 1:	
X		fpDiff = stdin;
X		fnNew  = argv[optind++];
X		fpNew  = fopenOrElse (fnNew, "r");
X		break;
X
X	case 2:	
X#ifdef NO_PIPE
X		fprintf	(stderr,
X			"%s: sorry, no pipes. use stdin.\n", progname);
X		exit (1);
X#else
X		fnOld  = argv[optind++];
X		fnNew  = argv[optind++];
X		fpDiff = pipeDiffs (fnOld, fnNew);
X		fpNew  = fopenOrElse (fnNew, "r");
X#endif
X		break;
X
X	default: 
X		fprintf	(stderr,
X			"Usage: %s [-a] [-b] [-d] [oldfile] newfile\n",
X			progname);
X		exit (1);
X	}
X
X	/* 
X	 *   Now the real work begins.
X	 */
X	nrchbar	(fpDiff, fpNew);
X
X	/*
X	 *   clean up and exit...
X	 */
X	if (fpDiff != stdin)
X		pclose (fpDiff);
X
X	exit (0);
X}
X
X
X
X/*------------------------------*/
X/*	beginChbar		*/
X/*------------------------------*/
Xvoid beginChbar	(chMark)
Xint	chMark;			/* in: use this	character */
X{
X
X/*
X *	beginChbar -- put out a	*roff command to begin a change	bar
X */
X
X/*!!!	if (flagBreakAfter)
X		printf (".br\n");
X*/
X	printf (".mc %c\n", chMark);
X	return;
X}
X
X
X
X/*------------------------------*/
X/*	cpLin			*/
X/*------------------------------*/
Xbool cpLin (nLn, nSkip, fpFrom)
Xint	nLn;			/* in: copy this many lines ...	*/
Xint	nSkip;			/* in: ... skipping this many characters
X					   at the start	of each	one ...	*/
XFILE   *fpFrom;			/* in: ... from	this file to stdout */
X{
X
X/*
X *	cpLin -- copy a given number of lines from one file to standard
X *	output
X */
X
X	int	ch;
X	int	iSkip;
X
X	while (nLn-- > 0)
X	{
X		for (iSkip = 0;	iSkip <	nSkip; iSkip++)
X		{
X			if (getc (fpFrom) == EOF)
X				return (FALSE);
X		}
X		do
X		{
X			ch = getc (fpFrom);
X			if (ch == EOF)
X				return (FALSE);
X			putchar	(ch);
X
X		} while	(ch != '\n');
X	}
X
X	return (TRUE);
X}
X
X
X
X/*------------------------------*/
X/*	cpLinOrElse		*/
X/*------------------------------*/
Xvoid cpLinOrElse (nLn, nSkip, fpFrom)
Xint	nLn;			/* in: copy this many lines ...	*/
Xint	nSkip;			/* in: ... skipping this many characters
X					   at the start	of each	one ...	*/
XFILE   *fpFrom;			/* in: ... from	this file to stdout */
X{
X
X/*
X *	cpLinOrElse -- copy a given number of lines from one file to
X *	standard output; exit if unable
X */
X
X	if (!cpLin (nLn, nSkip, fpFrom))
X		userErr	("unexpected EOF");	/* exits! */
X	return;
X}
X
X
X
X/*------------------------------*/
X/*	endChbar		*/
X/*------------------------------*/
Xvoid endChbar ()
X{
X
X/*
X *	endChbar -- put	out a *roff command to end a change bar	section
X */
X
X	/*
X	 *   make sure the previous change bar is visible
X	 */
X	if (flagBreakAfter)
X		printf (".br\n");
X
X	printf (".mc\n");
X
X	return;
X}
X
X
X
X/*------------------------------*/
X/*	fopenOrElse		*/
X/*------------------------------*/
XFILE *fopenOrElse (fname, type)
Xchar   *fname;			/* in: file name to open */
Xchar   *type;			/* in: way in which to open fname */
X{
X
X/*
X *	fopenOrElse -- open a file or else exit	with an	error message
X */
X
X	FILE   *fp;
X
X
X	fp = fopen (fname, type);
X
X	if (fp == (FILE *) NULL)
X	{
X		fprintf	(stderr, "%s: can't open \"%s\" for mode \"%s\"\n",
X			progname, fname, type);
X		exit (1);
X	}
X	return (fp);
X}
X
X
X
X/*------------------------------*/
X/*	getDiff			*/
X/*------------------------------*/
X
X#define	EOA		0
X#define	START_ACCUM	1
X#define	ACCUM		2
X#define	SETOLDFROM	3
X#define	SETOLDTO	4
X#define	SETCMD		5
X#define	SETNEWFROM	6
X#define	SETNEWTO	7
X#define	MXN_ACTION	8
X
Xstruct FSM
X{
X	int	state;
X	char   *trig;
X	int	stateNext;
X	int	action[MXN_ACTION];
X};
X
Xstruct FSM     *fsmCur;
Xstruct FSM	fsm[16] = 
X{
X/*	state	trig	      stateNext action */
X
X	{0,	"0123456789",	1,	{START_ACCUM, EOA} },
X	{1,	"0123456789",	1,	{ACCUM, EOA} },
X	{1,	",",		2,	{SETOLDFROM, EOA} },
X	{1,	"acd",		4,	{SETOLDFROM, SETOLDTO, SETCMD, EOA} },
X	{2,	"123456789",	3,	{START_ACCUM, EOA} },
X	{3,	"0123456789",	3,	{ACCUM, EOA} },
X	{3,	"acd",		4,	{SETOLDTO, SETCMD, EOA} },
X	{4,	"0123456789",	5,	{START_ACCUM, EOA} },
X	{5,	"0123456789",	5,	{ACCUM, EOA} },
X	{5,	",",		6,	{SETNEWFROM, EOA} },
X	{5,	"\n",		-1,	{SETNEWFROM, SETNEWTO, EOA} },
X	{6,	"123456789",	7,	{START_ACCUM, EOA} },
X	{7,	"0123456789",	7,	{ACCUM, EOA} },
X	{7,	"\n",		-1,	{SETNEWTO, EOA} },
X	{-1,	0L,		-1,	{EOA} }		/* sentinal */
X};
X
Xint getDiff (fp, ddscr)
XFILE	       *fp;		/* in: file containing "diff" output */
Xdiffdescr      *ddscr;		/* in: a diff section descriptor */
X{
X
X/*
X *	getDiff	-- get a "diff"	description line
X *
X *	diff output looks like this:
X *
X *		12 c 12				range
X *		< (hereafter, "*roff")		first file
X *		---				seperator
X *		> (hereafter, "_roff")		second file
X *
X *	range can be like these:
X *
X *		n l n
X *		n,n l n
X *		n l n,n
X *
X *	where n is a number, l is a letter (a, d, c)
X */
X
X
X	extern char    *index ();
X
X	int		stateCur = 0;
X	int		ch,
X			accum =	0;
X	int	       *action;
X	int		len = 0;
X
X	do
X	{
X		/*
X		 *   get a char, skip spaces
X		 */
XGET_A_CHAR:
X		ch = getc (fp);
X		if (ch == EOF)
X			return (EOF);
X		if (ch == ' ' || ch == '\t')
X			goto GET_A_CHAR;
X
X
X		/*
X		 *   set current fsm to first one
X		 */
X		len++;
X		fsmCur = (struct FSM *) &fsm[0];
X
X		/*
X		 *   find a state where ch is in trig. don't go past the end
X		 */
X		while (fsmCur->state != -1
X		&& (fsmCur->state != stateCur
X		|| index (fsmCur->trig, (char) ch) == (char *) NULL))
X		{
X			if (debugging == TRUE)
X				fprintf (stderr,
X				"state loop: fsmCur->state = %d, stateCur = %d, index (|%s|, |%c|)\n",
X				fsmCur->state, stateCur, fsmCur->trig, (int) ch);
X
X			fsmCur++;
X		}
X
X		/*
X		 *   if we reached the end, there was no match (error)
X		 */
X		if (fsmCur->state == -1)
X			userErr	("illegal syntax in 'diff' output");
X
X		/*
X		 *   do the work for each action in this state
X		 */
X		for (action = fsmCur->action; *action != EOA; action++)
X		{
X			if (debugging == TRUE)
X				fprintf (stderr,
X					"action loop: action = %d\n", action);
X
X			switch (*action)
X			{
X			case START_ACCUM:	/* get a number */
X				accum =	ch - '0';
X				break;
X
X			case ACCUM:		/* continue on number */
X				accum =	10 * accum + (ch - '0');
X				break;
X
X			case SETCMD:		/* a command (a,c,d) */
X				ddscr->cmd = ch;
X				break;
X
X			case SETNEWFROM:	/* new, range start */
X				ddscr->lnNewFrom = accum;
X				break;
X
X			case SETNEWTO:		/* new, range end */
X				ddscr->lnNewTo = accum;
X				break;
X
X			case SETOLDFROM:	/* old, range start */
X				ddscr->lnOldFrom = accum;
X				break;
X
X			case SETOLDTO: 		/* old, range end */
X				ddscr->lnOldTo = accum;
X				break;
X			}
X		}
X
X		/*
X		 *   set current state to next state and continue reading
X		 *   the diff "command"
X		 */
X		stateCur = fsmCur->stateNext;
X
X	} while	(stateCur != -1);
X
X	return (len);
X}
X
X
X
X/*------------------------------*/
X/*	isRoffCmd		*/
X/*------------------------------*/
Xbool isRoffCmd (fp)
XFILE   *fp;			/* in: file to examine for *roff command */
X{
X
X/*
X *	isRoffCmd -- return TRUE iff the next line begins with a *roff
X *	command
X */
X
X	int	ch;
X
X	if ((ch	= getc (fp)) ==	EOF)
X		userErr	("unexpected EOF");
X
X	ungetc (ch, fp);
X
X	return (ch == '.');		/* don't know about ".cc" command */
X}
X
X
X
X/*------------------------------*/
X/*	markDiff		*/
X/*------------------------------*/
Xvoid markDiff (ddscr, fpDiff, fpNew)
Xdiffdescr      *ddscr;		/* in: descriptor of the differing sections */
XFILE	       *fpDiff;		/* in: the diff	file */
XFILE	       *fpNew;		/* in: the new file */
X{
X
X/*
X *	markDiff -- note a changed section of a	file; return # of lines
X *	copied from fpNew
X */
X
X	int	nLnNew;
X	int	nLnOld;
X	int	nLnNewCopy;
X
X	nLnNew     = ddscr->lnNewTo - ddscr->lnNewFrom + 1;
X	nLnOld     = ddscr->lnOldTo - ddscr->lnOldFrom + 1;
X	nLnNewCopy = nLnNew;
X
X	switch (ddscr->cmd)
X	{
X	case ADD: 
X		if (!flagAll)
X		{
X			while (nLnNewCopy > 0 && isRoffCmd (fpNew))
X			{
X				cpLinOrElse (1, 0, fpNew);
X				nLnNewCopy--;
X			}
X		}
X		if (nLnNewCopy > 0)
X		{
X			beginChbar ('+');
X			cpLinOrElse (nLnNewCopy, 0, fpNew);
X			endChbar ();
X		}
X		skipLinesOrElse	(nLnNew, fpDiff);
X		return;
X
X	case CHANGE: 
X		if (!flagAll)
X		{
X			while (nLnNewCopy > 0 && isRoffCmd (fpNew))
X			{
X				cpLinOrElse (1, 0, fpNew);
X				nLnNewCopy--;
X			}
X		}
X		if (nLnNewCopy > 0)
X		{
X			beginChbar ('|');
X			cpLinOrElse (nLnNewCopy, 0, fpNew);
X			endChbar ();
X		}
X		skipLinesOrElse	(nLnNew	+ 1 + nLnOld, fpDiff);
X					/* allow for "---" in diff */
X		return;
X
X	case DELETE: 
X		beginChbar ('-');
X		if (flagDelete)
X		{
X			putchar	('[');
X			putchar	('[');
X			putchar	('\n');
X			cpLinOrElse (nLnOld, 2, fpDiff);
X					/* strip off the "< " */
X			putchar	(']');
X			putchar	(']');
X			putchar	('\n');
X		}
X		else
X			skipLinesOrElse	(nLnOld, fpDiff);
X		endChbar ();
X		return;
X	}
X}
X
X
X
X/*------------------------------*/
X/*	nrchbar			*/
X/*------------------------------*/
Xvoid nrchbar (fpDiff, fpNew)
XFILE   *fpDiff;			/* in: diff file */
XFILE   *fpNew;			/* in: original	file */
X{
X
X/*
X *	nrchbar	-- produce *roff change	bar file
X */
X
X	int		lnNew =	1;
X	int		nLines;
X	diffdescr	ddscr;
X
X	/*
X	 *   read diff "commands"
X	 */
X	while (getDiff (fpDiff,	&ddscr)	!= EOF)
X	{
X		/*
X		 *   line count from command
X		 */
X		nLines = ddscr.lnNewFrom - lnNew;
X		if (ddscr.cmd == DELETE)
X			nLines++;
X
X		/*
X		 *   copy the lines from new file
X		 */
X		cpLinOrElse (nLines, 0, fpNew);
X
X		/*
X		 *   add any change bars...
X		 */
X		markDiff (&ddscr, fpDiff, fpNew);
X		lnNew =	ddscr.lnNewTo +	1;
X	}
X
X	/*
X	 *   last line...
X	 */
X	while (cpLin (1, 0, fpNew))
X		;
X
X	return;
X}
X
X
X
X#ifndef NO_PIPE
X
X/*------------------------------*/
X/*	pipeDiffs		*/
X/*------------------------------*/
XFILE *pipeDiffs	(fnOld,	fnNew)
Xchar   *fnOld;			/* in: old file	name */
Xchar   *fnNew;			/* in: new file	name */
X{
X
X/*
X *	pipeDiffs -- return a pipe with	a diff run on the other	end
X */
X
X	FILE   *popen ();
X	char   *malloc ();
X
X	char   *cmd;
X	FILE   *fpPipe;
X#ifndef USE_MALLOC
X	char	cmdbuf[1000];		/* need more space to append ">file" */
X#endif
X
X	/*
X	 *   make up the diff command...
X	 */
X#ifdef USE_MALLOC
X	cmd = (char *) malloc ((unsigned int) (strlen (DIFFPROG) + 1 + strlen (fnOld) +	1 + strlen (fnNew) + 1));
X#else
X	cmd = &cmdbuf[0];
X#endif
X	sprintf	(cmd, "%s %s %s", DIFFPROG, fnOld, fnNew);
X
X	/*
X	 *   do it with a pipe
X	 */
X	fpPipe = popen (cmd, "r");
X	if (fpPipe == (FILE *) NULL)
X	{
X		fprintf	(stderr, "%s: can't open pipe for \"%s\"\n",
X				progname, cmd);
X		exit (1);
X	}
X
X	/*
X	 *   clean up...
X	 */
X#ifdef USE_MALLOC
X	free (cmd);
X#endif
X
X	/*
X	 *   return descriptor of pipe
X	 */
X	return (fpPipe);
X}
X
X
X
X#ifdef ALCYON
X
X/*------------------------------*/
X/*	popen			*/
X/*------------------------------*/
X
X#define PIPE_FILE	"__NRCH__.PIP"
X
XFILE *popen (cmd, mode)
Xchar   *cmd;
Xchar   *mode;
X{
X
X/*
X *	simulate pipes on the ST (alcyon). pipe output of cmd to file.
X *	return file descriptor of fopen'd file as the pipe descriptor.
X *
X *	pclose should close the descriptor, then delete the pipe file...
X *	note: abnormal exits to nrchbar may cause the pipe file to linger.
X */
X
X	FILE   *fp;
X
X	/*
X	 *   only read pipes needed here...
X	 */
X	if (*mode == 'r')
X	{
X		/*
X		 *   delete the "pipe"
X		 */
X		unlink (PIPE_FILE);
X
X		/*
X		 *   cat an output redirect to the command
X		 */
X		strcat (cmd, " >");
X		strcat (cmd, PIPE_FILE);
X
X		/*
X		 *   do it! we could be more selective here: if diff returns
X		 *   0, there were no diffs so there should be no need to
X		 *   do this.
X		 */
X		system (cmd);
X
X		/*
X		 *   now open the "pipe" as a file and return its descriptor
X		 *   don't need to check as NULL is a valid return...
X		 */
X		fp = fopen (PIPE_FILE, "r");
X
X		return (fp);
X	}
X	else
X	{
X		fprintf (stderr, "%s: sorry, no support for write pipes!\n", progname);
X		return ((FILE *) 0);
X	}
X}
X
X
X
X/*------------------------------*/
X/*	pclose			*/
X/*------------------------------*/
Xpclose (fp)
XFILE   *fp;
X{
X	/*
X	 *   close the pipe (open file). delete the pipe file
X	 */
X	close (fp);
X	unlink (PIPE_FILE);
X}
X
X#endif /*ALCYON*/
X
X#endif /*!NO_PIPE*/
X
X
X
X/*------------------------------*/
X/*	skipLinesOrElse		*/
X/*------------------------------*/
Xvoid skipLinesOrElse (nLn, fp)
Xint	nLn;			/* in: skip this many lines ...	*/
XFILE   *fp;			/* in: ... in this file	*/
X{
X
X/*
X *	skipLinesOrElse	-- skip	a given	number of lines	in a file; exit	if
X *	errors
X */
X
X	int	ch;
X
X	while (nLn-- > 0)
X	{
X		do
X		{
X			if ((ch	= getc (fp)) ==	EOF)
X				userErr	("unexpected EOF");
X
X#ifdef ALCYON
X		} while	(ch != '\n' && ch != '\r');
X#else
X		} while	(ch != '\n');
X#endif
X	}
X	return;
X}
X
X
X
X/*------------------------------*/
X/*	userErr			*/
X/*------------------------------*/
Xvoid userErr (msg)
Xchar   *msg;
X{
X
X/*
X *	userErr	-- note	an error and politely exude
X */
X
X	fprintf	(stderr, "%s: %s\n", progname, msg);
X	exit (1);
X}
X
END_OF_nrchbar.c
if test 15234 -ne `wc -c <nrchbar.c`; then
    echo shar: \"nrchbar.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f nrchbar.man -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"nrchbar.man\"
else
echo shar: Extracting \"nrchbar.man\" \(2747 characters\)
sed "s/^X//" >nrchbar.man <<'END_OF_nrchbar.man'
X.\" $Header: nrchbar.1,v 1.2 87/03/31 16:33:02 bobl Exp $
X.TH NRCHBAR 1
X.SH NAME
Xnrchbar \- insert n/troff-style change bars in a file
X.SH SYNOPSIS
Xnrchbar [\-a] [\-b] [\-d] [oldfile] newfile
X.SH OPTIONS
X.IP \-a
XPut change bars around all changed sections, even if they consist of
Xnothing but *roff commands.
X.IP \-b
XDo not insert breaks after changed sections.
X.IP \-d
XShow deleted text by preceding it with "[[" and following it with "]]".
X.SH DESCRIPTION
XNrchbar
Xinserts commands suitable for
Xnroff(1)
Xor
Xtroff(1)
X(hereafter, "*roff") to produce "change bars" denoting
Xdifferences between oldfile and newfile.
XIt sends the result to standard output.
X.LP
XIf
Xoldfile
Xis defaulted,
Xnrchbar
Xassumes that its standard
Xinput will contain differences between
Xoldfile
Xand
Xnewfile
Xin
Xdiff(1)
Xformat.
XIf
Xoldfile
Xis given, then
Xnrchbar
Xwill run
Xdiff(1)
Xon both files and use the output generated.
X.LP
XBy default, nrchbar ignores changes to sections containing nothing
Xbut *roff commands, which it takes to be any lines beginning with "\.".
XYou can override this with the \-a option.
X.LP
XNrchbar inserts *roff ".mc" commands to provide the change
Xbars.
XThis will place a character to the far right of each changed section.
XThis character is a "+" for added sections, a "|" for
Xmodified sections, and a "-" for deleted sections.
X.LP
XBy default, the text of deleted sections does not appear, but the
X\-d option will cause it to be inserted, surrounded by "[[" and "]]".
X.LP
XAlso by default, nrchbar puts a break (".br") command after each
Xchanged section.
XThis is the only way to guarantee that deletions and small changes
Xget flagged.
XThe \-b option directs the program not to insert these breaks.
XIt makes the text look more like *roffed
Xnewfile, but means that some change bars won't appear where
Xthey should.
X.\".SH PRONUNCIATION
X.\"NERCH-bar
X.\".SH ETYMOLOGY
X.\"NRoff CHange BAR
X.SH "SEE ALSO"
Xnroff(1), troff(1)
X.SH BUGS
X"." is always assumed to denote *roff commands.
XNrchbar knows nothing about the ".cc" command.
X.LP
XThe need for the \-b hack would disappear if there were a way
Xto tell *roff "Turn off the change bar character at
Ximmediately after you put out this one.".
XA horizontal "\.wh", perhaps?
X.LP
XThe \.mc command doesn't always work, especially with diversions.
XThis is actually a *roff bug, but you ought to know about it.
X.LP
XNrchbar may mess up tables, lists, or displays.
XFor a really polished change bar document, you may want to edit
Xits output before sending it to *roff.
X.SH AUTHOR
X.nf
XUnix version by:
X
XBob Lewis
XTest Systems Strategies, Inc.
X8205 SW Creekside Pl.
XBeaverton, OR  97005
X(503) 643-9281
X\&...!tektronix!tessi!bobl or bobl@tessi.UUCP
X
XMINIX and Atari ST version by:
X
XBill Rosenkranz
Xrosenkra%c1yankee@convex.com
X.fi
END_OF_nrchbar.man
if test 2747 -ne `wc -c <nrchbar.man`; then
    echo shar: \"nrchbar.man\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f tests.uu -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"tests.uu\"
else
echo shar: Extracting \"tests.uu\" \(9887 characters\)
sed "s/^X//" >tests.uu <<'END_OF_tests.uu'
Xbegin 644 tests.shar.Z
XM'YV0(T*`>"$FC9L7<]`H&`&""IHT<T!`!!$&1,(R;-A0E#/FH9TR+D"`D%*F
XMS9N/%-WDH?/0S1D08LJ8>2.G#`B6$]D8+,/B)IHR;D#4<0,GS)@U"R72@9G'
XM8A@[!E^F66J0SAN*(,RD86,SC!LR-_/`B0I"1,*L6\N("-GPZLDR<N[(F6JS
XM#!Z(=*(F36+&Y\0P'#W:G#CF31LX7.GP!)'G31T0=[9JG%/&)DN;,S.^B>P2
XM1)LR<^:$.=-UZ6400,GH6)@@@8@B7T&\Z7LQX\:.:3ZZ$+$PZ9`W;A0'G[.:
XMH4@J1:902>+D2-88+<S(<$$F35\ST*6[:./U>?3ICI=BW]Y=.W<WO1E>D1,&
XM#IPR8,4TE?.&LILU[(&,89_'1>$VL@4UQ5`@!%''2R#4`$(,-.@00PXZP'##
XM@CGD`$-O4`1!!1(]$&20#B_4,8<<'KH!HH@DUC&&&"#L@!H><-"T5(8;*F#=
XM3:`M%5U#R2W7'`@M5"0""7O$T(<(((300UDMC(&DBY<%I8!(971T54*`Z0#"
XM%9*!X,8;2[TE1PMRT?4B7F1IQ14(7(B`G'+,'=&F`AA11J>5%J&1)0A%X$$'
XM>V/DU5F;;_HH)Y)<H$####F`T!%@1BDFQQQ<I*``96"9]8(76+SP`I(^%!HG
XM"#SP<$(13A#QQ1-&?"%J<R<H@(5#F+VA&6=2923BGV$H%E%%OH;9EQN!B0$8
XM"C&DX(*LLAZ1&U!H<44<LU@D,-YYK8E`4QIG(*FF32A4=%Y1I%E:K7E>9>M&
XM&7=XFQ8(*)A4G5;P/>>"#.;*2L0;9.$T+1:R)E""E\4"!B18UY8WW7D@^(#=
XM=^2A!S`6-%$K,`CS7A=#Q%DMW)W#V4TW;\`#$]N1L7(<W#''/#RLW;P-N^RQ
XMQ+*2MBY[OF*U[AV>>46N39&QY*B>+I6!<D0HR!RQL@3/IE5G4T$V%1JK37PQ
XML4X#R;#2#(,,<7C4PD$?&2J"YI--.V=%$W=T*`;6N*,!/?707I%V-+Q*AZ>L
XM`JBJRJJK/<9I8U_!@K!HHRVL"P(8=XP!I.,\O'H$&%#^A)Y(5.*)I1Q:$AIX
XM<VT*1911:]0;-!J0T=?9'&GH448("FB55&JR]25FF8*^U%&52,E^8^$[*@US
XMD&41:2222C+I9(MG2YDY&E?JR?F677X9YD=CXE[777/D'JU-;0IOW9QUEG$G
XM]'GNV2>O@9(5?LC4C8\HLC+8$`/=@$I*J:68EC7'IIWZ5,S@![-2G2I5JVJ5
XM^,P0*RS$0`:.6I`,9,4#>/VD)F$P@Z1Z(@(5T,<,9A!!"FYR%;&]@6QCL(D(
XM'E4TF`!F#D@B`U#`I!<LM."&LO*!!>%2A@QNL"Q?^&`(1V@5$)@0A2ID(6E<
XM.*D8SC!WLHJ!@BH2`QNP0`8QR&%;<-0]+9H,#2C3HK^,"*DSL`<.J--31&("
XMK3"0089D6!86=)B$I6`P(TU1HY?`U)*7%)$,5SD="*!W!R\6+&5WH,D:YM`3
XM->P**\&2HPY=P`0HR$H&,XB@#')`09C482D>S-I_SD,&1D+F(1U1RDW"4+J(
XM%#$F*6F*3M:UQC*<P2!N(,OI9'7#%FA1#)\$01!%:1A2FO(.J$1=U.C`2K.]
XMLBLJ`<$LS1:36[HAEYW9)19D,"''S6`&G73"(27B!LK(@0X1"24(R[*=Y8W2
XM*Z4DH1'I`Q49GHUN1>,E#N<(`G&>S&`&,2<ZA2E$=K;!G<6$IRM+2,\TV/,T
XM2C0?%FAP/\?1X`:=K&//6GE/Q?A)FF]XPQH\0Q.;Z*1T(%"G&>"C3U_R4Z/<
XMX>AI/+H4-H1TI":IB333@-)A@I"E$Z4!"RZ*,<-Q$@L5=,$4D``"*$CA"4ZH
XM@A.&D`0-)0&JX2R"%(:`A!:$$:D@4"I3BT"%+#3A"4QXPA&R$$XI9(VK=;.)
XM$((@!5G5H*()`B=8K=='3X*RH._\RASDV$LO\I$LP%R*3_L2V%+*L0:-<IS]
XM.KD6)/V%#7<(0QY^%9HZ?`8L?WRB353JJ(0*EK#[U&%E)?(KS&J6LW/P;+U"
XM:SV;++:T;3"F'&V02<G6H)-%5(QM2.NF.L@A*%F#*-&6B#+\10HN%*%#2\5X
XM%>%JY+;%/6[M"/<3?#+78(_*'W1[)2L;X"""-[@06!TRD;\$J@YAP"-62`O,
XM,_0DL8QQC&P.A`;37&4-7^)9&,00'J6@UJ4Z9&]$W$L'^,JW(K>M[WV#V9C'
XM..8,_94G@#=#$0('<RIRO`$$'7<#&G1R*A$)#QR"&9.9Z-0^U8&:?U,JQ`-K
XM$<7[I<.*E]+BDEHD-619YE46NZR^)?`+"QP<%Y?R0/L!27&,<UR32+5`RC5O
XM2IBK$OHVUSD1+#!T0RG*44PW-[D`YR6L<QWL9,<0VLU&-MC#'5EV=Y38I4')
XMP-,8Q!A&O"$5Z4A)6I((FO2DYH$`RUJ.WIZX9!OKP1DN9)J+8L[4O32]ZWU[
XM]@KYV&"G1*=O>NO+G_N\#+_SA"Y1];M!-Z7WW$E5ZE+UTA2G/`4JKG7'@$;^
XMFZW=T$`7A(X$2.BA#*?W192Y(`8LL,."[@4"'-S@!3"8P0MF<+\JZN";$8(@
XM@<6@D3[!`00DD)4+-M3/K2)AKE)84%F0)`)VLQNJ3&!.$7B#!;'V,PA-*(*L
XMBFTP+K2`G`+UT@O^Y+06="\/:XHH$Q<<E(I\2]Q+!<$4LN"$)T!A"DF8PK['
XMN05_AZ$+(.BX5T$N<C*0W%9D^!;(=_;P>D><",D9@A22`(7E8!4+_@0C0,L)
XMEX$V-B*QG<J`U^3BC3L-6>:J&!8(#D*DB_N@(."#K%!PP1YJ$"X<7*P(Y7G$
XMLI5%X4=SHO5JZ`(QR.'I8Y!5QGCHAA36D@YWJ`QRV9#R=\'32^SZEAPU"F-7
XM=K<FL67#C+L'3\"`1<6?E",E+5EOJ*]`5E2H;HXV_L^S+_TA$2D*>\S8GC2&
XMH99M?"-\]F[''LI7CWSMUU4`*36A$9+R.D>D(DWIR.Y!,D>*KZ2XS8YV6?%%
XM-G3_%FLQ)I,PU$'P\.D)OU/V^=A^QN^]4@K0F?D5P\O*(#N6FFT*$YPP&`1C
XMUEEI3=I.S3+`7>[`K_N:[L[RM%Q?8AES.A9<S+;<,UX(39&A&8PO>.6/DUM?
XM`GC>Y4Q74B5Y`1P1P7W,9!!DD7HN@791)ROX=5L_UQ/(E`:IM$S-M%`P`4VR
XMM!.U9$W8]!+:5':6UTZR4EERE`7Z-0;=(29S\5"8UWJH<QH>)QMP<(!N8'\0
XM*'4X]W\\=TX1@5WMA"0_QW4-)8,V$5&[=X(')8$O)$<*IGT:@1A&T17.%2C0
XM%5S=M7\I,Q<8)BRH812H$U%@01GM`QQ2.(/AU6K#)R0KX"TT01&B=X8&F`8(
XMV!-"P@=R:'GR8AUI4"]HJ(.F='="T@)]2'R)(8AWB(`\B`7X1WS[=WQTT!,S
XM91=B*$.+:(=I6$X8\P9FXVCM\1Z`,6&F\1.RXF^'EX-X&!21L7W&1QFJ]$P`
XMUW/)9Q'&11]#`4=,419;L`5(<G<BT`5=L!;BIGM8$`2<=A7R(8G\5XD$4WE&
XM]$F_`A,8-%(HL!9FMW6-11%7ES(]U!&R8H8_UHEKV%Y^9Q/`P09-D5E-441G
XM`%_L$1R5X1/1IXGFUXJ_$AMSP!W;MUR@43/FEQ5L,!JD$4>0UUW^QB)OP(K`
XM`7XU$2CI.$]OP'D`XFA%%%`]=S:R:'8]M$B*!W4^"%,;V%&8"%(B15(Z=5*V
XM)41`98*]AP7MQQ6FZ!D]Y(DL$7US8!A+")`+!QG`<0)+,8H]A$A5)RN7T10)
XMX1AT%Y)2)BN_"'%,Y510)554954WYP1:Q55>!1A2R2=E=59IM5:RX@1NM4YP
XMU4+H)BO$V(0Q:6\69W-.H''U1G-L$B2R`@7!!'8OM!&.$1OQI1'D.(CZV!-E
XM\!%!\3L_T13<QSJV-QL]N&^'U1D3"%BFY5ANV7AI5Y=0<)=BH"]7X6@:>4[6
XM^)&_\HT#R(F$J'AVJ8JR,@6$I(CF-ULGV8QB4R7P$61+(4@B\(O!&!N985.X
XMHDJ\28S&Z'),-05%4`1<4"!,,`5/8'1-ERR6*$3R9V]"4`5'0)?M%(%8L%J7
XMY8ZP)5N@M7JB15#$E%L*I7B\IYEE.4X;=@<1X8`O,6`%=AIK,08(I9Y?\8BT
XM@G?UXF+WM)"#1#I`>7Q@41VBX1Y%*1'<Q4.0`:$5X8Z1N7229QO8107&A5SK
XMI%QQQ419*"G1E9DHB`5ID%NYV2L8T10^!%T5-HUA$DQC!!P@<9Q!,$C;H@?`
XMP4P:L1;()`(]\1YRH"=P,`<_<(R,]Y]K<5!&>)F?"!J\-I2NM5E`*0=K8)AS
XM\!YCD`:!V8YS4QW8PSJ.6*%3R&`.QHY8$6$'4I,O>F$95D3QV6$%!F(D^H3U
XMAHPYUUS<T13/%Q%U\&W,Q&V@T1,ZT3VF-(<*:H6;)4=&,(<5<4=H&B.%^A-@
XMP9<I`TAC(%O!T1,ONJ>0X14SEIO2I9G>B6.(QV,RX6,PIIOR1&1UNIDN4`0`
XMDVL*5&I>@6<Y`@*I-B&)8Q-1]CA49JMN8&51@F7/HVC3@VGHX@9@-CIC!A:"
XM9&:KTSJO8V>S$QMO=CN2-F<_46>^0SBY&CSP4V!]9CR`ECR#MCR5`RV(ICG2
XMHR6,IA&.)B:19B9V@2:=(7S*"AZ?M&F=YJ[JXR>B-BBD]C7].C\SH&JK!BE:
XMZ&K\$VO_,VL"Y#7:46"XAD"Z-JZ?U$!EB6]%(!*R@CDB&XVQ!R2U2)H'P71F
XM8'!T@'`]^:%W\WT.]R[4,G$5=W$9![)8,+*8LWPA%R0D-W(_:W(AAW(JAW=W
XM('S4`G-3(',T)Y<ZR[,BD:<&<[(#A5O&)!)!%ZAKHC8ITS33.4*RD3(JBW0B
XMX8-2NT,8](U9)T1;5T1=ET)?YY-A1WQCUQEIBSEH*[5K-WYNUX'G!RU&:W>Q
XM,9,@(1)\EQH3"7B4*$\A*[6$5WUR<'B?M&-L02UI&WE+1K+--4::-QIGY'F@
XMUW!UR!8@H%$@`*E-4:`1`0*/M[-22Y_RQ'J"%)L^FTA62GN/!"RXE[=2^[J^
XM&[S".[S$2[S`*[6_-[AK,A'Z]XRWZ+/-)UO01Q4#%;ED8'CDE'V/R[.OJ!&E
XMU7W?U[=`\;<Q$;ASIW[0!!:&2T[@%[;;.[+TURN7.S%I&XG-2XD]P;E5"X`E
XMU;H1U;I%5(Z$*!(*Z'TC^+XB*[M^)1*WA;4*E;\7F$JJM$HRQ8P>N%.T=+8(
XMC#G5A$NZ-#?%&\(BK+<;+!(J*!(L^!@NB%S8$X.6,8."=!K$TY`Z.+\EW$]`
XM*%!#6%!+NI]9"[=)^,(OVT)2N[<\>S1L,87=:T0%*;<5T88-*T_WE!55"X89
XM5CM40H8W/)B-N(.8,X50+*)_419QZ+5TR(N$F8<4<<,BP(=F_(?THIJ%F1)@
XM<8B)B(]N(\#Z:,.PR[/V6WSX:Y(?]69XS(B=&!&`9#9[M!04P:"E*!*)=<.G
XMH3(XJ(-4Z"BQ.!@S!DNCZ38]$5MRH(M?42_-V)O`>,/":)Q\G+;*N).]>+_]
XMI[\ILV/5Z)&L!"_:*`?<Z*0M"HYD>&A]/+)<;(Y?/(/#-\7KN+KN*!(!'(^0
XM0H\V88^CFK9XK(]TK+7^*)@`&1&D(1X%>08'F<3=Y565W(H0:8!S(,G=94(6
XMN<CRU,D<:1.V#)*(NQ0QY4S=15,B85,IZ9UIFU,FQ5,MZ33U,L(&';Q&/+*&
XM6Y.?X173:Q$\.8`_F4A1VLBD:)00FI3`G+9+B:!L\8L''=+$ZU(B7=(F/;(N
XM1951-555!;4G_=)Y2])2JY7FUI5?"],X+=,XO=/%ZU)D959HI599P--$+;(Z
XM/;)F^59(\*'H!@+$6-0]32UQ>55SJ;,W3#P;7;QZR<@*]Y-^N8LB$9BIJ<=J
XM?)C08ATWG+8:W9AX@<6R6YGIJ5O%ZX-7S2)93;S[XL[P/,^G*:+#O)I6'<Q&
XM#19W/;RPR6&RF<<X\E&].$^X&6,($C4T:,*^B3GPE-92&YR;P:K%68Q\K)P?
XM&P3/^011&[O629TW<=HC1"W4DIW;6=H\"YZM)9X4T5F?-;OG28&7.5@&G=`B
XM2[4I$Y_S.9GUZ6&GJ$+^X</PM,I2^Y\`BC!S*,,LHB='<:!T!WX+>M$.>C8Z
XM%7<Z-:&:)<6^C3G6A9[KE%T<^J`2W5QA/%Z,',+C+1(G^EE<*EPLBIHOFGWW
XM.8,TNAML<:,X.A<ZVGW>ZZ-H`*0W+*1$:J2!G;G=9<)%B#G=*!*)/`<531%3
XMVKJX>Z54DJ55PJ7R18,W#*9P(:;E),[H2!'OU:5I6E`2ML!MRE\S%J?^++7V
XM^6%T8+I0'=)T+=B8`]P]PZ>@X:>`.G2#NE.&VA.("A&*RMLBT:A?6Q&I:WKL
XMF."V`A&42L`^":*?F*F?L:GY]1B>FEG!(4^B*GTYEGTU?L2I^F)`)F.M6F,[
XM/K)T3:M(IK'2]3NYFK"J]F2^VCC`VC)X3JR68ZRH`;#)6K`5>["B(V:E`ZUE
XMICIH1JUK=F=MAJVV$V?;VAETUCMWIN>V)ZX<4ZY_ACR"1FC,$R6'=JR?!J_5
XM`R:/ECV2MCWX^A+Z2FH1XZ_FXVE<QB<"&RFCEC#,.C\R0`,P4%&LUK#[`VN9
XM$K$!5&L;PS`7ZS>U&C&]]FO!YD9PH27+=VS)MFP0Y&S0)FW4MB`V<&TSD&TP
XM\0;<YNO?%F[U1FYFR55-?3_MMF[X+@+P)F_T9F].X+&PUUS^9K4"I[(LZ[+K
XMW9<R^SU?:;,6AW%TZ;,B]W$AMY`DIXHG%WQIL7)YYW[("0),Z[0U1]7O*8V=
XMG("[C8M")ZA>*YUF(']*5[;),G55U\L<I%)ORU`GY'4K1+<O)'8T](!8(+[D
XM]W9Q)[@:OWZ%V_%<07H_)ECWQ+B")T_6B[VG^HC)F_2#@<B`C'QDX'_2&+W/
XM)\UH7O63^W[9M\0%'+[AQW;D:WY'?[["QWY,+U$&H7;A)W_QF^-(*BM_/(FQ
XM[+/\*X#_2_5=C/+@.X*+W$<2&$RD58&GA('*9!HE28M>\8$9W,'7],$LD8+^
XM+2LIC,DL#!<N[!<1$<,*.<,.N8-]_X,F'X0#15P1?H1`?!(.)<0#"(63<HZG
XMWR56Z,0ANH75U84&8\5B&(YE")!RK(8)21C)+L;5*`)E+*!NA,:'KX=EX<9%
XMAP5P'(C+7TYZ")A,<L<8,9O?/UBM__?/:(GY?)*$7/YYG,:>6.'N3)2/C%^7
XMD8HML(J6K/:9/(L6S&K=(E`FRGA1*:MLJ<RSM;Y6QHSR3]>#1CZ+EF&%>8;+
XM3-`NXT]U##4AOW&D_,@:ZYL5,V@BG(9D]JG>T55P9O-(,;RP>P3_K-G=Z4=B
XM[7\))&]FD$9/0@(?Y(R&F;/J$)$&RFE@9^SA(L&ZC`3[XEEI8B7H#PN0))G2
XM_CX*/\,I/H8ET1B"1@;V3=UC:#?IH>VDSY#P)@50JFCV#Z/5!*2TF/($4T)(
XM'T^E6:661O)PSE;J*E_%WOPTL234RM)9Z@MI:8FLI8\WU:`*=VI->`D+;+4N
XM^"L*((;39G'E_!DFQ+3=UAH":FN02281MP7V^'8;:^I,"PDTZ;4BR->\D5_K
XM@/(O";H`0%@%L<!AXQF%#+34IJ9PFU((9"-.<\.4_2;H=BLX6RQ490UO.34G
XMT0:=7![2J4Y'9^9]/-=&EV0;AJ-M8F^VF*?:,@77R<^1(T!.N"T^LG#CCAL[
XMT4]-"@/ZI^ZR+@)4=$M]T\U`)1($A=W"8".L.A'JNY5`I'2A-`)QT5#:);ET
XM%TL5_)C/J)IO*<J^>4(7I5_TFXSB;^OB\R6C`-<Z=E1\82<_*DC!A05WI.Y4
XMDNHN/2P;DI(G9>&$TC%\+56*PX$&+07BT)0@(7&38H\UOP7S*U;<@VF&?>'%
XMX9<8%X8T3("14SCN$0$Y3]6GA$*1$U2FI%"A$R5WJ9A<05I4L@+*8075942N
XMW$6H5#[O4KT!+P<4H%&G"F]D+E15AWLX4$Y5!W(Q-F%5P;DBHE(4CZSB&QBK
XMVIT'7&5[BMVQ\W.+`]!-&4$7,0@=4#!TO.Y=L0E<9VJ01)@A'61&:$BK2:=F
XMK-6E.SR9#B[(&4[7K3P=6=01UV%F``DA8:Y,G?(H-*JN76T9N1BOW!F]TAZ4
XMQGO<NF6EZ\X'LM(2H0;8$2S.2.QH0`TX+^W-83$[_P%`:$W,4(S3[L@LJVN'
XM)("-L-EVLLS;*9N-$>Z>3;29-M7FW&$;&*!MV%VW@1'@1MS(.W-3[_*=NRD+
XM^TXK];N(\^_R3<#K-_\&GJ4L(7+P$DY29#A8H>78&X>'LR(>Q_$X%T]HE9R,
XMA[XX7M+R>/8FY,V<D9>5<EC/07D8$.C4@95'=)0.UG!?%,/RR#QS075XB,T#
XM(FZ+B.@\)#*W8-;/LUM![PS@O9_BM\J/^4H_<V_IO<>FYWN60M^)>J"A<141
XMLT>Y=$SB:7V:*UA<1P$Y@SX7YT$CK*L#A1XXXO2((NJ9A'\DD,R-UR.3QLF&
XMTUVVAW=U#ZQG.[3>\(%EGDR6U3;G@\^B#XXAD6@OF*@]@\CV*.3XLI!Q#T,2
XM+O55]][/A'QYPG#O/2+U%\@$WQD(0&:C\(W(P_>]%I#BHT^-3[%8IOQH@9+)
XM+*I\`?#R8;#R(X(XGT+X3@(Q]*VP6%?ZQ@CJPX$500<R/X=8\DK6R3-O?2$B
XM.C"H5_OJ">YC0E@`B8W$2_;[L%!JE">GP0NE+FZ18=X,\AMK\H_WU<,W1,82
XM4?4S9(0(^[6Q/B0KNA^LG&.&:/R9L53H`44A,B*3L>P2#;*^P"M#(46L?XY,
XM#M2D_(<%5%$Y>TC^3T1H,GG"R6#?`,Q%?\D`-@59>,V&D0)DE,EH&;VR!PCV
XM2I8$K`@4,!M9P!'2C7K9&!)'6."OM2)5*0*["PE<9O!('H&J>I23ED(U0T#7
XM#`;^H[B2SK!`-R-(-1`-_B<"I2B#`@]$9_<$"(8!(3ACX-EEZ$C7*`DN07QF
XM&4[2$U1)`:VGN*12N-`66$/#27K"0T8T2W7Z@M)02I:GA(>0P3*@E*"'1_M*
XM?7`NB1M`&`;RTE[ZCE\-,`W,HJ$(40,C5$PT\WLY)F$AF7`"90HFNBT_7D+/
XMI`E%$R?,F/LP9<C+,<69[E(I/(6)C39]%-L4D7(3G.--"!`XV0KA9`N%AK<\
XM3N-1%SJG7M@C@V$*`(8`$CMIIV*X&]Y0AEN2Y`FW,<.HJ5L:97.1AK*K&MZ3
XM_*3<^A.*Y(:5`;J1+7!8H*K;.+QN"LH<(LWN)J'6H87"$1B*A\'#]'9/Z.&G
XM)"\F"D55!Q6%IMQE?@LF^VTB]#<;11`''(]"B`=.(0ZI]F"D'B=R8U*3,D&!
XMHHHHI6C;AL-2')'%?<1G$1*Y9IDJB0V&Q4$8%[>F8)Q^<5,S[B4J3CH%+F=B
XM>*N)?VJ5X$1"A1<.54_,4C\Q"0K%1T7E6*%1S'+T$%-I*J>H7\8<J#)S4_'Z
XM5,7*Q6+:7%9\<U)AQKBJ>O,5[=RR.HRZRC2>EUZ5%J4,Y%A6;O%R9!E$UV5(
XM8Z/#BY!.+THZBT#I_")JP'2Q;C#JCL)HK>*B^@"AM4$C``;<H!OHQ%U8"A<"
X`
Xend
END_OF_tests.uu
if test 9887 -ne `wc -c <tests.uu`; then
    echo shar: \"tests.uu\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
Bill Rosenkranz            |UUCP: {uunet,texsun}!convex!c1yankee!rosenkra
Convex Computer Corp.      |ARPA: rosenkra%c1yankee@convex.com