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