Browse Source

Plan 9 from Bell Labs 2006-09-08

David du Colombier 17 years ago
parent
commit
9f12f9908e

+ 10 - 6
dist/replica/_plan9.db

@@ -185,6 +185,7 @@
 386/bin/cmp - 775 sys sys 1157597609 40658
 386/bin/colors - 775 sys sys 1155491750 151061
 386/bin/comm - 775 sys sys 1148500616 61680
+386/bin/compress - 775 sys sys 1157684160 166929
 386/bin/con - 775 sys sys 1148500616 78580
 386/bin/cp - 775 sys sys 1148500616 63548
 386/bin/cpp - 775 sys sys 1148500616 150553
@@ -264,7 +265,7 @@
 386/bin/gif - 775 sys sys 1150062736 158649
 386/bin/grap - 775 sys sys 1136656337 280496
 386/bin/graph - 775 sys sys 1148500640 129344
-386/bin/grep - 775 sys sys 1157138535 79446
+386/bin/grep - 775 sys sys 1157684160 79663
 386/bin/gs - 775 sys sys 1137468663 13275174
 386/bin/gunzip - 775 sys sys 1148500640 80617
 386/bin/gview - 775 sys sys 1155491751 239077
@@ -7311,7 +7312,7 @@ sys/man/1/graph - 664 sys sys 1148227125 3061
 sys/man/1/grep - 664 sys sys 1139690020 2257
 sys/man/1/gs - 664 sys sys 1032054727 6906
 sys/man/1/gview - 664 sys sys 1136378273 4361
-sys/man/1/gzip - 664 sys sys 1124839836 3226
+sys/man/1/gzip - 664 sys sys 1157681393 3830
 sys/man/1/hget - 664 sys sys 1141313152 1482
 sys/man/1/history - 664 sys sys 1109685635 1709
 sys/man/1/hoc - 664 sys sys 1136378274 2357
@@ -7570,7 +7571,7 @@ sys/man/3/ether - 664 sys sys 984709635 2563
 sys/man/3/floppy - 664 sys sys 954378905 881
 sys/man/3/fs - 664 sys sys 1133880474 2702
 sys/man/3/i82365 - 664 sys sys 954378906 884
-sys/man/3/ip - 664 sys sys 1133880453 21677
+sys/man/3/ip - 664 sys sys 1157657123 21416
 sys/man/3/kbmap - 664 sys sys 1131110122 1732
 sys/man/3/kprof - 664 sys sys 1018029972 1377
 sys/man/3/loopback - 664 sys sys 964662153 1995
@@ -9886,6 +9887,9 @@ sys/src/cmd/clock.c - 664 sys sys 1014925410 1881
 sys/src/cmd/cmp.c - 664 sys sys 1157581072 2491
 sys/src/cmd/colors.c - 664 sys sys 951763912 3186
 sys/src/cmd/comm.c - 664 sys sys 1093979717 2140
+sys/src/cmd/compress - 20000000775 sys sys 1157679448 0
+sys/src/cmd/compress/compress.c - 664 sys sys 1157679448 31907
+sys/src/cmd/compress/mkfile - 664 sys sys 1157679443 118
 sys/src/cmd/con - 20000000775 sys sys 944961996 0
 sys/src/cmd/con/con.c - 664 sys sys 1143759347 15227
 sys/src/cmd/con/hayes.c - 664 sys sys 1014925263 3865
@@ -10233,11 +10237,11 @@ sys/src/cmd/graph/subr.c - 664 sys sys 985051276 321
 sys/src/cmd/graph/whoami.c - 664 sys sys 944960999 62
 sys/src/cmd/grep - 20000000775 sys sys 1018466661 0
 sys/src/cmd/grep/comp.c - 664 sys sys 1135487941 4177
-sys/src/cmd/grep/grep.h - 664 sys sys 1068478083 2176
-sys/src/cmd/grep/grep.y - 664 sys sys 944961351 2804
+sys/src/cmd/grep/grep.h - 664 sys sys 1157665788 2198
+sys/src/cmd/grep/grep.y - 664 sys sys 1157665806 2964
 sys/src/cmd/grep/main.c - 664 sys sys 1136378273 4686
 sys/src/cmd/grep/mkfile - 664 sys sys 944961351 153
-sys/src/cmd/grep/sub.c - 664 sys sys 1157090728 3941
+sys/src/cmd/grep/sub.c - 664 sys sys 1157665944 4006
 sys/src/cmd/gs - 20000000775 sys sys 1017695101 0
 sys/src/cmd/gs/386.h - 664 sys sys 1137462348 1464
 sys/src/cmd/gs/alpha.h - 664 sys sys 1137462348 1373

+ 10 - 6
dist/replica/plan9.db

@@ -185,6 +185,7 @@
 386/bin/cmp - 775 sys sys 1157597609 40658
 386/bin/colors - 775 sys sys 1155491750 151061
 386/bin/comm - 775 sys sys 1148500616 61680
+386/bin/compress - 775 sys sys 1157684160 166929
 386/bin/con - 775 sys sys 1148500616 78580
 386/bin/cp - 775 sys sys 1148500616 63548
 386/bin/cpp - 775 sys sys 1148500616 150553
@@ -264,7 +265,7 @@
 386/bin/gif - 775 sys sys 1150062736 158649
 386/bin/grap - 775 sys sys 1136656337 280496
 386/bin/graph - 775 sys sys 1148500640 129344
-386/bin/grep - 775 sys sys 1157138535 79446
+386/bin/grep - 775 sys sys 1157684160 79663
 386/bin/gs - 775 sys sys 1137468663 13275174
 386/bin/gunzip - 775 sys sys 1148500640 80617
 386/bin/gview - 775 sys sys 1155491751 239077
@@ -7311,7 +7312,7 @@ sys/man/1/graph - 664 sys sys 1148227125 3061
 sys/man/1/grep - 664 sys sys 1139690020 2257
 sys/man/1/gs - 664 sys sys 1032054727 6906
 sys/man/1/gview - 664 sys sys 1136378273 4361
-sys/man/1/gzip - 664 sys sys 1124839836 3226
+sys/man/1/gzip - 664 sys sys 1157681393 3830
 sys/man/1/hget - 664 sys sys 1141313152 1482
 sys/man/1/history - 664 sys sys 1109685635 1709
 sys/man/1/hoc - 664 sys sys 1136378274 2357
@@ -7570,7 +7571,7 @@ sys/man/3/ether - 664 sys sys 984709635 2563
 sys/man/3/floppy - 664 sys sys 954378905 881
 sys/man/3/fs - 664 sys sys 1133880474 2702
 sys/man/3/i82365 - 664 sys sys 954378906 884
-sys/man/3/ip - 664 sys sys 1133880453 21677
+sys/man/3/ip - 664 sys sys 1157657123 21416
 sys/man/3/kbmap - 664 sys sys 1131110122 1732
 sys/man/3/kprof - 664 sys sys 1018029972 1377
 sys/man/3/loopback - 664 sys sys 964662153 1995
@@ -9886,6 +9887,9 @@ sys/src/cmd/clock.c - 664 sys sys 1014925410 1881
 sys/src/cmd/cmp.c - 664 sys sys 1157581072 2491
 sys/src/cmd/colors.c - 664 sys sys 951763912 3186
 sys/src/cmd/comm.c - 664 sys sys 1093979717 2140
+sys/src/cmd/compress - 20000000775 sys sys 1157679448 0
+sys/src/cmd/compress/compress.c - 664 sys sys 1157679448 31907
+sys/src/cmd/compress/mkfile - 664 sys sys 1157679443 118
 sys/src/cmd/con - 20000000775 sys sys 944961996 0
 sys/src/cmd/con/con.c - 664 sys sys 1143759347 15227
 sys/src/cmd/con/hayes.c - 664 sys sys 1014925263 3865
@@ -10233,11 +10237,11 @@ sys/src/cmd/graph/subr.c - 664 sys sys 985051276 321
 sys/src/cmd/graph/whoami.c - 664 sys sys 944960999 62
 sys/src/cmd/grep - 20000000775 sys sys 1018466661 0
 sys/src/cmd/grep/comp.c - 664 sys sys 1135487941 4177
-sys/src/cmd/grep/grep.h - 664 sys sys 1068478083 2176
-sys/src/cmd/grep/grep.y - 664 sys sys 944961351 2804
+sys/src/cmd/grep/grep.h - 664 sys sys 1157665788 2198
+sys/src/cmd/grep/grep.y - 664 sys sys 1157665806 2964
 sys/src/cmd/grep/main.c - 664 sys sys 1136378273 4686
 sys/src/cmd/grep/mkfile - 664 sys sys 944961351 153
-sys/src/cmd/grep/sub.c - 664 sys sys 1157090728 3941
+sys/src/cmd/grep/sub.c - 664 sys sys 1157665944 4006
 sys/src/cmd/gs - 20000000775 sys sys 1017695101 0
 sys/src/cmd/gs/386.h - 664 sys sys 1137462348 1464
 sys/src/cmd/gs/alpha.h - 664 sys sys 1137462348 1373

+ 10 - 0
dist/replica/plan9.log

@@ -30369,3 +30369,13 @@
 1157581805 0 c 386/bin/cmp - 775 sys sys 1157581077 40658
 1157581805 1 c sys/src/cmd/cmp.c - 664 sys sys 1157581072 2491
 1157598006 0 c 386/bin/cmp - 775 sys sys 1157597609 40658
+1157657405 0 c sys/man/3/ip - 664 sys sys 1157657123 21416
+1157666406 0 c sys/src/cmd/grep/grep.h - 664 sys sys 1157665788 2198
+1157666406 1 c sys/src/cmd/grep/grep.y - 664 sys sys 1157665806 2964
+1157666406 2 c sys/src/cmd/grep/sub.c - 664 sys sys 1157665944 4006
+1157680805 0 a sys/src/cmd/compress - 20000000775 sys sys 1157679448 0
+1157680805 1 a sys/src/cmd/compress/compress.c - 664 sys sys 1157679448 31907
+1157680805 2 a sys/src/cmd/compress/mkfile - 664 sys sys 1157679443 118
+1157682607 0 c sys/man/1/gzip - 664 sys sys 1157681393 3830
+1157684407 0 c 386/bin/grep - 775 sys sys 1157684160 79663
+1157684407 1 a 386/bin/compress - 775 sys sys 1157684160 166929

+ 44 - 5
sys/man/1/gzip

@@ -1,6 +1,6 @@
 .TH GZIP 1
 .SH NAME
-gzip, gunzip, bzip2, bunzip2, zip, unzip, \- compress and expand data
+gzip, gunzip, bzip2, bunzip2, compress, uncompress, zip, unzip \- compress and expand data
 .SH SYNOPSIS
 .B gzip
 .RB [ -cvD [ 1-9 ]]
@@ -22,6 +22,22 @@ gzip, gunzip, bzip2, bunzip2, zip, unzip, \- compress and expand data
 .RI [ file
 .BR ... ]
 .PP
+.B compress
+[
+.B -cv
+] [
+.I file
+.B ...
+]
+.PP
+.B uncompress
+[
+.B -cv
+] [
+.I file
+.B ...
+]
+.PP
 .B zip
 .RB [ -vD [ 1-9 ]]
 .RB [ -f
@@ -33,7 +49,7 @@ gzip, gunzip, bzip2, bunzip2, zip, unzip, \- compress and expand data
 .RB [ -cistTvD ]
 .RB [ -f
 .IR zipfile ]
-.IR [ file
+.RI [ file
 .BR ... ]
 .SH DESCRIPTION
 .PP
@@ -83,6 +99,19 @@ recognizes the extension
 as a synonym for
 .BR .tbz .
 .PP
+.I Compress
+and
+.I uncompress
+are similar in interface to
+.I gzip
+and
+.IR gunzip ,
+but use the Lempel-Ziv-Welch compression algorithm.
+The default suffix for output files is
+.BR .Z .
+.I Compress
+is one of the oldest widespread Unix compression programs.
+.PP
 .I Zip
 encodes the named files and places the results into the archive
 .IR zipfile ,
@@ -92,12 +121,16 @@ extracts files from an archive created by
 .IR zip .
 If no files are named as arguments, all of files in the archive are extracted.
 A directory's name implies all recursively contained files and subdirectories.
+.I Zip
+is the
+.I "de facto"
+standard for compression on Microsoft operating systems.
 .PP
 None of these programs removes the original files.
 If the process fails, the faulty output files are removed.
 .PP
 The options are:
-.TP 1i
+.TP 0.6i
 .B -c
 Write to standard output rather than creating an output file.
 .TP
@@ -149,9 +182,15 @@ Produce debugging output.
 .B /sys/src/cmd/gzip
 .br
 .B /sys/src/cmd/bzip2
+.br
+.B /sys/src/cmd/compress
 .SH SEE ALSO
-.IR tar (1),
-.IR compress (1)
+.IR tar (1)
+.br
+"A Technique for High Performance Data Compression",
+Terry A. Welch,
+.IR "IEEE Computer" ,
+vol. 17, no. 6 (June 1984), pp. 8-19.
 .SH BUGS
 .I Unzip
 can only extract files which are uncompressed or compressed

+ 5 - 20
sys/man/3/ip

@@ -51,10 +51,9 @@ However multiple stacks can be used for debugging
 new IP networks or implementing firewalls or proxy
 services.
 .PP
-All addresses used are 16-byte IPv6 addresses.  Though
-we currently implement only IPv4, the IPv6 format is intended to
-prepare the way for an IPv6 implementation.  IPv4 addresses
-are a subset of the IPv6 addresses and both standard
+All addresses used are 16-byte IPv6 addresses.
+We implement IPv4 and IPv6.
+IPv4 addresses are a subset of the IPv6 addresses and both standard
 .SM ASCII
 formats
 are accepted.  In binary, all v4 addresses start with the
@@ -566,19 +565,6 @@ one of the following messages is written to
 .BR ctl ,
 then all messages sent to the announced port
 are received on the announced connection prefixed with the given structure.
-.TP
-.B headers4
-.EX
-typedef struct Udphdr4 Udphdr4;
-struct Udphdr
-{
-	uchar	raddr[4];		/* v4 remote address and port */
-	uchar	laddr[4];		/* v4 local address and port */
-	uchar	rport[2];
-	uchar	lport[2];
-};
-.EE
-.TP
 .B headers
 .EX
 typedef struct Udphdr Udphdr;
@@ -586,6 +572,7 @@ struct Udphdr
 {
 	uchar	raddr[16];	/* v6 remote address and port */
 	uchar	laddr[16];	/* v6 local address and port */
+	uchar	ifcaddr[16];	/* interface address (receive only) */
 	uchar	rport[2];
 	uchar	lport[2];
 };
@@ -612,9 +599,7 @@ One must use either
 or
 .B announce
 followed immediately by
-.B headers
-or
-.BR headers4 .
+.B headers .
 .PP
 Unlike IL or TCP, the reboot of one end of a connection does
 not force a closing of the connection.  Communications will

+ 1242 - 0
sys/src/cmd/compress/compress.c

@@ -0,0 +1,1242 @@
+/*
+ * compress - File compression ala IEEE Computer, June 1984.
+ *
+ * Algorithm from "A Technique for High Performance Data Compression",
+ * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
+ *
+ * Usage: compress [-dfvc] [-b bits] [file ...]
+ * Inputs:
+ *	-b:	limit the max number of bits/code.
+ *	-c:	write output on stdout, don't remove original.
+ *	-d:	decompress instead.
+ *	-f:	Forces output file to be generated, even if one already
+ *		exists, and even if no space is saved by compressing.
+ *		If -f is not used, the user will be prompted if stdin is
+ *		a tty, otherwise, the output file will not be overwritten.
+ *	-v:	Write compression statistics
+ *
+ * 	file ...: Files to be compressed.  If none specified, stdin is used.
+ * Outputs:
+ *	file.Z:	Compressed form of file with same mode, owner, and utimes
+ * 		or stdout (if stdin used as input)
+ *
+ * Assumptions:
+ *	When filenames are given, replaces with the compressed version
+ *	(.Z suffix) only if the file decreases in size.
+ * Algorithm:
+ * 	Modified Lempel-Ziv method (LZW).  Basically finds common
+ * substrings and replaces them with a variable size code.  This is
+ * deterministic, and can be done on the fly.  Thus, the decompression
+ * procedure needs no input table, but tracks the way the table was built.
+
+ * Authors:	Spencer W. Thomas	(decvax!harpo!utah-cs!utah-gr!thomas)
+ *		Jim McKie		(decvax!mcvax!jim)
+ *		Steve Davies		(decvax!vax135!petsd!peora!srd)
+ *		Ken Turkowski		(decvax!decwrl!turtlevax!ken)
+ *		James A. Woods		(decvax!ihnp4!ames!jaw)
+ *		Joe Orost		(decvax!vax135!petsd!joe)
+ */
+#define _PLAN9_SOURCE
+
+#include <u.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define	min(a,b)	((a>b) ? b : a)
+
+#define BITS	16
+#define HSIZE	69001		/* 95% occupancy */
+
+/*
+ * a code_int must be able to hold 2**BITS values of type int, and also -1
+ */
+typedef long	code_int;
+typedef long	count_int;
+
+static char rcs_ident[] = "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $";
+
+uchar magic_header[] = { 0x1F, 0x9D };	/* 1F 9D */
+
+/* Defines for third byte of header */
+#define BIT_MASK	0x1f
+#define BLOCK_MASK	0x80
+/* Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
+	a fourth header byte (for expansion).
+*/
+#define INIT_BITS 9			/* initial number of bits/code */
+
+void onintr(int);
+void oops(int);
+
+#define ARGVAL() (*++(*argv) || (--argc && *++argv))
+
+int n_bits;				/* number of bits/code */
+int maxbits = BITS;			/* user settable max # bits/code */
+code_int maxcode;			/* maximum code, given n_bits */
+code_int maxmaxcode = 1 << BITS;	/* should NEVER generate this code */
+
+#define MAXCODE(n_bits)	((1 << (n_bits)) - 1)
+
+count_int htab[HSIZE];
+ushort codetab[HSIZE];
+
+#define htabof(i)	htab[i]
+#define codetabof(i)	codetab[i]
+
+code_int hsize = HSIZE;			/* for dynamic table sizing */
+count_int fsize;
+
+/*
+ * To save much memory, we overlay the table used by compress() with those
+ * used by decompress().  The tab_prefix table is the same size and type
+ * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
+ * get this from the beginning of htab.  The output stack uses the rest
+ * of htab, and contains characters.  There is plenty of room for any
+ * possible stack (stack used to be 8000 characters).
+ */
+
+#define tab_prefixof(i)	codetabof(i)
+#define tab_suffixof(i)	((uchar *)(htab))[i]
+#define de_stack		((uchar *)&tab_suffixof(1<<BITS))
+
+code_int free_ent = 0;			/* first unused entry */
+int exit_stat = 0;
+
+code_int getcode();
+
+Usage()
+{
+#ifdef DEBUG
+	fprintf(stderr,"Usage: compress [-cdfDV] [-b maxbits] [file ...]\n");
+#else
+	fprintf(stderr,"Usage: compress [-cdfvV] [-b maxbits] [file ...]\n");
+#endif /* DEBUG */
+}
+
+int debug = 0;
+int nomagic = 0;	/* Use a 3-byte magic number header, unless old file */
+int zcat_flg = 0;	/* Write output on stdout, suppress messages */
+int quiet = 1;		/* don't tell me about compression */
+
+/*
+ * block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+int block_compress = BLOCK_MASK;
+int clear_flg = 0;
+long ratio = 0;
+#define CHECK_GAP 10000	/* ratio check interval */
+count_int checkpoint = CHECK_GAP;
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define FIRST	257	/* first free entry */
+#define	CLEAR	256	/* table clear output code */
+
+int force = 0;
+char ofname [100];
+#ifdef DEBUG
+int verbose = 0;
+#endif /* DEBUG */
+void (*bgnd_flag)(int);
+
+int do_decomp = 0;
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+	int overwrite = 0;	/* Do not overwrite unless given -f flag */
+	char tempname[512];
+	char **filelist, **fileptr;
+	char *cp;
+	struct stat statbuf;
+
+	if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
+		signal(SIGINT, onintr);
+		signal(SIGSEGV, oops);
+	}
+
+	filelist = fileptr = (char **)(malloc(argc * sizeof(*argv)));
+	*filelist = NULL;
+
+	if((cp = strrchr(argv[0], '/')) != 0)
+		cp++;
+	else
+		cp = argv[0];
+	if(strcmp(cp, "uncompress") == 0)
+		do_decomp = 1;
+	else if(strcmp(cp, "zcat") == 0) {
+		do_decomp = 1;
+		zcat_flg = 1;
+	}
+
+	/*
+	 * Argument Processing
+	 * All flags are optional.
+	 * -C	generate output compatible with compress 2.0.
+	 * -D	debug
+	 * -V	print Version; debug verbose
+	 * -b maxbits	maxbits.  If -b is specified, then maxbits MUST be
+	 *		given also.
+	 * -c	cat all output to stdout
+	 * -d	do_decomp
+	 * -f	force overwrite of output file
+	 * -n	no header: useful to uncompress old files
+	 * -v	unquiet
+	 * if a string is left, must be an input filename.
+	 */
+	for (argc--, argv++; argc > 0; argc--, argv++) {
+	if (**argv == '-') {	/* A flag argument */
+		while (*++(*argv)) {	/* Process all flags in this arg */
+		switch (**argv) {
+		case 'C':
+			block_compress = 0;
+			break;
+#ifdef DEBUG
+		case 'D':
+			debug = 1;
+			break;
+		case 'V':
+			verbose = 1;
+			version();
+			break;
+#else
+		case 'V':
+			version();
+			break;
+#endif
+		case 'b':
+			if (!ARGVAL()) {
+				fprintf(stderr, "Missing maxbits\n");
+				Usage();
+				exit(1);
+			}
+			maxbits = atoi(*argv);
+			goto nextarg;
+		case 'c':
+			zcat_flg = 1;
+			break;
+		case 'd':
+			do_decomp = 1;
+			break;
+		case 'f':
+		case 'F':
+			overwrite = 1;
+			force = 1;
+			break;
+		case 'n':
+			nomagic = 1;
+			break;
+		case 'q':
+			quiet = 1;
+			break;
+		case 'v':
+			quiet = 0;
+			break;
+		default:
+			fprintf(stderr, "Unknown flag: '%c'; ", **argv);
+			Usage();
+			exit(1);
+		}
+		}
+	} else {			/* Input file name */
+		*fileptr++ = *argv;	/* Build input file list */
+		*fileptr = NULL;
+		/* process nextarg; */
+	}
+nextarg:
+		continue;
+	}
+
+	if(maxbits < INIT_BITS) maxbits = INIT_BITS;
+	if (maxbits > BITS) maxbits = BITS;
+	maxmaxcode = 1 << maxbits;
+
+	if (*filelist != NULL) {
+	for (fileptr = filelist; *fileptr; fileptr++) {
+		exit_stat = 0;
+		if (do_decomp != 0) {			/* DECOMPRESSION */
+		/* Check for .Z suffix */
+		if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) {
+			/* No .Z: tack one on */
+			strcpy(tempname, *fileptr);
+			strcat(tempname, ".Z");
+			*fileptr = tempname;
+		}
+		/* Open input file */
+		if ((freopen(*fileptr, "r", stdin)) == NULL) {
+			perror(*fileptr);
+			continue;
+		}
+		/* Check the magic number */
+		if (nomagic == 0) {
+			if ((getchar() != (magic_header[0] & 0xFF))
+			|| (getchar() != (magic_header[1] & 0xFF))) {
+				fprintf(stderr, "%s: not in compressed format\n",
+					*fileptr);
+				continue;
+			}
+			maxbits = getchar();	/* set -b from file */
+			block_compress = maxbits & BLOCK_MASK;
+			maxbits &= BIT_MASK;
+			maxmaxcode = 1 << maxbits;
+			if(maxbits > BITS) {
+				fprintf(stderr,
+		"%s: compressed with %d bits, can only handle %d bits\n",
+					*fileptr, maxbits, BITS);
+				continue;
+			}
+		}
+		/* Generate output filename */
+		strcpy(ofname, *fileptr);
+		ofname[strlen(*fileptr) - 2] = '\0';  /* Strip off .Z */
+		} else {				/* COMPRESSION */
+		if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0) {
+			fprintf(stderr,
+				"%s: already has .Z suffix -- no change\n",
+				*fileptr);
+			continue;
+		}
+		/* Open input file */
+		if ((freopen(*fileptr, "r", stdin)) == NULL) {
+			perror(*fileptr);
+			continue;
+		}
+		(void) stat(*fileptr, &statbuf);
+		fsize = (long) statbuf.st_size;
+		/*
+		 * tune hash table size for small files -- ad hoc,
+		 * but the sizes match earlier #defines, which
+		 * serve as upper bounds on the number of output codes.
+		 */
+		hsize = HSIZE;
+		if (fsize < (1 << 12))
+			hsize = min(5003, HSIZE);
+		else if (fsize < (1 << 13))
+			hsize = min(9001, HSIZE);
+		else if (fsize < (1 << 14))
+			hsize = min (18013, HSIZE);
+		else if (fsize < (1 << 15))
+			hsize = min (35023, HSIZE);
+		else if (fsize < 47000)
+			hsize = min (50021, HSIZE);
+
+		/* Generate output filename */
+		strcpy(ofname, *fileptr);
+#ifndef BSD4_2
+		if ((cp=strrchr(ofname,'/')) != NULL)
+			cp++;
+		else
+			cp = ofname;
+		/*
+		 *** changed 12 to 25;  should be NAMELEN-3, but I don't want
+		 * to fight the headers.	ehg 5 Nov 92 **
+		 */
+		if (strlen(cp) > 25) {
+			fprintf(stderr, "%s: filename too long to tack on .Z\n",
+				cp);
+			continue;
+		}
+#endif
+		strcat(ofname, ".Z");
+		}
+		/* Check for overwrite of existing file */
+		if (overwrite == 0 && zcat_flg == 0 &&
+		   stat(ofname, &statbuf) == 0) {
+			char response[2];
+
+			response[0] = 'n';
+			fprintf(stderr, "%s already exists;", ofname);
+			if (foreground()) {
+				fprintf(stderr,
+				    " do you wish to overwrite %s (y or n)? ",
+					ofname);
+				fflush(stderr);
+				(void) read(2, response, 2);
+				while (response[1] != '\n')
+					if (read(2, response+1, 1) < 0) {
+						/* Ack! */
+						perror("stderr");
+						break;
+					}
+			}
+			if (response[0] != 'y') {
+				fprintf(stderr, "\tnot overwritten\n");
+				continue;
+			}
+		}
+		if(zcat_flg == 0) {		/* Open output file */
+			if (freopen(ofname, "w", stdout) == NULL) {
+				perror(ofname);
+				continue;
+			}
+			if(!quiet)
+				fprintf(stderr, "%s: ", *fileptr);
+		}
+
+		/* Actually do the compression/decompression */
+		if (do_decomp == 0)
+			compress();
+#ifndef DEBUG
+		else
+			decompress();
+#else
+		else if (debug == 0)
+			decompress();
+		else
+			printcodes();
+		if (verbose)
+			dump_tab();
+#endif						/* DEBUG */
+		if(zcat_flg == 0) {
+			copystat(*fileptr, ofname);	/* Copy stats */
+			if (exit_stat == 1 || !quiet)
+				putc('\n', stderr);
+		}
+	}
+	} else {		/* Standard input */
+	if (do_decomp == 0) {
+		compress();
+#ifdef DEBUG
+		if(verbose)
+			dump_tab();
+#endif
+		if(!quiet)
+			putc('\n', stderr);
+	} else {
+		/* Check the magic number */
+		if (nomagic == 0) {
+		if ((getchar()!=(magic_header[0] & 0xFF))
+		 || (getchar()!=(magic_header[1] & 0xFF))) {
+			fprintf(stderr, "stdin: not in compressed format\n");
+			exit(1);
+		}
+		maxbits = getchar();	/* set -b from file */
+		block_compress = maxbits & BLOCK_MASK;
+		maxbits &= BIT_MASK;
+		maxmaxcode = 1 << maxbits;
+		fsize = 100000;		/* assume stdin large for USERMEM */
+		if(maxbits > BITS) {
+			fprintf(stderr,
+			"stdin: compressed with %d bits, can only handle %d bits\n",
+			maxbits, BITS);
+			exit(1);
+		}
+		}
+#ifndef DEBUG
+		decompress();
+#else
+		if (debug == 0)
+			decompress();
+		else
+			printcodes();
+		if (verbose)
+			dump_tab();
+#endif						/* DEBUG */
+	}
+	}
+	exit(exit_stat);
+}
+
+static int offset;
+long in_count = 1;		/* length of input */
+long bytes_out;			/* length of compressed output */
+long out_count = 0;		/* # of codes output (for debugging) */
+
+/*
+ * compress stdin to stdout
+ *
+ * Algorithm:  use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination.  We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe.  Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation.  Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills.  The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor.  Late addition:  construct the table according to
+ * file size for noticeable speed improvement on small files.  Please direct
+ * questions about this implementation to ames!jaw.
+ */
+compress()
+{
+	code_int ent, hsize_reg;
+	code_int i = 0;
+	int c, disp, hshift;
+	long fcode;
+
+	if (nomagic == 0) {
+		putchar(magic_header[0]);
+		putchar(magic_header[1]);
+		putchar((char)(maxbits | block_compress));
+		if(ferror(stdout))
+			writeerr();
+	}
+	offset = 0;
+	bytes_out = 3;		/* includes 3-byte header mojo */
+	out_count = 0;
+	clear_flg = 0;
+	ratio = 0;
+	in_count = 1;
+	checkpoint = CHECK_GAP;
+	maxcode = MAXCODE(n_bits = INIT_BITS);
+	free_ent = (block_compress? FIRST: 256);
+
+	ent = getchar ();
+
+	hshift = 0;
+	for (fcode = (long)hsize;  fcode < 65536L; fcode *= 2)
+		hshift++;
+	hshift = 8 - hshift;		/* set hash code range bound */
+
+	hsize_reg = hsize;
+	cl_hash( (count_int) hsize_reg);		/* clear hash table */
+
+	while ((c = getchar()) != EOF) {
+		in_count++;
+		fcode = (long) (((long) c << maxbits) + ent);
+	 	i = ((c << hshift) ^ ent);	/* xor hashing */
+
+		if (htabof (i) == fcode) {
+			ent = codetabof(i);
+			continue;
+		} else if ((long)htabof(i) < 0 )	/* empty slot */
+			goto nomatch;
+	 	disp = hsize_reg - i;	/* secondary hash (after G. Knott) */
+		if (i == 0)
+			disp = 1;
+probe:
+		if ((i -= disp) < 0)
+			i += hsize_reg;
+
+		if (htabof (i) == fcode) {
+			ent = codetabof(i);
+			continue;
+		}
+		if ((long)htabof(i) > 0)
+			goto probe;
+nomatch:
+		output((code_int)ent);
+		out_count++;
+	 	ent = c;
+		if (free_ent < maxmaxcode) {
+	 		codetabof(i) = free_ent++;	/* code -> hashtable */
+			htabof(i) = fcode;
+		} else if ((count_int)in_count >= checkpoint && block_compress)
+			cl_block ();
+	}
+	/*
+	* Put out the final code.
+	*/
+	output( (code_int)ent );
+	out_count++;
+	output( (code_int)-1 );
+
+	/*
+	* Print out stats on stderr
+	*/
+	if(zcat_flg == 0 && !quiet) {
+#ifdef DEBUG
+	fprintf( stderr,
+		"%ld chars in, %ld codes (%ld bytes) out, compression factor: ",
+		in_count, out_count, bytes_out );
+	prratio( stderr, in_count, bytes_out );
+	fprintf( stderr, "\n");
+	fprintf( stderr, "\tCompression as in compact: " );
+	prratio( stderr, in_count-bytes_out, in_count );
+	fprintf( stderr, "\n");
+	fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
+		free_ent - 1, n_bits );
+#else /* !DEBUG */
+	fprintf( stderr, "Compression: " );
+	prratio( stderr, in_count-bytes_out, in_count );
+#endif /* DEBUG */
+	}
+	if(bytes_out > in_count)	/* exit(2) if no savings */
+		exit_stat = 2;
+}
+
+/*
+ * TAG( output )
+ *
+ * Output the given code.
+ * Inputs:
+ * 	code:	A n_bits-bit integer.  If == -1, then EOF.  This assumes
+ *		that n_bits =< (long)wordsize - 1.
+ * Outputs:
+ * 	Outputs code to the file.
+ * Assumptions:
+ *	Chars are 8 bits long.
+ * Algorithm:
+ * 	Maintain a BITS character long buffer (so that 8 codes will
+ * fit in it exactly).  When the buffer fills up empty it and start over.
+ */
+
+static char buf[BITS];
+
+uchar lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
+uchar rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+
+output( code )
+code_int  code;
+{
+#ifdef DEBUG
+	static int col = 0;
+#endif
+	int r_off = offset, bits= n_bits;
+	char *bp = buf;
+
+#ifdef DEBUG
+	if (verbose)
+		fprintf(stderr, "%5d%c", code,
+			(col+=6) >= 74? (col = 0, '\n'): ' ');
+#endif
+	if (code >= 0) {
+		/*
+		 * byte/bit numbering on the VAX is simulated by the
+		 * following code
+		 */
+		/*
+		 * Get to the first byte.
+		 */
+		bp += (r_off >> 3);
+		r_off &= 7;
+		/*
+		 * Since code is always >= 8 bits, only need to mask the first
+		 * hunk on the left.
+		 */
+		*bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
+		bp++;
+		bits -=  8 - r_off;
+		code >>= 8 - r_off;
+		/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+		if ( bits >= 8 ) {
+			*bp++ = code;
+			code >>= 8;
+			bits -= 8;
+		}
+		/* Last bits. */
+		if(bits)
+			*bp = code;
+
+		offset += n_bits;
+		if ( offset == (n_bits << 3) ) {
+			bp = buf;
+			bits = n_bits;
+			bytes_out += bits;
+			do {
+				putchar(*bp++);
+			} while(--bits);
+			offset = 0;
+		}
+
+		/*
+		 * If the next entry is going to be too big for the code size,
+		 * then increase it, if possible.
+		 */
+		if ( free_ent > maxcode || (clear_flg > 0)) {
+			/*
+			* Write the whole buffer, because the input side won't
+			* discover the size increase until after it has read it.
+			*/
+			if ( offset > 0 ) {
+				if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
+					writeerr();
+				bytes_out += n_bits;
+			}
+			offset = 0;
+
+			if ( clear_flg ) {
+				maxcode = MAXCODE (n_bits = INIT_BITS);
+				clear_flg = 0;
+			} else {
+				n_bits++;
+				if ( n_bits == maxbits )
+					maxcode = maxmaxcode;
+				else
+					maxcode = MAXCODE(n_bits);
+			}
+#ifdef DEBUG
+			if ( debug ) {
+				fprintf(stderr,
+					"\nChange to %d bits\n", n_bits);
+				col = 0;
+			}
+#endif
+		}
+	} else {
+		/*
+		 * At EOF, write the rest of the buffer.
+		 */
+		if ( offset > 0 )
+			fwrite( buf, 1, (offset + 7) / 8, stdout );
+		bytes_out += (offset + 7) / 8;
+		offset = 0;
+		fflush( stdout );
+#ifdef DEBUG
+		if ( verbose )
+			fprintf( stderr, "\n" );
+#endif
+		if( ferror( stdout ) )
+			writeerr();
+	}
+}
+
+/*
+ * Decompress stdin to stdout.  This routine adapts to the codes in the
+ * file building the "string" table on-the-fly; requiring no table to
+ * be stored in the compressed file.  The tables used herein are shared
+ * with those of the compress() routine.  See the definitions above.
+ */
+decompress()
+{
+	int finchar;
+	code_int code, oldcode, incode;
+	uchar *stackp;
+
+	/*
+	* As above, initialize the first 256 entries in the table.
+	*/
+	maxcode = MAXCODE(n_bits = INIT_BITS);
+	for (code = 255; code >= 0; code--) {
+		tab_prefixof(code) = 0;
+		tab_suffixof(code) = (uchar)code;
+	}
+	free_ent = (block_compress? FIRST: 256);
+
+	finchar = oldcode = getcode();
+	if(oldcode == -1)		/* EOF already? */
+		return;			/* Get out of here */
+	putchar((char)finchar);		/* first code must be 8 bits = char */
+	if(ferror(stdout))		/* Crash if can't write */
+		writeerr();
+	stackp = de_stack;
+
+	while ((code = getcode()) > -1) {
+		if ((code == CLEAR) && block_compress) {
+			for (code = 255; code >= 0; code--)
+				tab_prefixof(code) = 0;
+			clear_flg = 1;
+			free_ent = FIRST - 1;
+			if ((code = getcode()) == -1)	/* O, untimely death! */
+				break;
+		}
+		incode = code;
+		/*
+		 * Special case for KwKwK string.
+		 */
+		if (code >= free_ent) {
+			*stackp++ = finchar;
+			code = oldcode;
+		}
+
+		/*
+		 * Generate output characters in reverse order
+		 */
+		while (code >= 256) {
+			*stackp++ = tab_suffixof(code);
+			code = tab_prefixof(code);
+		}
+		*stackp++ = finchar = tab_suffixof(code);
+
+		/*
+		 * And put them out in forward order
+		 */
+		do {
+			putchar(*--stackp);
+		} while (stackp > de_stack);
+
+		/*
+		 * Generate the new entry.
+		 */
+		if ( (code=free_ent) < maxmaxcode ) {
+			tab_prefixof(code) = (ushort)oldcode;
+			tab_suffixof(code) = finchar;
+			free_ent = code+1;
+		}
+		/*
+		 * Remember previous code.
+		 */
+		oldcode = incode;
+	}
+	fflush(stdout);
+	if(ferror(stdout))
+		writeerr();
+}
+
+/*
+ * TAG( getcode )
+ *
+ * Read one code from the standard input.  If EOF, return -1.
+ * Inputs:
+ * 	stdin
+ * Outputs:
+ * 	code or -1 is returned.
+ */
+code_int
+getcode()
+{
+	int r_off, bits;
+	code_int code;
+	static int offset = 0, size = 0;
+	static uchar buf[BITS];
+	uchar *bp = buf;
+
+	if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
+		/*
+		 * If the next entry will be too big for the current code
+		 * size, then we must increase the size.  This implies reading
+		 * a new buffer full, too.
+		 */
+		if ( free_ent > maxcode ) {
+			n_bits++;
+			if ( n_bits == maxbits )
+				maxcode = maxmaxcode; /* won't get any bigger now */
+			else
+				maxcode = MAXCODE(n_bits);
+		}
+		if ( clear_flg > 0) {
+			maxcode = MAXCODE(n_bits = INIT_BITS);
+			clear_flg = 0;
+		}
+		size = fread(buf, 1, n_bits, stdin);
+		if (size <= 0)
+			return -1;			/* end of file */
+		offset = 0;
+		/* Round size down to integral number of codes */
+		size = (size << 3) - (n_bits - 1);
+	}
+	r_off = offset;
+	bits = n_bits;
+	/*
+	 * Get to the first byte.
+	 */
+	bp += (r_off >> 3);
+	r_off &= 7;
+	/* Get first part (low order bits) */
+	code = (*bp++ >> r_off);
+	bits -= (8 - r_off);
+	r_off = 8 - r_off;		/* now, offset into code word */
+	/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+	if (bits >= 8) {
+		code |= *bp++ << r_off;
+		r_off += 8;
+		bits -= 8;
+	}
+	/* high order bits. */
+	code |= (*bp & rmask[bits]) << r_off;
+	offset += n_bits;
+	return code;
+}
+
+#ifdef DEBUG
+printcodes()
+{
+	/*
+	* Just print out codes from input file.  For debugging.
+	*/
+	code_int code;
+	int col = 0, bits;
+
+	bits = n_bits = INIT_BITS;
+	maxcode = MAXCODE(n_bits);
+	free_ent = ((block_compress) ? FIRST : 256 );
+	while ( ( code = getcode() ) >= 0 ) {
+	if ( (code == CLEAR) && block_compress ) {
+			free_ent = FIRST - 1;
+			clear_flg = 1;
+	}
+	else if ( free_ent < maxmaxcode )
+		free_ent++;
+	if ( bits != n_bits ) {
+		fprintf(stderr, "\nChange to %d bits\n", n_bits );
+		bits = n_bits;
+		col = 0;
+	}
+	fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
+	}
+	putc( '\n', stderr );
+	exit( 0 );
+}
+
+code_int sorttab[1<<BITS];	/* sorted pointers into htab */
+
+#define STACK_SIZE	15000
+
+dump_tab()	/* dump string table */
+{
+	int i, first, c, ent;
+	int stack_top = STACK_SIZE;
+
+	if(do_decomp == 0) {	/* compressing */
+	int flag = 1;
+
+	for(i=0; i<hsize; i++) {	/* build sort pointers */
+		if((long)htabof(i) >= 0) {
+			sorttab[codetabof(i)] = i;
+		}
+	}
+	first = block_compress ? FIRST : 256;
+	for(i = first; i < free_ent; i++) {
+		fprintf(stderr, "%5d: \"", i);
+		de_stack[--stack_top] = '\n';
+		de_stack[--stack_top] = '"';
+		stack_top = in_stack((htabof(sorttab[i])>>maxbits)&0xff,
+	stack_top);
+		for(ent=htabof(sorttab[i]) & ((1<<maxbits)-1);
+			ent > 256;
+			ent=htabof(sorttab[ent]) & ((1<<maxbits)-1)) {
+			stack_top = in_stack(htabof(sorttab[ent]) >> maxbits,
+						stack_top);
+		}
+		stack_top = in_stack(ent, stack_top);
+		fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr);
+			stack_top = STACK_SIZE;
+	}
+	} else if(!debug) {	/* decompressing */
+
+	for ( i = 0; i < free_ent; i++ ) {
+		ent = i;
+		c = tab_suffixof(ent);
+		if ( isascii(c) && isprint(c) )
+		fprintf( stderr, "%5d: %5d/'%c'  \"",
+				ent, tab_prefixof(ent), c );
+		else
+		fprintf( stderr, "%5d: %5d/\\%03o \"",
+				ent, tab_prefixof(ent), c );
+		de_stack[--stack_top] = '\n';
+		de_stack[--stack_top] = '"';
+		for ( ; ent != NULL;
+			ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
+		stack_top = in_stack(tab_suffixof(ent), stack_top);
+		}
+		fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr );
+		stack_top = STACK_SIZE;
+	}
+	}
+}
+
+int
+in_stack(int c, int stack_top)
+{
+	if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
+		de_stack[--stack_top] = c;
+	} else {
+		switch( c ) {
+		case '\n': de_stack[--stack_top] = 'n'; break;
+		case '\t': de_stack[--stack_top] = 't'; break;
+		case '\b': de_stack[--stack_top] = 'b'; break;
+		case '\f': de_stack[--stack_top] = 'f'; break;
+		case '\r': de_stack[--stack_top] = 'r'; break;
+		case '\\': de_stack[--stack_top] = '\\'; break;
+		default:
+	 	de_stack[--stack_top] = '0' + c % 8;
+	 	de_stack[--stack_top] = '0' + (c / 8) % 8;
+	 	de_stack[--stack_top] = '0' + c / 64;
+	 	break;
+		}
+		de_stack[--stack_top] = '\\';
+	}
+	return stack_top;
+}
+#endif /* DEBUG */
+
+writeerr()
+{
+	perror(ofname);
+	unlink(ofname);
+	exit(1);
+}
+
+copystat(ifname, ofname)
+char *ifname, *ofname;
+{
+	int mode;
+	time_t timep[2];
+	struct stat statbuf;
+
+	fclose(stdout);
+	if (stat(ifname, &statbuf)) {		/* Get stat on input file */
+		perror(ifname);
+		return;
+	}
+	if (!S_ISREG(statbuf.st_mode)) {
+		if (quiet)
+			fprintf(stderr, "%s: ", ifname);
+		fprintf(stderr, " -- not a regular file: unchanged");
+		exit_stat = 1;
+	} else if (exit_stat == 2 && (!force)) {
+		/* No compression: remove file.Z */
+		if (!quiet)
+			fprintf(stderr, " -- file unchanged");
+	} else {			/* Successful Compression */
+		exit_stat = 0;
+		mode = statbuf.st_mode & 07777;
+		if (chmod(ofname, mode))		/* Copy modes */
+			perror(ofname);
+		/* Copy ownership */
+		chown(ofname, statbuf.st_uid, statbuf.st_gid);
+		timep[0] = statbuf.st_atime;
+		timep[1] = statbuf.st_mtime;
+		/* Update last accessed and modified times */
+		utime(ofname, timep);
+
+//		if (unlink(ifname))	/* Remove input file */
+//			perror(ifname);
+	}
+
+	/* Unsuccessful return -- one of the tests failed */
+	if (unlink(ofname))
+		perror(ofname);
+}
+
+/*
+ * This routine returns 1 if we are running in the foreground and stderr
+ * is a tty.
+ */
+foreground()
+{
+	if(bgnd_flag)			/* background? */
+		return 0;
+	else				/* foreground */
+		return isatty(2);	/* and stderr is a tty */
+}
+
+void
+onintr(int x)
+{
+	unlink(ofname);
+	exit(1);
+}
+
+void
+oops(int x)		/* wild pointer -- assume bad input */
+{
+	if (do_decomp == 1)
+		fprintf(stderr, "uncompress: corrupt input\n");
+	unlink(ofname);
+	exit(1);
+}
+
+cl_block ()		/* table clear for block compress */
+{
+	long rat;
+
+	checkpoint = in_count + CHECK_GAP;
+#ifdef DEBUG
+	if ( debug ) {
+		fprintf ( stderr, "count: %ld, ratio: ", in_count );
+		prratio ( stderr, in_count, bytes_out );
+		fprintf ( stderr, "\n");
+	}
+#endif /* DEBUG */
+
+	if (in_count > 0x007fffff) {	/* shift will overflow */
+		rat = bytes_out >> 8;
+		if (rat == 0)		/* Don't divide by zero */
+			rat = 0x7fffffff;
+		else
+			rat = in_count / rat;
+	} else
+		rat = (in_count << 8) / bytes_out;	/* 8 fractional bits */
+	if (rat > ratio)
+		ratio = rat;
+	else {
+		ratio = 0;
+#ifdef DEBUG
+		if (verbose)
+			dump_tab();	/* dump string table */
+#endif
+		cl_hash((count_int)hsize);
+		free_ent = FIRST;
+		clear_flg = 1;
+		output((code_int)CLEAR);
+#ifdef DEBUG
+		if (debug)
+			fprintf(stderr, "clear\n");
+#endif /* DEBUG */
+	}
+}
+
+cl_hash(hsize)		/* reset code table */
+count_int hsize;
+{
+	count_int *htab_p = htab+hsize;
+	long i;
+	long m1 = -1;
+
+	i = hsize - 16;
+ 	do {				/* might use Sys V memset(3) here */
+		*(htab_p-16) = m1;
+		*(htab_p-15) = m1;
+		*(htab_p-14) = m1;
+		*(htab_p-13) = m1;
+		*(htab_p-12) = m1;
+		*(htab_p-11) = m1;
+		*(htab_p-10) = m1;
+		*(htab_p-9) = m1;
+		*(htab_p-8) = m1;
+		*(htab_p-7) = m1;
+		*(htab_p-6) = m1;
+		*(htab_p-5) = m1;
+		*(htab_p-4) = m1;
+		*(htab_p-3) = m1;
+		*(htab_p-2) = m1;
+		*(htab_p-1) = m1;
+		htab_p -= 16;
+	} while ((i -= 16) >= 0);
+	for ( i += 16; i > 0; i-- )
+		*--htab_p = m1;
+}
+
+prratio(stream, num, den)
+FILE *stream;
+long num, den;
+{
+	int q;				/* Doesn't need to be long */
+
+	if(num > 214748L)		/* 2147483647/10000 */
+		q = num / (den / 10000L);
+	else
+		q = 10000L * num / den;	/* Long calculations, though */
+	if (q < 0) {
+		putc('-', stream);
+		q = -q;
+	}
+	fprintf(stream, "%d.%02d%%", q / 100, q % 100);
+}
+
+version()
+{
+	fprintf(stderr, "%s\n", rcs_ident);
+	fprintf(stderr, "Options: ");
+#ifdef DEBUG
+	fprintf(stderr, "DEBUG, ");
+#endif
+#ifdef BSD4_2
+	fprintf(stderr, "BSD4_2, ");
+#endif
+	fprintf(stderr, "BITS = %d\n", BITS);
+}
+
+/*
+ * The revision-history novel:
+ *
+ * $Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $
+ * $Log:	compress.c,v $
+ * Revision 4.0  85/07/30  12:50:00  joe
+ * Removed ferror() calls in output routine on every output except first.
+ * Prepared for release to the world.
+ *
+ * Revision 3.6  85/07/04  01:22:21  joe
+ * Remove much wasted storage by overlaying hash table with the tables
+ * used by decompress: tab_suffix[1<<BITS], stack[8000].  Updated USERMEM
+ * computations.  Fixed dump_tab() DEBUG routine.
+ *
+ * Revision 3.5  85/06/30  20:47:21  jaw
+ * Change hash function to use exclusive-or.  Rip out hash cache.  These
+ * speedups render the megamemory version defunct, for now.  Make decoder
+ * stack global.  Parts of the RCS trunks 2.7, 2.6, and 2.1 no longer apply.
+ *
+ * Revision 3.4  85/06/27  12:00:00  ken
+ * Get rid of all floating-point calculations by doing all compression ratio
+ * calculations in fixed point.
+ *
+ * Revision 3.3  85/06/24  21:53:24  joe
+ * Incorporate portability suggestion for M_XENIX.  Got rid of text on #else
+ * and #endif lines.  Cleaned up #ifdefs for vax and interdata.
+ *
+ * Revision 3.2  85/06/06  21:53:24  jaw
+ * Incorporate portability suggestions for Z8000, IBM PC/XT from mailing list.
+ * Default to "quiet" output (no compression statistics).
+ *
+ * Revision 3.1  85/05/12  18:56:13  jaw
+ * Integrate decompress() stack speedups (from early pointer mods by McKie).
+ * Repair multi-file USERMEM gaffe.  Unify 'force' flags to mimic semantics
+ * of SVR2 'pack'.  Streamline block-compress table clear logic.  Increase
+ * output byte count by magic number size.
+ *
+ * Revision 3.0	84/11/27  11:50:00  petsd!joe
+ * Set HSIZE depending on BITS.  Set BITS depending on USERMEM.  Unrolled
+ * loops in clear routines.  Added "-C" flag for 2.0 compatibility.  Used
+ * unsigned compares on Perkin-Elmer.  Fixed foreground check.
+ *
+ * Revision 2.7	84/11/16  19:35:39  ames!jaw
+ * Cache common hash codes based on input statistics; this improves
+ * performance for low-density raster images.  Pass on #ifdef bundle
+ * from Turkowski.
+ *
+ * Revision 2.6	84/11/05  19:18:21  ames!jaw
+ * Vary size of hash tables to reduce time for small files.
+ * Tune PDP-11 hash function.
+ *
+ * Revision 2.5	84/10/30  20:15:14  ames!jaw
+ * Junk chaining; replace with the simpler (and, on the VAX, faster)
+ * double hashing, discussed within.  Make block compression standard.
+ *
+ * Revision 2.4	84/10/16  11:11:11  ames!jaw
+ * Introduce adaptive reset for block compression, to boost the rate
+ * another several percent.  (See mailing list notes.)
+ *
+ * Revision 2.3	84/09/22  22:00:00  petsd!joe
+ * Implemented "-B" block compress.  Implemented REVERSE sorting of tab_next.
+ * Bug fix for last bits.  Changed fwrite to putchar loop everywhere.
+ *
+ * Revision 2.2	84/09/18  14:12:21  ames!jaw
+ * Fold in news changes, small machine typedef from thomas,
+ * #ifdef interdata from joe.
+ *
+ * Revision 2.1	84/09/10  12:34:56  ames!jaw
+ * Configured fast table lookup for 32-bit machines.
+ * This cuts user time in half for b <= FBITS, and is useful for news batching
+ * from VAX to PDP sites.  Also sped up decompress() [fwrite->putc] and
+ * added signal catcher [plus beef in writeerr()] to delete effluvia.
+ *
+ * Revision 2.0	84/08/28  22:00:00  petsd!joe
+ * Add check for foreground before prompting user.  Insert maxbits into
+ * compressed file.  Force file being uncompressed to end with ".Z".
+ * Added "-c" flag and "zcat".  Prepared for release.
+ *
+ * Revision 1.10  84/08/24  18:28:00  turtlevax!ken
+ * Will only compress regular files (no directories), added a magic number
+ * header (plus an undocumented -n flag to handle old files without headers),
+ * added -f flag to force overwriting of possibly existing destination file,
+ * otherwise the user is prompted for a response.  Will tack on a .Z to a
+ * filename if it doesn't have one when decompressing.  Will only replace
+ * file if it was compressed.
+ *
+ * Revision 1.9  84/08/16  17:28:00  turtlevax!ken
+ * Removed scanargs(), getopt(), added .Z extension and unlimited number of
+ * filenames to compress.  Flags may be clustered (-Ddvb12) or separated
+ * (-D -d -v -b 12), or combination thereof.  Modes and other status is
+ * copied with copystat().  -O bug for 4.2 seems to have disappeared with
+ * 1.8.
+ *
+ * Revision 1.8  84/08/09  23:15:00  joe
+ * Made it compatible with vax version, installed jim's fixes/enhancements
+ *
+ * Revision 1.6  84/08/01  22:08:00  joe
+ * Sped up algorithm significantly by sorting the compress chain.
+ *
+ * Revision 1.5  84/07/13  13:11:00  srd
+ * Added C version of vax asm routines.  Changed structure to arrays to
+ * save much memory.  Do unsigned compares where possible (faster on
+ * Perkin-Elmer)
+ *
+ * Revision 1.4  84/07/05  03:11:11  thomas
+ * Clean up the code a little and lint it.  (Lint complains about all
+ * the regs used in the asm, but I'm not going to "fix" this.)
+ *
+ * Revision 1.3  84/07/05  02:06:54  thomas
+ * Minor fixes.
+ *
+ * Revision 1.2  84/07/05  00:27:27  thomas
+ * Add variable bit length output.
+ */

+ 10 - 0
sys/src/cmd/compress/mkfile

@@ -0,0 +1,10 @@
+</$objtype/mkfile
+
+TARG=compress
+OFILES=compress.$O
+
+BIN=/$objtype/bin
+</sys/src/cmd/mkone
+CC=pcc
+LD=pcc
+CFLAGS=-B -c

+ 1 - 0
sys/src/cmd/grep/grep.h

@@ -85,6 +85,7 @@ EXTERN	union
 } u;
 
 EXTERN	char	*filename;
+EXTERN	char	*pattern;
 EXTERN	Biobuf	bout;
 EXTERN	char	flags[256];
 EXTERN	Re**	follow;

+ 15 - 5
sys/src/cmd/grep/grep.y

@@ -17,8 +17,11 @@
 %token		LBEGIN LEND LDOT LBAD LNEWLINE
 %%
 
-prog:
-	expr newlines
+prog:	/* empty */
+	{
+		yyerror("empty pattern");
+	}
+|	expr newlines
 	{
 		$$.beg = ral(Tend);
 		$$.end = $$.beg;
@@ -117,10 +120,17 @@ newlines:
 void
 yyerror(char *e, ...)
 {
+	va_list args;
+
+	fprint(2, "grep: ");
 	if(filename)
-		fprint(2, "grep: %s:%ld: %s\n", filename, lineno, e);
-	else
-		fprint(2, "grep: %s\n", e);
+		fprint(2, "%s:%ld: ", filename, lineno);
+	else if (pattern)
+		fprint(2, "%s: ", pattern);
+	va_start(args, e);
+	vfprint(2, e, args);
+	va_end(args);
+	fprint(2, "\n");
 	exits("syntax");
 }
 

+ 3 - 1
sys/src/cmd/grep/sub.c

@@ -157,7 +157,9 @@ str2top(char *p)
 	oldtop = topre;
 	input = p;
 	if (*p == '\0')
-		yyerror("empty pattern");
+		yyerror("empty pattern");	/* can't be a file name here */
+	if (!flags['f'])
+		pattern = p;
 	topre.beg = 0;
 	topre.end = 0;
 	yyparse();