xref: /minix/minix/commands/compress/compress.c (revision 433d6423)
1 /* compress - Reduce file size using Modified Lempel-Ziv encoding */
2 
3 /*
4  * compress.c - File compression ala IEEE Computer, June 1984.
5  *
6  * Authors:	Spencer W. Thomas	(decvax!harpo!utah-cs!utah-gr!thomas)
7  *		Jim McKie		(decvax!mcvax!jim)
8  *		Steve Davies		(decvax!vax135!petsd!peora!srd)
9  *		Ken Turkowski		(decvax!decwrl!turtlevax!ken)
10  *		James A. Woods		(decvax!ihnp4!ames!jaw)
11  *		Joe Orost		(decvax!vax135!petsd!joe)
12  *
13  *		Richard Todd		Port to MINIX
14  *		Andy Tanenbaum		Cleanup
15  *
16  *
17  * Algorithm from "A Technique for High Performance Data Compression",
18  * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
19  *
20  * Usage: compress [-dfvc] [-b bits] [file ...]
21  * Inputs:
22  *	-d:	    If given, decompression is done instead.
23  *
24  *      -c:         Write output on stdout.
25  *
26  *      -b:         Parameter limits the max number of bits/code.
27  *
28  *	-f:	    Forces output file to be generated, even if one already
29  *		    exists, and even if no space is saved by compressing.
30  *		    If -f is not used, the user will be prompted if stdin is
31  *		    a tty, otherwise, the output file will not be overwritten.
32  *
33  *      -v:	    Write compression statistics
34  *
35  * 	file ...:   Files to be compressed.  If none specified, stdin
36  *		    is used.
37  * Outputs:
38  *	file.Z:	    Compressed form of file with same mode, owner, and utimes
39  * 	or stdout   (if stdin used as input)
40  *
41  * Assumptions:
42  *	When filenames are given, replaces with the compressed version
43  *	(.Z suffix) only if the file decreases in size.
44  * Algorithm:
45  * 	Modified Lempel-Ziv method (LZW).  Basically finds common
46  * substrings and replaces them with a variable size code.  This is
47  * deterministic, and can be done on the fly.  Thus, the decompression
48  * procedure needs no input table, but tracks the way the table was built.
49  */
50 
51 
52 #define AZTEC86 1
53 
54 #define	min(a,b)	((a>b) ? b : a)
55 
56 /*
57  * Set USERMEM to the maximum amount of physical user memory available
58  * in bytes.  USERMEM is used to determine the maximum BITS that can be used
59  * for compression.
60  *
61  * SACREDMEM is the amount of physical memory saved for others; compress
62  * will hog the rest.
63  */
64 #ifndef SACREDMEM
65 #define SACREDMEM	0
66 #endif
67 
68 #ifndef USERMEM
69 # define USERMEM 	450000	/* default user memory */
70 #endif
71 
72 #define REGISTER register
73 #define DOTZ ".Z"
74 
75 #include <limits.h>
76 #include <dirent.h>
77 
78 /* The default for Minix is -b13, but we can do -b16 if the machine can. */
79 #define DEFAULTBITS 13
80 #if INT_MAX == 32767
81 # define BITS 13
82 #else
83 # define BITS 16
84 #endif
85 
86 #ifdef USERMEM
87 # if USERMEM >= (433484+SACREDMEM)
88 #  define PBITS	16
89 # else
90 #  if USERMEM >= (229600+SACREDMEM)
91 #   define PBITS	15
92 #  else
93 #   if USERMEM >= (127536+SACREDMEM)
94 #    define PBITS	14
95 #   else
96 #    if USERMEM >= (73464+SACREDMEM)
97 #     define PBITS	13
98 #    else
99 #     define PBITS	12
100 #    endif
101 #   endif
102 #  endif
103 # endif
104 # undef USERMEM
105 #endif /* USERMEM */
106 
107 #ifdef PBITS		/* Preferred BITS for this memory size */
108 # ifndef BITS
109 #  define BITS PBITS
110 # endif
111 #endif /* PBITS */
112 
113 #if BITS == 16
114 # define HSIZE	69001		/* 95% occupancy */
115 #endif
116 #if BITS == 15
117 # define HSIZE	35023		/* 94% occupancy */
118 #endif
119 #if BITS == 14
120 # define HSIZE	18013		/* 91% occupancy */
121 #endif
122 #if BITS == 13
123 # define HSIZE	9001		/* 91% occupancy */
124 #endif
125 #if BITS <= 12
126 # define HSIZE	5003		/* 80% occupancy */
127 #endif
128 
129 
130 /*
131  * a code_int must be able to hold 2**BITS values of type int, and also -1
132  */
133 #if BITS > 15
134 typedef long int	code_int;
135 #else
136 typedef int		code_int;
137 #endif
138 
139 #ifdef SIGNED_COMPARE_SLOW
140 typedef unsigned long int count_int;
141 typedef unsigned short int count_short;
142 #else
143 typedef long int	  count_int;
144 #endif
145 
146 #ifdef NO_UCHAR
147  typedef char	char_type;
148 #else
149  typedef	unsigned char	char_type;
150 #endif /* UCHAR */
151 char_type magic_header[] = "\037\235";	/* 1F 9D */
152 
153 /* Defines for third byte of header */
154 #define BIT_MASK	0x1f
155 #define BLOCK_MASK	0x80
156 /* Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
157    a fourth header byte (for expansion).
158 */
159 #define INIT_BITS 9			/* initial number of bits/code */
160 
161 #include <sys/types.h>
162 #include <sys/stat.h>
163 #include <fcntl.h>
164 #include <ctype.h>
165 #include <signal.h>
166 #include <stdlib.h>
167 #include <string.h>
168 #include <unistd.h>
169 #include <utime.h>
170 #include <stdio.h>
171 
172 #define ARGVAL() (*++(*argv) || (--argc && *++argv))
173 
174 int n_bits;				/* number of bits/code */
175 int maxbits = DEFAULTBITS;		/* user settable max # bits/code */
176 code_int maxcode;			/* maximum code, given n_bits */
177 code_int maxmaxcode = 1 << BITS;	/* should NEVER generate this code */
178 #ifdef COMPATIBLE		/* But wrong! */
179 # define MAXCODE(n_bits)	(1 << (n_bits) - 1)
180 #else
181 # define MAXCODE(n_bits)	((1 << (n_bits)) - 1)
182 #endif /* COMPATIBLE */
183 
184 #ifndef AZTEC86
185 	count_int htab [HSIZE];
186 	unsigned short codetab [HSIZE];
187 #else
188 	count_int *htab;
189 	unsigned short *codetab;
190 #	define HTABSIZE ((size_t)(HSIZE*sizeof(count_int)))
191 #	define CODETABSIZE ((size_t)(HSIZE*sizeof(unsigned short)))
192 
193 
194 #define htabof(i)	htab[i]
195 #define codetabof(i)	codetab[i]
196 #endif	/* XENIX_16 */
197 code_int hsize = HSIZE;			/* for dynamic table sizing */
198 count_int fsize;
199 
200 /*
201  * To save much memory, we overlay the table used by compress() with those
202  * used by decompress().  The tab_prefix table is the same size and type
203  * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
204  * get this from the beginning of htab.  The output stack uses the rest
205  * of htab, and contains characters.  There is plenty of room for any
206  * possible stack (stack used to be 8000 characters).
207  */
208 
209 #define tab_prefixof(i)	codetabof(i)
210 #ifdef XENIX_16
211 # define tab_suffixof(i)	((char_type *)htab[(i)>>15])[(i) & 0x7fff]
212 # define de_stack		((char_type *)(htab2))
213 #else	/* Normal machine */
214 # define tab_suffixof(i)	((char_type *)(htab))[i]
215 # define de_stack		((char_type *)&tab_suffixof(1<<BITS))
216 #endif	/* XENIX_16 */
217 
218 code_int free_ent = 0;			/* first unused entry */
219 int exit_stat = 0;
220 
221 int main(int argc, char **argv);
222 void Usage(void);
223 void compress(void);
224 void onintr(int dummy);
225 void oops(int dummy);
226 void output(code_int code);
227 int foreground(void);
228 void decompress(void);
229 code_int getcode(void);
230 void writeerr(void);
231 void copystat(char *ifname, char *ofname);
232 int foreground(void);
233 void cl_block(void);
234 void cl_hash(count_int hsize);
235 void prratio(FILE *stream, long int num, long int den);
236 void version(void);
237 
Usage()238 void Usage() {
239 #ifdef DEBUG
240 fprintf(stderr,"Usage: compress [-dDVfc] [-b maxbits] [file ...]\n");
241 }
242 int debug = 0;
243 #else
244 fprintf(stderr,"Usage: compress [-dfvcV] [-b maxbits] [file ...]\n");
245 }
246 #endif /* DEBUG */
247 int nomagic = 0;	/* Use a 3-byte magic number header, unless old file */
248 int zcat_flg = 0;	/* Write output on stdout, suppress messages */
249 int quiet = 0;		/* don't tell me about compression */
250 
251 /*
252  * block compression parameters -- after all codes are used up,
253  * and compression rate changes, start over.
254  */
255 int block_compress = BLOCK_MASK;
256 int clear_flg = 0;
257 long int ratio = 0;
258 #define CHECK_GAP 10000	/* ratio check interval */
259 count_int checkpoint = CHECK_GAP;
260 /*
261  * the next two codes should not be changed lightly, as they must not
262  * lie within the contiguous general code space.
263  */
264 #define FIRST	257	/* first free entry */
265 #define	CLEAR	256	/* table clear output code */
266 
267 int force = 0;
268 char ofname [100];
269 #ifdef DEBUG
270 int verbose = 0;
271 #endif /* DEBUG */
272 
273 #ifndef METAWARE
274 #ifdef AZTEC86
275 void
276 #else
277 int
278 #endif
279 #ifndef __STDC__
280 (*bgnd_flag)();
281 #else
282 (*bgnd_flag)(int);
283 #endif
284 #endif
285 
286 int do_decomp = 0;
287 
288 
main(argc,argv)289 int main(argc, argv)
290 int argc;
291 char **argv;
292 {
293     int overwrite = 0;	/* Do not overwrite unless given -f flag */
294     char tempname[100];
295     char **filelist, **fileptr;
296     char *cp;
297     struct stat statbuf;
298 #ifndef METAWARE
299     if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
300 	signal ( SIGINT, onintr );
301 	signal ( SIGSEGV, oops );
302     }
303 #endif
304 #ifdef AZTEC86
305 #ifdef METAWARE
306 	_setmode(NULL,_ALL_FILES_BINARY);
307 	_setmode(stdin,_BINARY);
308 	_setmode(stdout,_BINARY);
309 	_setmode(stderr,_TEXT);
310 #endif
311 	if (NULL == (htab = (count_int *)malloc(HTABSIZE)))
312 	{
313 		fprintf(stderr,"Can't allocate htab\n");
314 		exit(1);
315 	}
316 	if (NULL == (codetab = (unsigned short *)malloc(CODETABSIZE)))
317 	{
318 		fprintf(stderr,"Can't allocate codetab\n");
319 		exit(1);
320 	}
321 #endif
322 #ifdef COMPATIBLE
323     nomagic = 1;	/* Original didn't have a magic number */
324 #endif /* COMPATIBLE */
325 
326     filelist = fileptr = (char **)(malloc((size_t)(argc * sizeof(*argv))));
327     *filelist = NULL;
328 
329     if((cp = strrchr(argv[0], '/')) != 0) {
330 	cp++;
331     } else {
332 	cp = argv[0];
333     }
334     if(strcmp(cp, "uncompress") == 0) {
335 	do_decomp = 1;
336     } else if(strcmp(cp, "zcat") == 0) {
337 	do_decomp = 1;
338 	zcat_flg = 1;
339     }
340 
341 #ifdef BSD4_2
342     /* 4.2BSD dependent - take it out if not */
343     setlinebuf( stderr );
344 #endif /* BSD4_2 */
345 
346     /* Argument Processing
347      * All flags are optional.
348      * -D => debug
349      * -V => print Version; debug verbose
350      * -d => do_decomp
351      * -v => unquiet
352      * -f => force overwrite of output file
353      * -n => no header: useful to uncompress old files
354      * -b maxbits => maxbits.  If -b is specified, then maxbits MUST be
355      *	    given also.
356      * -c => cat all output to stdout
357      * -C => generate output compatible with compress 2.0.
358      * if a string is left, must be an input filename.
359      */
360     for (argc--, argv++; argc > 0; argc--, argv++)
361 	{
362 		if (**argv == '-')
363 		{	/* A flag argument */
364 		    while (*++(*argv))
365 			{	/* Process all flags in this arg */
366 				switch (**argv)
367 				{
368 #ifdef DEBUG
369 			    case 'D':
370 					debug = 1;
371 					break;
372 			    case 'V':
373 					verbose = 1;
374 					version();
375 					break;
376 #else
377 			    case 'V':
378 					version();
379 					break;
380 #endif /* DEBUG */
381 			    case 'v':
382 					quiet = 0;
383 					break;
384 			    case 'd':
385 					do_decomp = 1;
386 					break;
387 			    case 'f':
388 			    case 'F':
389 					overwrite = 1;
390 					force = 1;
391 					break;
392 			    case 'n':
393 					nomagic = 1;
394 					break;
395 			    case 'C':
396 					block_compress = 0;
397 					break;
398 			    case 'b':
399 					if (!ARGVAL())
400 					{
401 					    fprintf(stderr, "Missing maxbits\n");
402 					    Usage();
403 					    exit(1);
404 					}
405 					maxbits = atoi(*argv);
406 					goto nextarg;
407 			    case 'c':
408 					zcat_flg = 1;
409 					break;
410 			    case 'q':
411 					quiet = 1;
412 					break;
413 			    default:
414 					fprintf(stderr, "Unknown flag: '%c'; ", **argv);
415 					Usage();
416 					exit(1);
417 				}
418 		    }
419 		}
420 		else
421 		{		/* Input file name */
422 		    *fileptr++ = *argv;	/* Build input file list */
423 		    *fileptr = NULL;
424 		    /* process nextarg; */
425 		}
426 		nextarg: continue;
427     }
428 
429     if(maxbits < INIT_BITS) maxbits = INIT_BITS;
430     if (maxbits > BITS) maxbits = BITS;
431     maxmaxcode = 1 << maxbits;
432 
433     if (*filelist != NULL)
434 	{
435 		for (fileptr = filelist; *fileptr; fileptr++)
436 		{
437 		    exit_stat = 0;
438 		    if (do_decomp != 0)
439 			{			/* DECOMPRESSION */
440 				/* Check for .Z suffix */
441 #ifndef PCDOS
442 				if (strcmp(*fileptr + strlen(*fileptr) - 2, DOTZ) != 0)
443 #else
444 				if (strcmp(*fileptr + strlen(*fileptr) - 1, DOTZ) != 0)
445 #endif
446 				{
447 				    /* No .Z: tack one on */
448 				    strcpy(tempname, *fileptr);
449 #ifndef PCDOS
450 				    strcat(tempname, DOTZ);
451 #else
452 					/* either tack one on or replace last character */
453 					{
454 						char *dot;
455 						if (NULL == (dot = strchr(tempname,'.')))
456 						{
457 							strcat(tempname,".Z");
458 						}
459 						else
460 						/* if there is a dot then either tack a z on
461 						   or replace last character */
462 						{
463 							if (strlen(dot) < 4)
464 								strcat(tempname,DOTZ);
465 							else
466 								dot[3] = 'Z';
467 						}
468 					}
469 #endif
470 				    *fileptr = tempname;
471 				}
472 				/* Open input file */
473 				if ((freopen(*fileptr, "r", stdin)) == NULL)
474 				{
475 					perror(*fileptr); continue;
476 				}
477 				/* Check the magic number */
478 				if (nomagic == 0)
479 				{
480 					unsigned magic1, magic2;
481 				    if (((magic1 = getc(stdin)) != (magic_header[0] & 0xFF))
482 				     || ((magic2 = getc(stdin)) != (magic_header[1] & 0xFF)))
483 					{
484 						fprintf(stderr,
485 						"%s: not in compressed format %x %x\n",
486 					    *fileptr,magic1,magic2);
487 					    continue;
488 				    }
489 				    maxbits = getc(stdin);	/* set -b from file */
490 				    block_compress = maxbits & BLOCK_MASK;
491 				    maxbits &= BIT_MASK;
492 				    maxmaxcode = 1 << maxbits;
493 				    if(maxbits > BITS)
494 					{
495 						fprintf(stderr,
496 					"%s: compressed with %d bits, can only handle %d bits\n",
497 						*fileptr, maxbits, BITS);
498 						continue;
499 				    }
500 				}
501 				/* Generate output filename */
502 				strcpy(ofname, *fileptr);
503 #ifndef PCDOS
504 				ofname[strlen(*fileptr) - 2] = '\0';  /* Strip off .Z */
505 #else
506 				/* kludge to handle various common three character extension */
507 				{
508 					char *dot;
509 					char fixup = '\0';
510 					/* first off, map name to upper case */
511 					for (dot = ofname; *dot; dot++)
512 						*dot = toupper(*dot);
513 					if (NULL == (dot = strchr(ofname,'.')))
514 					{
515 						fprintf(stderr,"Bad filename %s\n",ofname);
516 						exit(1);
517 					}
518 					if (strlen(dot) == 4)
519 					/* we got three letter extensions */
520 					{
521 						if (strcmp(dot,".EXZ") == 0)
522 							fixup = 'E';
523 						else if (strcmp(dot,".COZ") == 0)
524 							fixup = 'M';
525 						else if (strcmp(dot,".BAZ") == 0)
526 							fixup = 'S';
527 						else if (strcmp(dot,".OBZ") == 0)
528 							fixup = 'J';
529 						else if (strcmp(dot,".SYZ") == 0)
530 							fixup = 'S';
531 						else if (strcmp(dot,".DOZ") == 0)
532 							fixup = 'C';
533 
534 					}
535 					/* replace the Z */
536 					ofname[strlen(*fileptr) - 1] = fixup;
537 				}
538 #endif
539 		    } else
540 			{					/* COMPRESSION */
541 				if (strcmp(*fileptr + strlen(*fileptr) - 2, DOTZ) == 0)
542 				{
543 			    	fprintf(stderr, "%s: already has .Z suffix -- no change\n",
544 				    *fileptr);
545 				    continue;
546 				}
547 				/* Open input file */
548 				if ((freopen(*fileptr, "r", stdin)) == NULL)
549 				{
550 				    perror(*fileptr); continue;
551 				}
552 				(void)stat( *fileptr, &statbuf );
553 				fsize = (long) statbuf.st_size;
554 				/*
555 				 * tune hash table size for small files -- ad hoc,
556 				 * but the sizes match earlier #defines, which
557 				 * serve as upper bounds on the number of output codes.
558 				 */
559 				hsize = HSIZE; /*lint -e506 -e712 */
560 				if ( fsize < (1 << 12) )
561 				    hsize = min ( 5003, HSIZE );
562 				else if ( fsize < (1 << 13) )
563 				    hsize = min ( 9001, HSIZE );
564 				else if ( fsize < (1 << 14) )
565 				    hsize = min ( 18013, HSIZE );
566 				else if ( fsize < (1 << 15) )
567 				    hsize = min ( 35023, HSIZE );
568 				else if ( fsize < 47000 )
569 				    hsize = min ( 50021, HSIZE ); /*lint +e506 +e712 */
570 
571 				/* Generate output filename */
572 				strcpy(ofname, *fileptr);
573 #ifndef BSD4_2		/* Short filenames */
574 				if ((cp=strrchr(ofname,'/')) != NULL)
575 					cp++;
576 				else
577 					cp = ofname;
578 				if (strlen(cp) >= NAME_MAX-3)
579 				{
580 				    fprintf(stderr,"%s: filename too long to tack on .Z\n",cp);
581 				    continue;
582 				}
583 #ifdef PCDOS
584 				else
585 				{
586 					/* either tack one on or replace last character */
587 					char *dot;
588 					if (NULL == (dot = strchr(cp,'.')))
589 					{
590 						strcat(cp,".Z");
591 					}
592 					else
593 					/* if there is a dot then either tack a z on
594 					   or replace last character */
595 					{
596 						if (strlen(dot) < 4)
597 							strcat(cp,DOTZ);
598 						else
599 							dot[3] = 'Z';
600 					}
601 				}
602 #endif
603 #endif  /* BSD4_2		Long filenames allowed */
604 #ifndef PCDOS
605 			/* PCDOS takes care of this above */
606 				strcat(ofname, DOTZ);
607 #endif
608 		    }
609 		    /* Check for overwrite of existing file */
610 		    if (overwrite == 0 && zcat_flg == 0)
611 			{
612 				if (stat(ofname, &statbuf) == 0)
613 				{
614 				    char response[2]; int fd;
615 				    response[0] = 'n';
616 				    fprintf(stderr, "%s already exists;", ofname);
617 				    if (foreground())
618 					{
619 						fd = open("/dev/tty", O_RDONLY);
620 						fprintf(stderr,
621 						" do you wish to overwrite %s (y or n)? ", ofname);
622 						fflush(stderr);
623 						(void)read(fd, response, 2);
624 						while (response[1] != '\n')
625 						{
626 						    if (read(fd, response+1, 1) < 0)
627 							{	/* Ack! */
628 								perror("stderr");
629 								break;
630 						    }
631 						}
632 						close(fd);
633 				    }
634 				    if (response[0] != 'y')
635 					{
636 						fprintf(stderr, "\tnot overwritten\n");
637 						continue;
638 				    }
639 				}
640 		    }
641 		    if(zcat_flg == 0)
642 			{		/* Open output file */
643 				if (freopen(ofname, "w", stdout) == NULL)
644 				{
645 				    perror(ofname);
646 				    continue;
647 				}
648 				if(!quiet)
649 					fprintf(stderr, "%s: ", *fileptr);
650 		    }
651 
652 		    /* Actually do the compression/decompression */
653 		    if (do_decomp == 0)
654 				compress();
655 #ifndef DEBUG
656 		    else
657 				decompress();
658 #else
659 		    else if (debug == 0)
660 				decompress();
661 		    else
662 				printcodes();
663 		    if (verbose)
664 				dump_tab();
665 #endif /* DEBUG */
666 		    if(zcat_flg == 0)
667 			{
668 				copystat(*fileptr, ofname);	/* Copy stats */
669 				if((exit_stat == 1) || (!quiet))
670 					putc('\n', stderr);
671 		    }
672 		}
673     } else
674 	{		/* Standard input */
675 		if (do_decomp == 0)
676 		{
677 			compress();
678 #ifdef DEBUG
679 			if(verbose)		dump_tab();
680 #endif /* DEBUG */
681 			if(!quiet)
682 				putc('\n', stderr);
683 		} else
684 		{
685 		    /* Check the magic number */
686 		    if (nomagic == 0)
687 			{
688 				if ((getc(stdin)!=(magic_header[0] & 0xFF))
689 				 || (getc(stdin)!=(magic_header[1] & 0xFF)))
690 				{
691 				    fprintf(stderr, "stdin: not in compressed format\n");
692 				    exit(1);
693 				}
694 				maxbits = getc(stdin);	/* set -b from file */
695 				block_compress = maxbits & BLOCK_MASK;
696 				maxbits &= BIT_MASK;
697 				maxmaxcode = 1 << maxbits;
698 				fsize = 100000;		/* assume stdin large for USERMEM */
699 				if(maxbits > BITS)
700 				{
701 					fprintf(stderr,
702 					"stdin: compressed with %d bits, can only handle %d bits\n",
703 					maxbits, BITS);
704 					exit(1);
705 				}
706 		    }
707 #ifndef DEBUG
708 		    decompress();
709 #else
710 		    if (debug == 0)	decompress();
711 		    else		printcodes();
712 		    if (verbose)	dump_tab();
713 #endif /* DEBUG */
714 		}
715     }
716     return(exit_stat);
717 }
718 
719 static int offset;
720 long int in_count = 1;			/* length of input */
721 long int bytes_out;			/* length of compressed output */
722 long int out_count = 0;			/* # of codes output (for debugging) */
723 
724 /*
725  * compress stdin to stdout
726  *
727  * Algorithm:  use open addressing double hashing (no chaining) on the
728  * prefix code / next character combination.  We do a variant of Knuth's
729  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
730  * secondary probe.  Here, the modular division first probe is gives way
731  * to a faster exclusive-or manipulation.  Also do block compression with
732  * an adaptive reset, whereby the code table is cleared when the compression
733  * ratio decreases, but after the table fills.  The variable-length output
734  * codes are re-sized at this point, and a special CLEAR code is generated
735  * for the decompressor.  Late addition:  construct the table according to
736  * file size for noticeable speed improvement on small files.  Please direct
737  * questions about this implementation to ames!jaw.
738  */
739 
compress()740 void compress()
741 {
742     REGISTER long fcode;
743     REGISTER code_int i = 0;
744     REGISTER int c;
745     REGISTER code_int ent;
746 #ifdef XENIX_16
747     REGISTER code_int disp;
748 #else	/* Normal machine */
749     REGISTER int disp;
750 #endif
751     REGISTER code_int hsize_reg;
752     REGISTER int hshift;
753 
754 #ifndef COMPATIBLE
755     if (nomagic == 0)
756 	{
757 		putc(magic_header[0],stdout);
758 		putc(magic_header[1],stdout);
759 		putc((char)(maxbits | block_compress),stdout);
760 		if(ferror(stdout))
761 			writeerr();
762     }
763 #endif /* COMPATIBLE */
764 
765     offset = 0;
766     bytes_out = 3;		/* includes 3-byte header mojo */
767     out_count = 0;
768     clear_flg = 0;
769     ratio = 0;
770     in_count = 1;
771     checkpoint = CHECK_GAP;
772     maxcode = MAXCODE(n_bits = INIT_BITS);
773     free_ent = ((block_compress) ? FIRST : 256 );
774 
775     ent = getc(stdin);
776 
777     hshift = 0;
778     for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
779     	hshift++;
780     hshift = 8 - hshift;		/* set hash code range bound */
781 
782     hsize_reg = hsize;
783     cl_hash( (count_int) hsize_reg);		/* clear hash table */
784 
785 #ifdef SIGNED_COMPARE_SLOW
786     while ( (c = getc(stdin)) != (unsigned) EOF )
787 #else
788     while ( (c = getc(stdin)) != EOF )
789 #endif
790 	{
791 		in_count++;
792 		fcode = (long) (((long) c << maxbits) + ent);
793 	 	i = ((c << hshift) ^ ent);	/* xor hashing */
794 
795 		if ( htabof (i) == fcode )
796 		{
797 		    ent = codetabof (i);
798 		    continue;
799 		} else if ( (long)htabof (i) < 0 )	/* empty slot */
800 		    goto nomatch;
801 	 	disp = hsize_reg - i;		/* secondary hash (after G. Knott) */
802 		if ( i == 0 )
803 		    disp = 1;
804 probe:
805 		if ( (i -= disp) < 0 )
806 		    i += hsize_reg;
807 
808 		if ( htabof (i) == fcode )
809 		{
810 		    ent = codetabof (i);
811 		    continue;
812 		}
813 		if ( (long)htabof (i) > 0 )
814 		    goto probe;
815 nomatch:
816 		output ( (code_int) ent );
817 		out_count++;
818 	 	ent = c;
819 #ifdef SIGNED_COMPARE_SLOW
820 		if ( (unsigned) free_ent < (unsigned) maxmaxcode)
821 #else
822 		if ( free_ent < maxmaxcode )
823 #endif
824 		{
825 	 	    codetabof (i) = free_ent++;	/* code -> hashtable */
826 		    htabof (i) = fcode;
827 		}
828 		else if ( (count_int)in_count >= checkpoint && block_compress )
829 		    cl_block ();
830     }
831     /*
832      * Put out the final code.
833      */
834     output( (code_int)ent );
835     out_count++;
836     output( (code_int)-1 );
837 
838     /*
839      * Print out stats on stderr
840      */
841     if(zcat_flg == 0 && !quiet)
842 	{
843 #ifdef DEBUG
844 		fprintf( stderr,
845 		"%ld chars in, %ld codes (%ld bytes) out, compression factor: ",
846 		in_count, out_count, bytes_out );
847 		prratio( stderr, in_count, bytes_out );
848 		fprintf( stderr, "\n");
849 		fprintf( stderr, "\tCompression as in compact: " );
850 		prratio( stderr, in_count-bytes_out, in_count );
851 		fprintf( stderr, "\n");
852 		fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
853 		free_ent - 1, n_bits );
854 #else /* !DEBUG */
855 		fprintf( stderr, "Compression: " );
856 		prratio( stderr, in_count-bytes_out, in_count );
857 #endif /* DEBUG */
858     }
859     if(bytes_out > in_count)	/* exit(2) if no savings */
860 		exit_stat = 2;
861     return;
862 }
863 
864 /*****************************************************************
865  * TAG( output )
866  *
867  * Output the given code.
868  * Inputs:
869  * 	code:	A n_bits-bit integer.  If == -1, then EOF.  This assumes
870  *		that n_bits =< (long)wordsize - 1.
871  * Outputs:
872  * 	Outputs code to the file.
873  * Assumptions:
874  *	Chars are 8 bits long.
875  * Algorithm:
876  * 	Maintain a BITS character long buffer (so that 8 codes will
877  * fit in it exactly).  Use the VAX insv instruction to insert each
878  * code in turn.  When the buffer fills up empty it and start over.
879  */
880 
881 static char buf[BITS];
882 
883 #ifndef vax
884 char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
885 char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
886 #endif /* vax */
output(code)887 void output( code )
888 code_int  code;
889 {
890 #ifdef DEBUG
891     static int col = 0;
892 #endif /* DEBUG */
893 
894     /*
895      * On the VAX, it is important to have the REGISTER declarations
896      * in exactly the order given, or the asm will break.
897      */
898     REGISTER int r_off = offset, bits= n_bits;
899     REGISTER char * bp = buf;
900 #ifndef BREAKHIGHC
901 #ifdef METAWARE
902 	int temp;
903 #endif
904 #endif
905 #ifdef DEBUG
906 	if ( verbose )
907 	    fprintf( stderr, "%5d%c", code,
908 		    (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
909 #endif /* DEBUG */
910     if ( code >= 0 )
911 	{
912 #ifdef vax
913 	/* VAX DEPENDENT!! Implementation on other machines is below.
914 	 *
915 	 * Translation: Insert BITS bits from the argument starting at
916 	 * offset bits from the beginning of buf.
917 	 */
918 	0;	/* Work around for pcc -O bug with asm and if stmt */
919 	asm( "insv	4(ap),r11,r10,(r9)" );
920 #else /* not a vax */
921 /*
922  * byte/bit numbering on the VAX is simulated by the following code
923  */
924 	/*
925 	 * Get to the first byte.
926 	 */
927 	bp += (r_off >> 3);
928 	r_off &= 7;
929 	/*
930 	 * Since code is always >= 8 bits, only need to mask the first
931 	 * hunk on the left.
932 	 */
933 #ifndef BREAKHIGHC
934 #ifdef METAWARE
935 	*bp &= rmask[r_off];
936 	temp = (code << r_off) & lmask[r_off];
937 	*bp |= temp;
938 #else
939 	*bp = (*bp & rmask[r_off]) | ((code << r_off) & lmask[r_off]);
940 #endif
941 #else
942 	*bp = (*bp & rmask[r_off]) | ((code << r_off) & lmask[r_off]);
943 #endif
944 	bp++;
945 	bits -= (8 - r_off);
946 	code >>= (8 - r_off);
947 	/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
948 	if ( bits >= 8 )
949 	{
950 	    *bp++ = code;
951 	    code >>= 8;
952 	    bits -= 8;
953 	}
954 	/* Last bits. */
955 	if(bits)
956 	    *bp = code;
957 #endif /* vax */
958 	offset += n_bits;
959 	if ( offset == (n_bits << 3) )
960 	{
961 	    bp = buf;
962 	    bits = n_bits;
963 	    bytes_out += bits;
964 	    do
965 		putc(*bp++,stdout);
966 	    while(--bits);
967 	    offset = 0;
968 	}
969 
970 	/*
971 	 * If the next entry is going to be too big for the code size,
972 	 * then increase it, if possible.
973 	 */
974 	if ( free_ent > maxcode || (clear_flg > 0))
975 	{
976 	    /*
977 	     * Write the whole buffer, because the input side won't
978 	     * discover the size increase until after it has read it.
979 	     */
980 	    if ( offset > 0 )
981 		{
982 			if( fwrite( buf, (size_t)1, (size_t)n_bits, stdout ) != n_bits)
983 				writeerr();
984 			bytes_out += n_bits;
985 	    }
986 	    offset = 0;
987 
988 	    if ( clear_flg )
989 		{
990     	        maxcode = MAXCODE (n_bits = INIT_BITS);
991 		        clear_flg = 0;
992 	    }
993 	    else
994 		{
995 	    	n_bits++;
996 	    	if ( n_bits == maxbits )
997 			    maxcode = maxmaxcode;
998 	    	else
999 			    maxcode = MAXCODE(n_bits);
1000 	    }
1001 #ifdef DEBUG
1002 	    if ( debug )
1003 		{
1004 			fprintf( stderr, "\nChange to %d bits\n", n_bits );
1005 			col = 0;
1006 	    }
1007 #endif /* DEBUG */
1008 	}
1009     } else
1010 	{
1011 	/*
1012 	 * At EOF, write the rest of the buffer.
1013 	 */
1014 	if ( offset > 0 )
1015 	    fwrite( buf, (size_t)1, (size_t)(offset + 7) / 8, stdout );
1016 	bytes_out += (offset + 7) / 8;
1017 	offset = 0;
1018 	fflush( stdout );
1019 #ifdef DEBUG
1020 	if ( verbose )
1021 	    fprintf( stderr, "\n" );
1022 #endif /* DEBUG */
1023 	if( ferror( stdout ) )
1024 		writeerr();
1025     }
1026 }
1027 /*
1028  * Decompress stdin to stdout.  This routine adapts to the codes in the
1029  * file building the "string" table on-the-fly; requiring no table to
1030  * be stored in the compressed file.  The tables used herein are shared
1031  * with those of the compress() routine.  See the definitions above.
1032  */
1033 
decompress()1034 void decompress() {
1035     REGISTER char_type *stackp;
1036     REGISTER int finchar;
1037     REGISTER code_int code, oldcode, incode;
1038 
1039     /*
1040      * As above, initialize the first 256 entries in the table.
1041      */
1042     maxcode = MAXCODE(n_bits = INIT_BITS);
1043     for ( code = 255; code >= 0; code-- ) {
1044 	tab_prefixof(code) = 0;
1045 	tab_suffixof(code) = (char_type)code;
1046     }
1047     free_ent = ((block_compress) ? FIRST : 256 );
1048 
1049     finchar = oldcode = getcode();
1050     if(oldcode == -1)	/* EOF already? */
1051 	return;			/* Get out of here */
1052     putc( (char)finchar,stdout );		/* first code must be 8 bits = char */
1053     if(ferror(stdout))		/* Crash if can't write */
1054 	writeerr();
1055     stackp = de_stack;
1056 
1057     while ( (code = getcode()) > -1 ) {
1058 
1059 	if ( (code == CLEAR) && block_compress ) {
1060 	    for ( code = 255; code >= 0; code-- )
1061 		tab_prefixof(code) = 0;
1062 	    clear_flg = 1;
1063 	    free_ent = FIRST - 1;
1064 	    if ( (code = getcode ()) == -1 )	/* O, untimely death! */
1065 		break;
1066 	}
1067 	incode = code;
1068 	/*
1069 	 * Special case for KwKwK string.
1070 	 */
1071 	if ( code >= free_ent ) {
1072             *stackp++ = finchar;
1073 	    code = oldcode;
1074 	}
1075 
1076 	/*
1077 	 * Generate output characters in reverse order
1078 	 */
1079 #ifdef SIGNED_COMPARE_SLOW
1080 	while ( ((unsigned long)code) >= ((unsigned long)256) ) {
1081 #else
1082 	while ( code >= 256 ) {
1083 #endif
1084 	    *stackp++ = tab_suffixof(code);
1085 	    code = tab_prefixof(code);
1086 	}
1087 	*stackp++ = finchar = tab_suffixof(code);
1088 
1089 	/*
1090 	 * And put them out in forward order
1091 	 */
1092 	do
1093 	    putc ( *--stackp ,stdout);
1094 	while ( stackp > de_stack );
1095 
1096 	/*
1097 	 * Generate the new entry.
1098 	 */
1099 	if ( (code=free_ent) < maxmaxcode )
1100 	{
1101 	    tab_prefixof(code) = (unsigned short)oldcode;
1102 	    tab_suffixof(code) = finchar;
1103 	    free_ent = code+1;
1104 	}
1105 	/*
1106 	 * Remember previous code.
1107 	 */
1108 	oldcode = incode;
1109     }
1110     fflush( stdout );
1111     if(ferror(stdout))
1112 	writeerr();
1113 }
1114 
1115 /*****************************************************************
1116  * TAG( getcode )
1117  *
1118  * Read one code from the standard input.  If EOF, return -1.
1119  * Inputs:
1120  * 	stdin
1121  * Outputs:
1122  * 	code or -1 is returned.
1123  */
1124 
1125 code_int
1126 getcode()
1127 {
1128     /*
1129      * On the VAX, it is important to have the REGISTER declarations
1130      * in exactly the order given, or the asm will break.
1131      */
1132     REGISTER code_int code;
1133     static int offset = 0, size = 0;
1134     static char_type buf[BITS];
1135     REGISTER int r_off, bits;
1136     REGISTER char_type *bp = buf;
1137 
1138     if ( clear_flg > 0 || offset >= size || free_ent > maxcode )
1139 	{
1140 		/*
1141 		 * If the next entry will be too big for the current code
1142 		 * size, then we must increase the size.  This implies reading
1143 		 * a new buffer full, too.
1144 		 */
1145 		if ( free_ent > maxcode )
1146 		{
1147 		    n_bits++;
1148 		    if ( n_bits == maxbits )
1149 				maxcode = maxmaxcode;	/* won't get any bigger now */
1150 		    else
1151 				maxcode = MAXCODE(n_bits);
1152 		}
1153 		if ( clear_flg > 0)
1154 		{
1155     	    maxcode = MAXCODE (n_bits = INIT_BITS);
1156 		    clear_flg = 0;
1157 		}
1158 		size = fread( buf, (size_t)1, (size_t)n_bits, stdin );
1159 		if ( size <= 0 )
1160 		    return -1;			/* end of file */
1161 		offset = 0;
1162 		/* Round size down to integral number of codes */
1163 		size = (size << 3) - (n_bits - 1);
1164     }
1165     r_off = offset;
1166     bits = n_bits;
1167 #ifdef vax
1168     asm( "extzv   r10,r9,(r8),r11" );
1169 #else /* not a vax */
1170 	/*
1171 	 * Get to the first byte.
1172 	 */
1173 	bp += (r_off >> 3);
1174 	r_off &= 7;
1175 	/* Get first part (low order bits) */
1176 #ifdef NO_UCHAR
1177 	code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
1178 #else
1179 	code = (*bp++ >> r_off);
1180 #endif /* NO_UCHAR */
1181 	bits -= (8 - r_off);
1182 	r_off = 8 - r_off;		/* now, offset into code word */
1183 	/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
1184 	if ( bits >= 8 )
1185 	{
1186 #ifdef NO_UCHAR
1187 	    code |= (*bp++ & 0xff) << r_off;
1188 #else
1189 	    code |= *bp++ << r_off;
1190 #endif /* NO_UCHAR */
1191 	    r_off += 8;
1192 	    bits -= 8;
1193 	}
1194 	/* high order bits. */
1195 	code |= (*bp & rmask[bits]) << r_off;
1196 #endif /* vax */
1197     offset += n_bits;
1198 
1199     return code;
1200 }
1201 
1202 #ifndef AZTEC86
1203 char *
1204 strrchr(s, c)		/* For those who don't have it in libc.a */
1205 REGISTER char *s, c;
1206 {
1207 	char *p;
1208 	for (p = NULL; *s; s++)
1209 	    if (*s == c)
1210 		p = s;
1211 	return(p);
1212 }
1213 #endif
1214 
1215 
1216 #ifndef METAWARE
1217 #ifdef DEBUG
1218 printcodes()
1219 {
1220     /*
1221      * Just print out codes from input file.  For debugging.
1222      */
1223     code_int code;
1224     int col = 0, bits;
1225 
1226     bits = n_bits = INIT_BITS;
1227     maxcode = MAXCODE(n_bits);
1228     free_ent = ((block_compress) ? FIRST : 256 );
1229     while ( ( code = getcode() ) >= 0 ) {
1230 	if ( (code == CLEAR) && block_compress ) {
1231    	    free_ent = FIRST - 1;
1232    	    clear_flg = 1;
1233 	}
1234 	else if ( free_ent < maxmaxcode )
1235 	    free_ent++;
1236 	if ( bits != n_bits ) {
1237 	    fprintf(stderr, "\nChange to %d bits\n", n_bits );
1238 	    bits = n_bits;
1239 	    col = 0;
1240 	}
1241 	fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
1242     }
1243     putc( '\n', stderr );
1244     exit( 0 );
1245 }
1246 #ifdef DEBUG2
1247 code_int sorttab[1<<BITS];	/* sorted pointers into htab */
1248 #define STACK_SIZE	500
1249 static char stack[STACK_SIZE];
1250 /* dumptab doesn't use main stack now -prevents distressing crashes */
1251 dump_tab()	/* dump string table */
1252 {
1253     REGISTER int i, first;
1254     REGISTER ent;
1255     int stack_top = STACK_SIZE;
1256     REGISTER c;
1257 
1258     if(do_decomp == 0) {	/* compressing */
1259 	REGISTER int flag = 1;
1260 
1261 	for(i=0; i<hsize; i++) {	/* build sort pointers */
1262 		if((long)htabof(i) >= 0) {
1263 			sorttab[codetabof(i)] = i;
1264 		}
1265 	}
1266 	first = block_compress ? FIRST : 256;
1267 	for(i = first; i < free_ent; i++) {
1268 		fprintf(stderr, "%5d: \"", i);
1269 		stack[--stack_top] = '\n';
1270 		stack[--stack_top] = '"'; /* " */
1271 		stack_top = in_stack((int)(htabof(sorttab[i])>>maxbits)&0xff,
1272                                      stack_top);
1273 		for(ent=htabof(sorttab[i]) & ((1<<maxbits)-1);
1274 		    ent > 256;
1275 		    ent=htabof(sorttab[ent]) & ((1<<maxbits)-1)) {
1276 			stack_top = in_stack((int)(htabof(sorttab[ent]) >> maxbits),
1277 						stack_top);
1278 		}
1279 		stack_top = in_stack(ent, stack_top);
1280 		fwrite( &stack[stack_top], (size_t)1, (size_t)(STACK_SIZE-stack_top), stderr);
1281 	   	stack_top = STACK_SIZE;
1282 	}
1283    } else if(!debug) {	/* decompressing */
1284 
1285        for ( i = 0; i < free_ent; i++ ) {
1286 	   ent = i;
1287 	   c = tab_suffixof(ent);
1288 	   if ( isascii(c) && isprint(c) )
1289 	       fprintf( stderr, "%5d: %5d/'%c'  \"",
1290 			   ent, tab_prefixof(ent), c );
1291 	   else
1292 	       fprintf( stderr, "%5d: %5d/\\%03o \"",
1293 			   ent, tab_prefixof(ent), c );
1294 	   stack[--stack_top] = '\n';
1295 	   stack[--stack_top] = '"'; /* " */
1296 	   for ( ; ent != NULL;
1297 		   ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
1298 	       stack_top = in_stack(tab_suffixof(ent), stack_top);
1299 	   }
1300 	   fwrite( &stack[stack_top], (size_t)1, (size_t)(STACK_SIZE - stack_top), stderr );
1301 	   stack_top = STACK_SIZE;
1302        }
1303     }
1304 }
1305 
1306 int
1307 in_stack(c, stack_top)
1308 	REGISTER int c, stack_top;
1309 {
1310 	if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
1311 	    stack[--stack_top] = c;
1312 	} else {
1313 	    switch( c ) {
1314 	    case '\n': stack[--stack_top] = 'n'; break;
1315 	    case '\t': stack[--stack_top] = 't'; break;
1316 	    case '\b': stack[--stack_top] = 'b'; break;
1317 	    case '\f': stack[--stack_top] = 'f'; break;
1318 	    case '\r': stack[--stack_top] = 'r'; break;
1319 	    case '\\': stack[--stack_top] = '\\'; break;
1320 	    default:
1321 	 	stack[--stack_top] = '0' + c % 8;
1322 	 	stack[--stack_top] = '0' + (c / 8) % 8;
1323 	 	stack[--stack_top] = '0' + c / 64;
1324 	 	break;
1325 	    }
1326 	    stack[--stack_top] = '\\';
1327 	}
1328 	if (stack_top<0) {
1329 	    fprintf(stderr,"dump_tab stack overflow!!!\n");
1330 	    exit(1);
1331 	}
1332 	return stack_top;
1333 }
1334 #else
1335 dump_tab() {}
1336 #endif /* DEBUG2 */
1337 #endif /* DEBUG */
1338 #endif /* METAWARE */
1339 
1340 void writeerr()
1341 {
1342     perror ( ofname );
1343     unlink ( ofname );
1344     exit ( 1 );
1345 }
1346 
1347 void copystat(ifname, ofname)
1348 char *ifname, *ofname;
1349 {
1350     struct stat statbuf;
1351     int mode;
1352 #ifndef AZTEC86
1353     time_t timep[2];
1354 #else
1355 	unsigned long timep[2];
1356 #endif
1357     fflush(stdout);
1358     close(fileno(stdout));
1359     if (stat(ifname, &statbuf))
1360 	{		/* Get stat on input file */
1361 		perror(ifname);
1362 		return;
1363     }
1364 #ifndef PCDOS
1365     /* meddling with UNIX-style file modes */
1366     if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/)
1367 	{
1368 		if(quiet)
1369 	    	fprintf(stderr, "%s: ", ifname);
1370 		fprintf(stderr, " -- not a regular file: unchanged");
1371 		exit_stat = 1;
1372     } else if (statbuf.st_nlink > 1)
1373 	{
1374 		if(quiet)
1375 	    	fprintf(stderr, "%s: ", ifname);
1376 		fprintf(stderr, " -- has %d other links: unchanged",
1377 		statbuf.st_nlink - 1);
1378 		exit_stat = 1;
1379     } else
1380 #endif
1381 	if (exit_stat == 2 && (!force))
1382 	{ /* No compression: remove file.Z */
1383 		if(!quiet)
1384 			fprintf(stderr, " -- file unchanged");
1385     } else
1386 	{			/* ***** Successful Compression ***** */
1387 		exit_stat = 0;
1388 #ifndef PCDOS
1389 		mode = statbuf.st_mode & 07777;
1390 #else
1391 		mode = statbuf.st_attr & 07777;
1392 #endif
1393 		if (chmod(ofname, mode))		/* Copy modes */
1394 		    perror(ofname);
1395 #ifndef PCDOS
1396 		chown(ofname, statbuf.st_uid, statbuf.st_gid);	/* Copy ownership */
1397 		timep[0] = statbuf.st_atime;
1398 		timep[1] = statbuf.st_mtime;
1399 #else
1400 		timep[0] = statbuf.st_mtime;
1401 		timep[1] = statbuf.st_mtime;
1402 #endif
1403 		utime(ofname, (struct utimbuf *)timep);	/* Update last accessed and modified times */
1404 /*
1405 		if (unlink(ifname))
1406 		    perror(ifname);
1407 */
1408 		if(!quiet) {
1409 		    if(do_decomp == 0)
1410 			fprintf(stderr, " -- compressed to %s", ofname);
1411 		    else
1412 			fprintf(stderr, " -- decompressed to %s", ofname);
1413 		}
1414 		return;		/* Successful return */
1415     }
1416 
1417     /* Unsuccessful return -- one of the tests failed */
1418     if (unlink(ofname))
1419 		perror(ofname);
1420 }
1421 /*
1422  * This routine returns 1 if we are running in the foreground and stderr
1423  * is a tty.
1424  */
1425 int foreground()
1426 {
1427 #ifndef METAWARE
1428 	if(bgnd_flag) {	/* background? */
1429 		return(0);
1430 	} else {			/* foreground */
1431 #endif
1432 		if(isatty(2)) {		/* and stderr is a tty */
1433 			return(1);
1434 		} else {
1435 			return(0);
1436 		}
1437 #ifndef METAWARE
1438 	}
1439 #endif
1440 }
1441 #ifndef METAWARE
1442 void onintr (dummy)
1443 int dummy; /* to keep the compiler happy */
1444 {
1445 	(void)signal(SIGINT,SIG_IGN);
1446     unlink ( ofname );
1447     exit ( 1 );
1448 }
1449 
1450 void oops (dummy)	/* wild pointer -- assume bad input */
1451 int dummy; /* to keep the compiler happy */
1452 {
1453 	(void)signal(SIGSEGV,SIG_IGN);
1454     if ( do_decomp == 1 )
1455     	fprintf ( stderr, "uncompress: corrupt input\n" );
1456     unlink ( ofname );
1457     exit ( 1 );
1458 }
1459 #endif
1460 void cl_block ()		/* table clear for block compress */
1461 {
1462     REGISTER long int rat;
1463 
1464     checkpoint = in_count + CHECK_GAP;
1465 #ifdef DEBUG
1466 	if ( debug ) {
1467     		fprintf ( stderr, "count: %ld, ratio: ", in_count );
1468      		prratio ( stderr, in_count, bytes_out );
1469 		fprintf ( stderr, "\n");
1470 	}
1471 #endif /* DEBUG */
1472 
1473     if(in_count > 0x007fffff) {	/* shift will overflow */
1474 	rat = bytes_out >> 8;
1475 	if(rat == 0) {		/* Don't divide by zero */
1476 	    rat = 0x7fffffff;
1477 	} else {
1478 	    rat = in_count / rat;
1479 	}
1480     } else {
1481 	rat = (in_count << 8) / bytes_out;	/* 8 fractional bits */
1482     }
1483     if ( rat > ratio ) {
1484 	ratio = rat;
1485     } else {
1486 	ratio = 0;
1487 #ifdef DEBUG
1488 	if(verbose)
1489 		dump_tab();	/* dump string table */
1490 #endif
1491  	cl_hash ( (count_int) hsize );
1492 	free_ent = FIRST;
1493 	clear_flg = 1;
1494 	output ( (code_int) CLEAR );
1495 #ifdef DEBUG
1496 	if(debug)
1497     		fprintf ( stderr, "clear\n" );
1498 #endif /* DEBUG */
1499     }
1500 }
1501 
1502 void cl_hash(hsize)		/* reset code table */
1503 	REGISTER count_int hsize;
1504 {
1505 #ifdef AZTEC86
1506 #ifdef PCDOS
1507 	/* This function only in PC-DOS lib, not in MINIX lib */
1508 	memset(htab,-1, hsize * sizeof(count_int));
1509 #else
1510 /* MINIX and all non-PC machines do it this way */
1511 #ifndef XENIX_16	/* Normal machine */
1512 	REGISTER count_int *htab_p = htab+hsize;
1513 #else
1514 	REGISTER j;
1515 	REGISTER long k = hsize;
1516 	REGISTER count_int *htab_p;
1517 #endif
1518 	REGISTER long i;
1519 	REGISTER long m1 = -1;
1520 
1521 #ifdef XENIX_16
1522     for(j=0; j<=8 && k>=0; j++,k-=8192)
1523 	{
1524 		i = 8192;
1525 		if(k < 8192)
1526 		{
1527 			i = k;
1528 		}
1529 		htab_p = &(htab[j][i]);
1530 		i -= 16;
1531 		if(i > 0)
1532 		{
1533 #else
1534 	i = hsize - 16;
1535 #endif
1536 	 	do
1537 		{				/* might use Sys V memset(3) here */
1538 			*(htab_p-16) = m1;
1539 			*(htab_p-15) = m1;
1540 			*(htab_p-14) = m1;
1541 			*(htab_p-13) = m1;
1542 			*(htab_p-12) = m1;
1543 			*(htab_p-11) = m1;
1544 			*(htab_p-10) = m1;
1545 			*(htab_p-9) = m1;
1546 			*(htab_p-8) = m1;
1547 			*(htab_p-7) = m1;
1548 			*(htab_p-6) = m1;
1549 			*(htab_p-5) = m1;
1550 			*(htab_p-4) = m1;
1551 			*(htab_p-3) = m1;
1552 			*(htab_p-2) = m1;
1553 			*(htab_p-1) = m1;
1554 			htab_p -= 16;
1555 		} while ((i -= 16) >= 0);
1556 #ifdef XENIX_16
1557 		}
1558     }
1559 #endif
1560 	for ( i += 16; i > 0; i-- )
1561 		*--htab_p = m1;
1562 #endif
1563 #endif
1564 }
1565 
1566 void prratio(stream, num, den)
1567 FILE *stream;
1568 long int num;
1569 long int den;
1570 {
1571 	REGISTER int q;			/* Doesn't need to be long */
1572 	if(num > 214748L)
1573 	{		/* 2147483647/10000 */
1574 		q = (int)(num / (den / 10000L));
1575 	} else
1576 	{
1577 		q = (int)(10000L * num / den);		/* Long calculations, though */
1578 	}
1579 	if (q < 0)
1580 	{
1581 		putc('-', stream);
1582 		q = -q;
1583 	}
1584 	fprintf(stream, "%d.%02d%c", q / 100, q % 100, '%');
1585 }
1586 
1587 void version()
1588 {
1589 	fprintf(stderr, "compress 4.1\n");
1590 	fprintf(stderr, "Options: ");
1591 #ifdef vax
1592 	fprintf(stderr, "vax, ");
1593 #endif
1594 #ifdef __minix
1595 	fprintf(stderr, "MINIX, ");
1596 #endif
1597 #ifdef NO_UCHAR
1598 	fprintf(stderr, "NO_UCHAR, ");
1599 #endif
1600 #ifdef SIGNED_COMPARE_SLOW
1601 	fprintf(stderr, "SIGNED_COMPARE_SLOW, ");
1602 #endif
1603 #ifdef XENIX_16
1604 	fprintf(stderr, "XENIX_16, ");
1605 #endif
1606 #ifdef COMPATIBLE
1607 	fprintf(stderr, "COMPATIBLE, ");
1608 #endif
1609 #ifdef DEBUG
1610 	fprintf(stderr, "DEBUG, ");
1611 #endif
1612 #ifdef BSD4_2
1613 	fprintf(stderr, "BSD4_2, ");
1614 #endif
1615 	fprintf(stderr, "BITS = %d\n", BITS);
1616 }
1617 /* End of text from uok.UUCP:net.sources */
1618 
1619