1 /*
2 * Copyright (c) 1985, 1986 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * James A. Woods, derived from original work by Spencer Thomas
7 * and Joseph Orost.
8 *
9 * Redistribution and use in source and binary forms are permitted
10 * provided that: (1) source distributions retain this entire copyright
11 * notice and comment, and (2) distributions including binaries display
12 * the following acknowledgement: ``This product includes software
13 * developed by the University of California, Berkeley and its contributors''
14 * in the documentation or other materials provided with the distribution
15 * and in all advertising materials mentioning features or use of this
16 * software. Neither the name of the University nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 */
23
24 #ifndef lint
25 char copyright[] =
26 "@(#) Copyright (c) 1985, 1986 The Regents of the University of California.\n\
27 All rights reserved.\n";
28 #endif /* not lint */
29
30 #ifndef lint
31 static char sccsid[] = "@(#)compress.c 5.12 (Berkeley) 6/1/90";
32 #endif /* not lint */
33
34 /* This version of Compress has been hacked around considerably - May 1994 */
35
36 /*
37 * Compress - data compression program
38 */
39
40 /*
41 * machine variants which require cc -Dmachine: pdp11, z8000, pcxt
42 */
43
44 #define min(a,b) ((a>b) ? b : a)
45
46 /*
47 * Set USERMEM to the maximum amount of physical user memory available
48 * in bytes. USERMEM is used to determine the maximum BITS that can be used
49 * for compression.
50 *
51 * SACREDMEM is the amount of physical memory saved for others; compress
52 * will hog the rest.
53 */
54 #ifndef SACREDMEM
55 #define SACREDMEM 0
56 #endif
57
58 #ifndef USERMEM
59 # define USERMEM 450000 /* default user memory */
60 #endif
61
62 #ifdef interdata /* (Perkin-Elmer) */
63 #define SIGNED_COMPARE_SLOW /* signed compare is slower than unsigned */
64 #endif
65
66 #ifdef pdp11
67 # define BITS 12 /* max bits/code for 16-bit machine */
68 # define NO_UCHAR /* also if "unsigned char" functions as signed char */
69 # undef USERMEM
70 #endif /* pdp11 */ /* don't forget to compile with -i */
71
72 #ifdef z8000
73 # define BITS 12
74 # undef vax /* weird preprocessor */
75 # undef USERMEM
76 #endif /* z8000 */
77
78 #ifdef pcxt
79 # define BITS 12
80 # undef USERMEM
81 #endif /* pcxt */
82
83 #ifdef USERMEM
84 # if USERMEM >= (433484+SACREDMEM)
85 # define PBITS 16
86 # else
87 # if USERMEM >= (229600+SACREDMEM)
88 # define PBITS 15
89 # else
90 # if USERMEM >= (127536+SACREDMEM)
91 # define PBITS 14
92 # else
93 # if USERMEM >= (73464+SACREDMEM)
94 # define PBITS 13
95 # else
96 # define PBITS 12
97 # endif
98 # endif
99 # endif
100 # endif
101 # undef USERMEM
102 #endif /* USERMEM */
103
104 #ifdef PBITS /* Preferred BITS for this memory size */
105 # ifndef BITS
106 # define BITS PBITS
107 # endif BITS
108 #endif /* PBITS */
109
110 #if BITS == 16
111 # define HSIZE 69001 /* 95% occupancy */
112 #endif
113 #if BITS == 15
114 # define HSIZE 35023 /* 94% occupancy */
115 #endif
116 #if BITS == 14
117 # define HSIZE 18013 /* 91% occupancy */
118 #endif
119 #if BITS == 13
120 # define HSIZE 9001 /* 91% occupancy */
121 #endif
122 #if BITS <= 12
123 # define HSIZE 5003 /* 80% occupancy */
124 #endif
125
126 #ifdef M_XENIX /* Stupid compiler can't handle arrays with */
127 # if BITS == 16 /* more than 65535 bytes - so we fake it */
128 # define XENIX_16
129 # else
130 # if BITS > 13 /* Code only handles BITS = 12, 13, or 16 */
131 # define BITS 13
132 # endif
133 # endif
134 #endif
135
136 /*
137 * a code_int must be able to hold 2**BITS values of type int, and also -1
138 */
139 #if BITS > 15
140 typedef long int code_int;
141 #else
142 typedef int code_int;
143 #endif
144
145 #ifdef SIGNED_COMPARE_SLOW
146 typedef unsigned long int count_int;
147 typedef unsigned short int count_short;
148 #else
149 typedef long int count_int;
150 #endif
151
152 #ifdef NO_UCHAR
153 typedef char char_type;
154 #else
155 typedef unsigned char char_type;
156 #endif /* UCHAR */
157 char_type magic_header[] = { "\037\235" }; /* 1F 9D */
158
159 /* Defines for third byte of header */
160 #define BIT_MASK 0x1f
161 #define BLOCK_MASK 0x80
162 /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
163 a fourth header byte (for expansion).
164 */
165 #define INIT_BITS 9 /* initial number of bits/code */
166
167 /*
168 * compress.c - File compression ala IEEE Computer, June 1984.
169 *
170 * Authors: Spencer W. Thomas (decvax!utah-cs!thomas)
171 * Jim McKie (decvax!mcvax!jim)
172 * Steve Davies (decvax!vax135!petsd!peora!srd)
173 * Ken Turkowski (decvax!decwrl!turtlevax!ken)
174 * James A. Woods (decvax!ihnp4!ames!jaw)
175 * Joe Orost (decvax!vax135!petsd!joe)
176 *
177 * $Header: /home/wtanksle/cvs/omega/compress.c,v 1.2 1998/08/08 10:47:56 wtanksle Exp $
178 * $Log: compress.c,v $
179 * Revision 1.2 1998/08/08 10:47:56 wtanksle
180 * Added a MAJOR (contributed) patch which permitted color under ncurses
181 * systems. VERY impressive, and credit will be given (if only I could remember
182 * the author's name right now!).
183 *
184 * Revision 4.0 85/07/30 12:50:00 joe
185 * Removed ferror() calls in output routine on every output except first.
186 * Prepared for release to the world.
187 *
188 * Revision 3.6 85/07/04 01:22:21 joe
189 * Remove much wasted storage by overlaying hash table with the tables
190 * used by decompress: tab_suffix[1<<BITS], stack[8000]. Updated USERMEM
191 * computations. Fixed dump_tab() DEBUG routine.
192 *
193 * Revision 3.5 85/06/30 20:47:21 jaw
194 * Change hash function to use exclusive-or. Rip out hash cache. These
195 * speedups render the megamemory version defunct, for now. Make decoder
196 * stack global. Parts of the RCS trunks 2.7, 2.6, and 2.1 no longer apply.
197 *
198 * Revision 3.4 85/06/27 12:00:00 ken
199 * Get rid of all floating-point calculations by doing all compression ratio
200 * calculations in fixed point.
201 *
202 * Revision 3.3 85/06/24 21:53:24 joe
203 * Incorporate portability suggestion for M_XENIX. Got rid of text on #else
204 * and #endif lines. Cleaned up #ifdefs for vax and interdata.
205 *
206 * Revision 3.2 85/06/06 21:53:24 jaw
207 * Incorporate portability suggestions for Z8000, IBM PC/XT from mailing list.
208 * Default to "quiet" output (no compression statistics).
209 *
210 * Revision 3.1 85/05/12 18:56:13 jaw
211 * Integrate decompress() stack speedups (from early pointer mods by McKie).
212 * Repair multi-file USERMEM gaffe. Unify 'force' flags to mimic semantics
213 * of SVR2 'pack'. Streamline block-compress table clear logic. Increase
214 * output byte count by magic number size.
215 *
216 * Revision 3.0 84/11/27 11:50:00 petsd!joe
217 * Set HSIZE depending on BITS. Set BITS depending on USERMEM. Unrolled
218 * loops in clear routines. Added "-C" flag for 2.0 compatibility. Used
219 * unsigned compares on Perkin-Elmer. Fixed foreground check.
220 *
221 * Revision 2.7 84/11/16 19:35:39 ames!jaw
222 * Cache common hash codes based on input statistics; this improves
223 * performance for low-density raster images. Pass on #ifdef bundle
224 * from Turkowski.
225 *
226 * Revision 2.6 84/11/05 19:18:21 ames!jaw
227 * Vary size of hash tables to reduce time for small files.
228 * Tune PDP-11 hash function.
229 *
230 * Revision 2.5 84/10/30 20:15:14 ames!jaw
231 * Junk chaining; replace with the simpler (and, on the VAX, faster)
232 * double hashing, discussed within. Make block compression standard.
233 *
234 * Revision 2.4 84/10/16 11:11:11 ames!jaw
235 * Introduce adaptive reset for block compression, to boost the rate
236 * another several percent. (See mailing list notes.)
237 *
238 * Revision 2.3 84/09/22 22:00:00 petsd!joe
239 * Implemented "-B" block compress. Implemented REVERSE sorting of tab_next.
240 * Bug fix for last bits. Changed fwrite to putchar loop everywhere.
241 *
242 * Revision 2.2 84/09/18 14:12:21 ames!jaw
243 * Fold in news changes, small machine typedef from thomas,
244 * #ifdef interdata from joe.
245 *
246 * Revision 2.1 84/09/10 12:34:56 ames!jaw
247 * Configured fast table lookup for 32-bit machines.
248 * This cuts user time in half for b <= FBITS, and is useful for news batching
249 * from VAX to PDP sites. Also sped up decompress() [fwrite->putc] and
250 * added signal catcher [plus beef in writeerr()] to delete effluvia.
251 *
252 * Revision 2.0 84/08/28 22:00:00 petsd!joe
253 * Add check for foreground before prompting user. Insert maxbits into
254 * compressed file. Force file being uncompressed to end with ".Z".
255 * Added "-c" flag and "zcat". Prepared for release.
256 *
257 * Revision 1.10 84/08/24 18:28:00 turtlevax!ken
258 * Will only compress regular files (no directories), added a magic number
259 * header (plus an undocumented -n flag to handle old files without headers),
260 * added -f flag to force overwriting of possibly existing destination file,
261 * otherwise the user is prompted for a response. Will tack on a .Z to a
262 * filename if it doesn't have one when decompressing. Will only replace
263 * file if it was compressed.
264 *
265 * Revision 1.9 84/08/16 17:28:00 turtlevax!ken
266 * Removed scanargs(), getopt(), added .Z extension and unlimited number of
267 * filenames to compress. Flags may be clustered (-Ddvb12) or separated
268 * (-D -d -v -b 12), or combination thereof. Modes and other status is
269 * copied with copystat(). -O bug for 4.2 seems to have disappeared with
270 * 1.8.
271 *
272 * Revision 1.8 84/08/09 23:15:00 joe
273 * Made it compatible with vax version, installed jim's fixes/enhancements
274 *
275 * Revision 1.6 84/08/01 22:08:00 joe
276 * Sped up algorithm significantly by sorting the compress chain.
277 *
278 * Revision 1.5 84/07/13 13:11:00 srd
279 * Added C version of vax asm routines. Changed structure to arrays to
280 * save much memory. Do unsigned compares where possible (faster on
281 * Perkin-Elmer)
282 *
283 * Revision 1.4 84/07/05 03:11:11 thomas
284 * Clean up the code a little and lint it. (Lint complains about all
285 * the regs used in the asm, but I'm not going to "fix" this.)
286 *
287 * Revision 1.3 84/07/05 02:06:54 thomas
288 * Minor fixes.
289 *
290 * Revision 1.2 84/07/05 00:27:27 thomas
291 * Add variable bit length output.
292 *
293 */
294 static char rcs_ident[] = "$Header: /home/wtanksle/cvs/omega/compress.c,v 1.2 1998/08/08 10:47:56 wtanksle Exp $";
295
296 #include <stdio.h>
297 #include <ctype.h>
298 #include <signal.h>
299 #include <fcntl.h>
300 #include <sys/types.h>
301 #include <sys/stat.h>
302 #ifdef notdef
303 #include <sys/ioctl.h>
304 #endif
305
306 int n_bits; /* number of bits/code */
307 int maxbits = BITS; /* user settable max # bits/code */
308 code_int maxcode; /* maximum code, given n_bits */
309 code_int maxmaxcode = 1 << BITS; /* should NEVER generate this code */
310 #ifdef COMPATIBLE /* But wrong! */
311 # define MAXCODE(n_bits) (1 << (n_bits) - 1)
312 #else
313 # define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
314 #endif /* COMPATIBLE */
315
316 #ifdef XENIX_16
317 count_int htab0[8192];
318 count_int htab1[8192];
319 count_int htab2[8192];
320 count_int htab3[8192];
321 count_int htab4[8192];
322 count_int htab5[8192];
323 count_int htab6[8192];
324 count_int htab7[8192];
325 count_int htab8[HSIZE-65536];
326 count_int * htab[9] = {
327 htab0, htab1, htab2, htab3, htab4, htab5, htab6, htab7, htab8 };
328
329 #define htabof(i) (htab[(i) >> 13][(i) & 0x1fff])
330 unsigned short code0tab[16384];
331 unsigned short code1tab[16384];
332 unsigned short code2tab[16384];
333 unsigned short code3tab[16384];
334 unsigned short code4tab[16384];
335 unsigned short * codetab[5] = {
336 code0tab, code1tab, code2tab, code3tab, code4tab };
337
338 #define codetabof(i) (codetab[(i) >> 14][(i) & 0x3fff])
339
340 #else /* Normal machine */
341
342 #ifdef sel /* gould base register braindamage */
343 /*NOBASE*/
344 count_int htab [HSIZE];
345 unsigned short codetab [HSIZE];
346 /*NOBASE*/
347 #else
348 count_int htab [HSIZE];
349 unsigned short codetab [HSIZE];
350 #endif sel
351
352 #define htabof(i) htab[i]
353 #define codetabof(i) codetab[i]
354 #endif /* XENIX_16 */
355 code_int hsize = HSIZE; /* for dynamic table sizing */
356 count_int fsize;
357
358 /*
359 * To save much memory, we overlay the table used by compress() with those
360 * used by decompress(). The tab_prefix table is the same size and type
361 * as the codetab. The tab_suffix table needs 2**BITS characters. We
362 * get this from the beginning of htab. The output stack uses the rest
363 * of htab, and contains characters. There is plenty of room for any
364 * possible stack (stack used to be 8000 characters).
365 */
366
367 #define tab_prefixof(i) codetabof(i)
368 #ifdef XENIX_16
369 # define tab_suffixof(i) ((char_type *)htab[(i)>>15])[(i) & 0x7fff]
370 # define de_stack ((char_type *)(htab2))
371 #else /* Normal machine */
372 # define tab_suffixof(i) ((char_type *)(htab))[i]
373 # define de_stack ((char_type *)&tab_suffixof(1<<BITS))
374 #endif /* XENIX_16 */
375
376 code_int free_ent = 0; /* first unused entry */
377 int exit_stat = 0; /* per-file status */
378 int perm_stat = 0; /* permanent status */
379
380 code_int getcode();
381
Usage()382 Usage() {
383 #ifdef DEBUG
384 fprintf(stderr,"Usage: compress [-dDVfc] [-b maxbits] [file ...]\n");
385 }
386 int debug = 0;
387 #else
388 fprintf(stderr,"Usage: compress [-fvc] [-b maxbits] [file ...]\n");
389 }
390 #endif /* DEBUG */
391 int nomagic = 0; /* Use a 3-byte magic number header, unless old file */
392 int zcat_flg = 0; /* Write output on outfile, suppress messages */
393 int precious = 1; /* Don't unlink output file on interrupt */
394 int quiet = 1; /* don't tell me about compression */
395
396 /*
397 * block compression parameters -- after all codes are used up,
398 * and compression rate changes, start over.
399 */
400 int block_compress = BLOCK_MASK;
401 int clear_flg = 0;
402 long int ratio = 0;
403 #define CHECK_GAP 10000 /* ratio check interval */
404 count_int checkpoint = CHECK_GAP;
405 /*
406 * the next two codes should not be changed lightly, as they must not
407 * lie within the contiguous general code space.
408 */
409 #define FIRST 257 /* first free entry */
410 #define CLEAR 256 /* table clear output code */
411
412 int force = 0;
413 char ofname [100];
414 #ifdef DEBUG
415 int verbose = 0;
416 #endif /* DEBUG */
417 #if 0
418 sig_t oldint;
419 #endif
420 int bgnd_flag=0;
421
422 int do_decomp = 0;
423
424 FILE *infile, *outfile;
425
426 /*****************************************************************
427 * TAG( main )
428 *
429 * Algorithm from "A Technique for High Performance Data Compression",
430 * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
431 *
432 * Usage: compress [-dfvc] [-b bits] [file ...]
433 * Inputs:
434 * -d: If given, decompression is done instead.
435 *
436 * -c: Write output on outfile, don't remove original.
437 *
438 * -b: Parameter limits the max number of bits/code.
439 *
440 * -f: Forces output file to be generated, even if one already
441 * exists, and even if no space is saved by compressing.
442 * If -f is not used, the user will be prompted if infile is
443 * a tty, otherwise, the output file will not be overwritten.
444 *
445 * -v: Write compression statistics
446 *
447 * file ...: Files to be compressed. If none specified, infile
448 * is used.
449 * Outputs:
450 * file.Z: Compressed form of file with same mode, owner, and utimes
451 * or outfile (if infile used as input)
452 *
453 * Assumptions:
454 * When filenames are given, replaces with the compressed version
455 * (.Z suffix) only if the file decreases in size.
456 * Algorithm:
457 * Modified Lempel-Ziv method (LZW). Basically finds common
458 * substrings and replaces them with a variable size code. This is
459 * deterministic, and can be done on the fly. Thus, the decompression
460 * procedure needs no input table, but tracks the way the table was built.
461 */
462
do_compression(decomp,file)463 do_compression( decomp, file )
464 int decomp;
465 char *file;
466 {
467 int overwrite = 1; /* Do not overwrite unless given -f flag */
468 char tempname[100];
469 char **fileptr;
470 char *cp, *rindex();
471 struct stat statbuf;
472 void onintr(), oops();
473
474 /* This bg check only works for sh. */
475 #if 0
476 if ( (oldint = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
477 signal ( SIGINT, onintr );
478 signal ( SIGSEGV, oops );
479 }
480 bgnd_flag = oldint != SIG_DFL;
481 #endif
482 #ifdef notdef /* This works for csh but we don't want it. */
483 { int tgrp;
484 if (bgnd_flag == 0 && ioctl(2, TIOCGPGRP, (char *)&tgrp) == 0 &&
485 getpgrp(0) != tgrp)
486 bgnd_flag = 1;
487 }
488 #endif
489
490 #ifdef COMPATIBLE
491 nomagic = 1; /* Original didn't have a magic number */
492 #endif /* COMPATIBLE */
493
494 fileptr = &file;
495
496 #ifdef BSD4_2
497 /* 4.2BSD dependent - take it out if not */
498 setlinebuf( stderr );
499 #endif /* BSD4_2 */
500
501 do_decomp = decomp;
502
503 if(maxbits < INIT_BITS) maxbits = INIT_BITS;
504 if (maxbits > BITS) maxbits = BITS;
505 maxmaxcode = 1 << maxbits;
506
507 exit_stat = 0;
508 if (do_decomp) { /* DECOMPRESSION */
509 /* Check for .Z suffix */
510 if (strcmp(*fileptr + strlen(*fileptr) - 1, "Z") != 0) {
511 /* No .Z: tack one on */
512 strcpy(tempname, *fileptr);
513 strcat(tempname, "Z");
514 *fileptr = tempname;
515 }
516 /* Open input file */
517 if ((infile = fopen(*fileptr, "rb")) == NULL) {
518 perror(*fileptr);
519 perm_stat = 1;
520 return;
521 }
522 /* Check the magic number */
523 if (nomagic == 0) {
524 if ((getc(infile) != (magic_header[0] & 0xFF))
525 || (getc(infile) != (magic_header[1] & 0xFF))) {
526 fprintf(stderr, "%s: not in compressed format\n",
527 *fileptr);
528 fclose(infile);
529 return;
530 }
531 maxbits = getc(infile); /* set -b from file */
532 block_compress = maxbits & BLOCK_MASK;
533 maxbits &= BIT_MASK;
534 maxmaxcode = 1 << maxbits;
535 if(maxbits > BITS) {
536 fprintf(stderr,
537 "%s: compressed with %d bits, can only handle %d bits\n",
538 *fileptr, maxbits, BITS);
539 fclose(infile);
540 return;
541 }
542 }
543 /* Generate output filename */
544 strcpy(ofname, *fileptr);
545 ofname[strlen(*fileptr) - 1] = '\0'; /* Strip off .Z */
546 } else { /* COMPRESSION */
547 if (strcmp(*fileptr + strlen(*fileptr) - 1, "Z") == 0) {
548 fprintf(stderr, "%s: already has Z suffix -- no change\n",
549 *fileptr);
550 return;
551 }
552 /* Open input file */
553 if ((infile = fopen(*fileptr, "rb")) == NULL) {
554 perror(*fileptr);
555 perm_stat = 1;
556 return;
557 }
558 stat ( *fileptr, &statbuf );
559 fsize = (long) statbuf.st_size;
560 /*
561 * tune hash table size for small files -- ad hoc,
562 * but the sizes match earlier #defines, which
563 * serve as upper bounds on the number of output codes.
564 */
565 hsize = HSIZE;
566 if ( fsize < (1 << 12) )
567 hsize = min ( 5003, HSIZE );
568 else if ( fsize < (1 << 13) )
569 hsize = min ( 9001, HSIZE );
570 else if ( fsize < (1 << 14) )
571 hsize = min ( 18013, HSIZE );
572 else if ( fsize < (1 << 15) )
573 hsize = min ( 35023, HSIZE );
574 else if ( fsize < 47000 )
575 hsize = min ( 50021, HSIZE );
576
577 /* Generate output filename */
578 strcpy(ofname, *fileptr);
579 #ifndef BSD4_2 /* Short filenames */
580 if ((cp=rindex(ofname,'/')) != NULL) cp++;
581 else cp = ofname;
582 if (strlen(cp) > 12) {
583 fprintf(stderr,"%s: filename too long to tack on Z\n",cp);
584 fclose(infile);
585 return;
586 }
587 #endif /* BSD4_2 Long filenames allowed */
588 strcat(ofname, "Z");
589 }
590 /* Check for overwrite of existing file */
591 if (overwrite == 0 && zcat_flg == 0) {
592 if (stat(ofname, &statbuf) == 0) {
593 char response[2];
594 response[0] = 'n';
595 fprintf(stderr, "%s already exists;", ofname);
596 if (bgnd_flag == 0 && isatty(2)) {
597 fprintf(stderr, " do you wish to overwrite %s (y or n)? ",
598 ofname);
599 fflush(stderr);
600 read(2, response, 2);
601 while (response[1] != '\n') {
602 if (read(2, response+1, 1) < 0) { /* Ack! */
603 perror("stderr"); break;
604 }
605 }
606 }
607 if (response[0] != 'y') {
608 fprintf(stderr, "\tnot overwritten\n");
609 fclose(infile);
610 return;
611 }
612 }
613 }
614 if(zcat_flg == 0) { /* Open output file */
615 if ((outfile = fopen(ofname, "wb")) == NULL) {
616 perror(ofname);
617 perm_stat = 1;
618 fclose(infile);
619 return;
620 }
621 precious = 0;
622 if(!quiet)
623 fprintf(stderr, "%s: ", *fileptr);
624 }
625
626 /* Actually do the compression/decompression */
627 if (do_decomp == 0) compress();
628 #ifndef DEBUG
629 else decompress();
630 #else
631 else if (debug == 0) decompress();
632 else printcodes();
633 if (verbose) dump_tab();
634 #endif /* DEBUG */
635 fclose(infile);
636 if(zcat_flg == 0) {
637 copystat(*fileptr, ofname); /* Copy stats */
638 precious = 1;
639 if((exit_stat == 1) || (!quiet))
640 putc('\n', stderr);
641 }
642 fclose(outfile);
643 }
644
645 static int offset;
646 long int in_count = 1; /* length of input */
647 long int bytes_out; /* length of compressed output */
648 long int out_count = 0; /* # of codes output (for debugging) */
649
650 /*
651 * compress infile to outfile
652 *
653 * Algorithm: use open addressing double hashing (no chaining) on the
654 * prefix code / next character combination. We do a variant of Knuth's
655 * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
656 * secondary probe. Here, the modular division first probe is gives way
657 * to a faster exclusive-or manipulation. Also do block compression with
658 * an adaptive reset, whereby the code table is cleared when the compression
659 * ratio decreases, but after the table fills. The variable-length output
660 * codes are re-sized at this point, and a special CLEAR code is generated
661 * for the decompressor. Late addition: construct the table according to
662 * file size for noticeable speed improvement on small files. Please direct
663 * questions about this implementation to ames!jaw.
664 */
665
compress()666 compress()
667 {
668 register long fcode;
669 register code_int i = 0;
670 register int c;
671 register code_int ent;
672 #ifdef XENIX_16
673 register code_int disp;
674 #else /* Normal machine */
675 register int disp;
676 #endif
677 register code_int hsize_reg;
678 register int hshift;
679
680 #ifndef COMPATIBLE
681 if (nomagic == 0) {
682 putc(magic_header[0], outfile);
683 putc(magic_header[1], outfile);
684 putc((char)(maxbits | block_compress), outfile);
685 if(ferror(outfile))
686 writeerr();
687 }
688 #endif /* COMPATIBLE */
689
690 offset = 0;
691 bytes_out = 3; /* includes 3-byte header mojo */
692 out_count = 0;
693 clear_flg = 0;
694 ratio = 0;
695 in_count = 1;
696 checkpoint = CHECK_GAP;
697 maxcode = MAXCODE(n_bits = INIT_BITS);
698 free_ent = ((block_compress) ? FIRST : 256 );
699
700 ent = getc (infile);
701
702 hshift = 0;
703 for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
704 hshift++;
705 hshift = 8 - hshift; /* set hash code range bound */
706
707 hsize_reg = hsize;
708 cl_hash( (count_int) hsize_reg); /* clear hash table */
709
710 #ifdef SIGNED_COMPARE_SLOW
711 while ( (c = getc(infile)) != (unsigned) EOF ) {
712 #else
713 while ( (c = getc(infile)) != EOF ) {
714 #endif
715 in_count++;
716 fcode = (long) (((long) c << maxbits) + ent);
717 i = ((c << hshift) ^ ent); /* xor hashing */
718
719 if ( htabof (i) == fcode ) {
720 ent = codetabof (i);
721 continue;
722 } else if ( (long)htabof (i) < 0 ) /* empty slot */
723 goto nomatch;
724 disp = hsize_reg - i; /* secondary hash (after G. Knott) */
725 if ( i == 0 )
726 disp = 1;
727 probe:
728 if ( (i -= disp) < 0 )
729 i += hsize_reg;
730
731 if ( htabof (i) == fcode ) {
732 ent = codetabof (i);
733 continue;
734 }
735 if ( (long)htabof (i) > 0 )
736 goto probe;
737 nomatch:
738 output ( (code_int) ent );
739 out_count++;
740 ent = c;
741 #ifdef SIGNED_COMPARE_SLOW
742 if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
743 #else
744 if ( free_ent < maxmaxcode ) {
745 #endif
746 codetabof (i) = free_ent++; /* code -> hashtable */
747 htabof (i) = fcode;
748 }
749 else if ( (count_int)in_count >= checkpoint && block_compress )
750 cl_block ();
751 }
752 /*
753 * Put out the final code.
754 */
755 output( (code_int)ent );
756 out_count++;
757 output( (code_int)-1 );
758
759 /*
760 * Print out stats on stderr
761 */
762 if(zcat_flg == 0 && !quiet) {
763 #ifdef DEBUG
764 fprintf( stderr,
765 "%ld chars in, %ld codes (%ld bytes) out, compression factor: ",
766 in_count, out_count, bytes_out );
767 prratio( stderr, in_count, bytes_out );
768 fprintf( stderr, "\n");
769 fprintf( stderr, "\tCompression as in compact: " );
770 prratio( stderr, in_count-bytes_out, in_count );
771 fprintf( stderr, "\n");
772 fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
773 free_ent - 1, n_bits );
774 #else /* !DEBUG */
775 fprintf( stderr, "Compression: " );
776 prratio( stderr, in_count-bytes_out, in_count );
777 #endif /* DEBUG */
778 }
779 if(bytes_out > in_count) /* exit(2) if no savings */
780 exit_stat = 2;
781 return;
782 }
783
784 /*****************************************************************
785 * TAG( output )
786 *
787 * Output the given code.
788 * Inputs:
789 * code: A n_bits-bit integer. If == -1, then EOF. This assumes
790 * that n_bits =< (long)wordsize - 1.
791 * Outputs:
792 * Outputs code to the file.
793 * Assumptions:
794 * Chars are 8 bits long.
795 * Algorithm:
796 * Maintain a BITS character long buffer (so that 8 codes will
797 * fit in it exactly). Use the VAX insv instruction to insert each
798 * code in turn. When the buffer fills up empty it and start over.
799 */
800
801 static char buf[BITS];
802
803 #ifndef vax
804 char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
805 char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
806 #endif /* vax */
807
808 output( code )
809 code_int code;
810 {
811 #ifdef DEBUG
812 static int col = 0;
813 #endif /* DEBUG */
814
815 /*
816 * On the VAX, it is important to have the register declarations
817 * in exactly the order given, or the asm will break.
818 */
819 register int r_off = offset, bits= n_bits;
820 register char * bp = buf;
821
822 #ifdef DEBUG
823 if ( verbose )
824 fprintf( stderr, "%5d%c", code,
825 (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
826 #endif /* DEBUG */
827 if ( code >= 0 ) {
828 #ifdef vax
829 /* VAX DEPENDENT!! Implementation on other machines is below.
830 *
831 * Translation: Insert BITS bits from the argument starting at
832 * offset bits from the beginning of buf.
833 */
834 0; /* Work around for pcc -O bug with asm and if stmt */
835 asm( "insv 4(ap),r11,r10,(r9)" );
836 #else /* not a vax */
837 /*
838 * byte/bit numbering on the VAX is simulated by the following code
839 */
840 /*
841 * Get to the first byte.
842 */
843 bp += (r_off >> 3);
844 r_off &= 7;
845 /*
846 * Since code is always >= 8 bits, only need to mask the first
847 * hunk on the left.
848 */
849 *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
850 bp++;
851 bits -= (8 - r_off);
852 code >>= 8 - r_off;
853 /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
854 if ( bits >= 8 ) {
855 *bp++ = code;
856 code >>= 8;
857 bits -= 8;
858 }
859 /* Last bits. */
860 if(bits)
861 *bp = code;
862 #endif /* vax */
863 offset += n_bits;
864 if ( offset == (n_bits << 3) ) {
865 bp = buf;
866 bits = n_bits;
867 bytes_out += bits;
868 do
869 putc(*bp++, outfile);
870 while(--bits);
871 offset = 0;
872 }
873
874 /*
875 * If the next entry is going to be too big for the code size,
876 * then increase it, if possible.
877 */
878 if ( free_ent > maxcode || (clear_flg > 0))
879 {
880 /*
881 * Write the whole buffer, because the input side won't
882 * discover the size increase until after it has read it.
883 */
884 if ( offset > 0 ) {
885 if( fwrite( buf, 1, n_bits, outfile ) != n_bits)
886 writeerr();
887 bytes_out += n_bits;
888 }
889 offset = 0;
890
891 if ( clear_flg ) {
892 maxcode = MAXCODE (n_bits = INIT_BITS);
893 clear_flg = 0;
894 }
895 else {
896 n_bits++;
897 if ( n_bits == maxbits )
898 maxcode = maxmaxcode;
899 else
900 maxcode = MAXCODE(n_bits);
901 }
902 #ifdef DEBUG
903 if ( debug ) {
904 fprintf( stderr, "\nChange to %d bits\n", n_bits );
905 col = 0;
906 }
907 #endif /* DEBUG */
908 }
909 } else {
910 /*
911 * At EOF, write the rest of the buffer.
912 */
913 if ( offset > 0 )
914 fwrite( buf, 1, (offset + 7) / 8, outfile );
915 bytes_out += (offset + 7) / 8;
916 offset = 0;
917 fflush( outfile );
918 #ifdef DEBUG
919 if ( verbose )
920 fprintf( stderr, "\n" );
921 #endif /* DEBUG */
922 if( ferror( outfile ) )
923 writeerr();
924 }
925 }
926
927 /*
928 * Decompress infile to outfile. This routine adapts to the codes in the
929 * file building the "string" table on-the-fly; requiring no table to
930 * be stored in the compressed file. The tables used herein are shared
931 * with those of the compress() routine. See the definitions above.
932 */
933
934 decompress() {
935 register char_type *stackp;
936 register int finchar;
937 register code_int code, oldcode, incode;
938
939 /*
940 * As above, initialize the first 256 entries in the table.
941 */
942 maxcode = MAXCODE(n_bits = INIT_BITS);
943 for ( code = 255; code >= 0; code-- ) {
944 tab_prefixof(code) = 0;
945 tab_suffixof(code) = (char_type)code;
946 }
947 free_ent = ((block_compress) ? FIRST : 256 );
948
949 finchar = oldcode = getcode();
950 if(oldcode == -1) /* EOF already? */
951 return; /* Get out of here */
952 putc( (char)finchar, outfile ); /* first code must be 8 bits = char */
953 if(ferror(outfile)) /* Crash if can't write */
954 writeerr();
955 stackp = de_stack;
956
957 while ( (code = getcode()) > -1 ) {
958
959 if ( (code == CLEAR) && block_compress ) {
960 for ( code = 255; code >= 0; code-- )
961 tab_prefixof(code) = 0;
962 clear_flg = 1;
963 free_ent = FIRST - 1;
964 if ( (code = getcode ()) == -1 ) /* O, untimely death! */
965 break;
966 }
967 incode = code;
968 /*
969 * Special case for KwKwK string.
970 */
971 if ( code >= free_ent ) {
972 *stackp++ = finchar;
973 code = oldcode;
974 }
975
976 /*
977 * Generate output characters in reverse order
978 */
979 #ifdef SIGNED_COMPARE_SLOW
980 while ( ((unsigned long)code) >= ((unsigned long)256) ) {
981 #else
982 while ( code >= 256 ) {
983 #endif
984 *stackp++ = tab_suffixof(code);
985 code = tab_prefixof(code);
986 }
987 *stackp++ = finchar = tab_suffixof(code);
988
989 /*
990 * And put them out in forward order
991 */
992 do
993 putc ( *--stackp, outfile );
994 while ( stackp > de_stack );
995
996 /*
997 * Generate the new entry.
998 */
999 if ( (code=free_ent) < maxmaxcode ) {
1000 tab_prefixof(code) = (unsigned short)oldcode;
1001 tab_suffixof(code) = finchar;
1002 free_ent = code+1;
1003 }
1004 /*
1005 * Remember previous code.
1006 */
1007 oldcode = incode;
1008 }
1009 fflush( outfile );
1010 if(ferror(outfile))
1011 writeerr();
1012 }
1013
1014 /*****************************************************************
1015 * TAG( getcode )
1016 *
1017 * Read one code from the standard input. If EOF, return -1.
1018 * Inputs:
1019 * infile
1020 * Outputs:
1021 * code or -1 is returned.
1022 */
1023
1024 code_int
1025 getcode() {
1026 /*
1027 * On the VAX, it is important to have the register declarations
1028 * in exactly the order given, or the asm will break.
1029 */
1030 register code_int code;
1031 static int offset = 0, size = 0;
1032 static char_type buf[BITS];
1033 register int r_off, bits;
1034 register char_type *bp = buf;
1035
1036 if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
1037 /*
1038 * If the next entry will be too big for the current code
1039 * size, then we must increase the size. This implies reading
1040 * a new buffer full, too.
1041 */
1042 if ( free_ent > maxcode ) {
1043 n_bits++;
1044 if ( n_bits == maxbits )
1045 maxcode = maxmaxcode; /* won't get any bigger now */
1046 else
1047 maxcode = MAXCODE(n_bits);
1048 }
1049 if ( clear_flg > 0) {
1050 maxcode = MAXCODE (n_bits = INIT_BITS);
1051 clear_flg = 0;
1052 }
1053 size = fread( buf, 1, n_bits, infile );
1054 if ( size <= 0 )
1055 return -1; /* end of file */
1056 offset = 0;
1057 /* Round size down to integral number of codes */
1058 size = (size << 3) - (n_bits - 1);
1059 }
1060 r_off = offset;
1061 bits = n_bits;
1062 #ifdef vax
1063 asm( "extzv r10,r9,(r8),r11" );
1064 #else /* not a vax */
1065 /*
1066 * Get to the first byte.
1067 */
1068 bp += (r_off >> 3);
1069 r_off &= 7;
1070 /* Get first part (low order bits) */
1071 #ifdef NO_UCHAR
1072 code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
1073 #else
1074 code = (*bp++ >> r_off);
1075 #endif /* NO_UCHAR */
1076 bits -= (8 - r_off);
1077 r_off = 8 - r_off; /* now, offset into code word */
1078 /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
1079 if ( bits >= 8 ) {
1080 #ifdef NO_UCHAR
1081 code |= (*bp++ & 0xff) << r_off;
1082 #else
1083 code |= *bp++ << r_off;
1084 #endif /* NO_UCHAR */
1085 r_off += 8;
1086 bits -= 8;
1087 }
1088 /* high order bits. */
1089 code |= (*bp & rmask[bits]) << r_off;
1090 #endif /* vax */
1091 offset += n_bits;
1092
1093 return code;
1094 }
1095
1096 #ifndef __GO32__
1097 char *
1098 rindex(s, c) /* For those who don't have it in libc.a */
1099 register char *s, c;
1100 {
1101 char *p;
1102 for (p = NULL; *s; s++)
1103 if (*s == c)
1104 p = s;
1105 return(p);
1106 }
1107 #endif
1108
1109 #ifdef DEBUG
1110 printcodes()
1111 {
1112 /*
1113 * Just print out codes from input file. For debugging.
1114 */
1115 code_int code;
1116 int col = 0, bits;
1117
1118 bits = n_bits = INIT_BITS;
1119 maxcode = MAXCODE(n_bits);
1120 free_ent = ((block_compress) ? FIRST : 256 );
1121 while ( ( code = getcode() ) >= 0 ) {
1122 if ( (code == CLEAR) && block_compress ) {
1123 free_ent = FIRST - 1;
1124 clear_flg = 1;
1125 }
1126 else if ( free_ent < maxmaxcode )
1127 free_ent++;
1128 if ( bits != n_bits ) {
1129 fprintf(stderr, "\nChange to %d bits\n", n_bits );
1130 bits = n_bits;
1131 col = 0;
1132 }
1133 fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
1134 }
1135 putc( '\n', stderr );
1136 exit( 0 );
1137 }
1138
1139 code_int sorttab[1<<BITS]; /* sorted pointers into htab */
1140
1141 dump_tab() /* dump string table */
1142 {
1143 register int i, first;
1144 register ent;
1145 #define STACK_SIZE 15000
1146 int stack_top = STACK_SIZE;
1147 register c;
1148
1149 if(do_decomp == 0) { /* compressing */
1150 register int flag = 1;
1151
1152 for(i=0; i<hsize; i++) { /* build sort pointers */
1153 if((long)htabof(i) >= 0) {
1154 sorttab[codetabof(i)] = i;
1155 }
1156 }
1157 first = block_compress ? FIRST : 256;
1158 for(i = first; i < free_ent; i++) {
1159 fprintf(stderr, "%5d: \"", i);
1160 de_stack[--stack_top] = '\n';
1161 de_stack[--stack_top] = '"';
1162 stack_top = in_stack((htabof(sorttab[i])>>maxbits)&0xff,
1163 stack_top);
1164 for(ent=htabof(sorttab[i]) & ((1<<maxbits)-1);
1165 ent > 256;
1166 ent=htabof(sorttab[ent]) & ((1<<maxbits)-1)) {
1167 stack_top = in_stack(htabof(sorttab[ent]) >> maxbits,
1168 stack_top);
1169 }
1170 stack_top = in_stack(ent, stack_top);
1171 fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr);
1172 stack_top = STACK_SIZE;
1173 }
1174 } else if(!debug) { /* decompressing */
1175
1176 for ( i = 0; i < free_ent; i++ ) {
1177 ent = i;
1178 c = tab_suffixof(ent);
1179 if ( isascii(c) && isprint(c) )
1180 fprintf( stderr, "%5d: %5d/'%c' \"",
1181 ent, tab_prefixof(ent), c );
1182 else
1183 fprintf( stderr, "%5d: %5d/\\%03o \"",
1184 ent, tab_prefixof(ent), c );
1185 de_stack[--stack_top] = '\n';
1186 de_stack[--stack_top] = '"';
1187 for ( ; ent != NULL;
1188 ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
1189 stack_top = in_stack(tab_suffixof(ent), stack_top);
1190 }
1191 fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr );
1192 stack_top = STACK_SIZE;
1193 }
1194 }
1195 }
1196
1197 int
1198 in_stack(c, stack_top)
1199 register c, stack_top;
1200 {
1201 if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
1202 de_stack[--stack_top] = c;
1203 } else {
1204 switch( c ) {
1205 case '\n': de_stack[--stack_top] = 'n'; break;
1206 case '\t': de_stack[--stack_top] = 't'; break;
1207 case '\b': de_stack[--stack_top] = 'b'; break;
1208 case '\f': de_stack[--stack_top] = 'f'; break;
1209 case '\r': de_stack[--stack_top] = 'r'; break;
1210 case '\\': de_stack[--stack_top] = '\\'; break;
1211 default:
1212 de_stack[--stack_top] = '0' + c % 8;
1213 de_stack[--stack_top] = '0' + (c / 8) % 8;
1214 de_stack[--stack_top] = '0' + c / 64;
1215 break;
1216 }
1217 de_stack[--stack_top] = '\\';
1218 }
1219 return stack_top;
1220 }
1221 #endif /* DEBUG */
1222
1223 writeerr()
1224 {
1225 perror ( ofname );
1226 unlink ( ofname );
1227 exit ( 1 );
1228 }
1229
1230 copystat(ifname, ofname)
1231 char *ifname, *ofname;
1232 {
1233 struct stat statbuf;
1234 int mode;
1235 time_t timep[2];
1236
1237 fclose(outfile);
1238 if (stat(ifname, &statbuf)) { /* Get stat on input file */
1239 perror(ifname);
1240 return;
1241 }
1242 if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) {
1243 if(quiet)
1244 fprintf(stderr, "%s: ", ifname);
1245 fprintf(stderr, " -- not a regular file: unchanged");
1246 exit_stat = 1;
1247 perm_stat = 1;
1248 } else if (statbuf.st_nlink > 1) {
1249 if(quiet)
1250 fprintf(stderr, "%s: ", ifname);
1251 fprintf(stderr, " -- has %d other links: unchanged",
1252 statbuf.st_nlink - 1);
1253 exit_stat = 1;
1254 perm_stat = 1;
1255 } else if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */
1256 if(!quiet)
1257 fprintf(stderr, " -- file unchanged");
1258 } else { /* ***** Successful Compression ***** */
1259 exit_stat = 0;
1260 mode = statbuf.st_mode & 07777;
1261 #if 0
1262 if (chmod(ofname, mode)) /* Copy modes */
1263 perror(ofname);
1264 #endif
1265 chown(ofname, statbuf.st_uid, statbuf.st_gid); /* Copy ownership */
1266 timep[0] = statbuf.st_atime;
1267 timep[1] = statbuf.st_mtime;
1268 utime(ofname, timep); /* Update last accessed and modified times */
1269 #if 0
1270 if (unlink(ifname)) /* Remove input file */
1271 perror(ifname);
1272 #else
1273 unlink(ifname);
1274 #endif
1275 if(!quiet)
1276 fprintf(stderr, " -- replaced with %s", ofname);
1277 return; /* Successful return */
1278 }
1279
1280 /* Unsuccessful return -- one of the tests failed */
1281 if (unlink(ofname))
1282 perror(ofname);
1283 }
1284
1285 void
1286 onintr ( )
1287 {
1288 if (!precious)
1289 unlink ( ofname );
1290 exit ( 1 );
1291 }
1292
1293 void
1294 oops ( ) /* wild pointer -- assume bad input */
1295 {
1296 if ( do_decomp )
1297 fprintf ( stderr, "uncompress: corrupt input\n" );
1298 unlink ( ofname );
1299 exit ( 1 );
1300 }
1301
1302 cl_block () /* table clear for block compress */
1303 {
1304 register long int rat;
1305
1306 checkpoint = in_count + CHECK_GAP;
1307 #ifdef DEBUG
1308 if ( debug ) {
1309 fprintf ( stderr, "count: %ld, ratio: ", in_count );
1310 prratio ( stderr, in_count, bytes_out );
1311 fprintf ( stderr, "\n");
1312 }
1313 #endif /* DEBUG */
1314
1315 if(in_count > 0x007fffff) { /* shift will overflow */
1316 rat = bytes_out >> 8;
1317 if(rat == 0) { /* Don't divide by zero */
1318 rat = 0x7fffffff;
1319 } else {
1320 rat = in_count / rat;
1321 }
1322 } else {
1323 rat = (in_count << 8) / bytes_out; /* 8 fractional bits */
1324 }
1325 if ( rat > ratio ) {
1326 ratio = rat;
1327 } else {
1328 ratio = 0;
1329 #ifdef DEBUG
1330 if(verbose)
1331 dump_tab(); /* dump string table */
1332 #endif
1333 cl_hash ( (count_int) hsize );
1334 free_ent = FIRST;
1335 clear_flg = 1;
1336 output ( (code_int) CLEAR );
1337 #ifdef DEBUG
1338 if(debug)
1339 fprintf ( stderr, "clear\n" );
1340 #endif /* DEBUG */
1341 }
1342 }
1343
1344 cl_hash(hsize) /* reset code table */
1345 register count_int hsize;
1346 {
1347 #ifndef XENIX_16 /* Normal machine */
1348 register count_int *htab_p = htab+hsize;
1349 #else
1350 register j;
1351 register long k = hsize;
1352 register count_int *htab_p;
1353 #endif
1354 register long i;
1355 register long m1 = -1;
1356
1357 #ifdef XENIX_16
1358 for(j=0; j<=8 && k>=0; j++,k-=8192) {
1359 i = 8192;
1360 if(k < 8192) {
1361 i = k;
1362 }
1363 htab_p = &(htab[j][i]);
1364 i -= 16;
1365 if(i > 0) {
1366 #else
1367 i = hsize - 16;
1368 #endif
1369 do { /* might use Sys V memset(3) here */
1370 *(htab_p-16) = m1;
1371 *(htab_p-15) = m1;
1372 *(htab_p-14) = m1;
1373 *(htab_p-13) = m1;
1374 *(htab_p-12) = m1;
1375 *(htab_p-11) = m1;
1376 *(htab_p-10) = m1;
1377 *(htab_p-9) = m1;
1378 *(htab_p-8) = m1;
1379 *(htab_p-7) = m1;
1380 *(htab_p-6) = m1;
1381 *(htab_p-5) = m1;
1382 *(htab_p-4) = m1;
1383 *(htab_p-3) = m1;
1384 *(htab_p-2) = m1;
1385 *(htab_p-1) = m1;
1386 htab_p -= 16;
1387 } while ((i -= 16) >= 0);
1388 #ifdef XENIX_16
1389 }
1390 }
1391 #endif
1392 for ( i += 16; i > 0; i-- )
1393 *--htab_p = m1;
1394 }
1395
1396 prratio(stream, num, den)
1397 FILE *stream;
1398 long int num, den;
1399 {
1400 register int q; /* Doesn't need to be long */
1401
1402 if(num > 214748L) { /* 2147483647/10000 */
1403 q = num / (den / 10000L);
1404 } else {
1405 q = 10000L * num / den; /* Long calculations, though */
1406 }
1407 if (q < 0) {
1408 putc('-', stream);
1409 q = -q;
1410 }
1411 fprintf(stream, "%d.%02d%%", q / 100, q % 100);
1412 }
1413