|
|
1.1 ! root 1: /* Set USERMEM to the maximum amount of physical user memory available ! 2: * in bytes. USERMEM is used to determine the maximum BITS that can be used ! 3: * for compression. If USERMEM is big enough, use fast compression algorithm. ! 4: * ! 5: * SACREDMEM is the amount of physical memory saved for others; compress ! 6: * will hog the rest. ! 7: */ ! 8: #ifndef SACREDMEM ! 9: #define SACREDMEM 0 ! 10: #endif ! 11: ! 12: #ifdef pdp11 ! 13: # define BITS 12 /* max bits/code for 16-bit machine */ ! 14: # define NO_UCHAR /* also if "unsigned char" functions as signed char */ ! 15: # define SHORT_INT /* ints are short */ ! 16: # undef USERMEM ! 17: #else !pdp11 ! 18: # ifndef USERMEM ! 19: # define USERMEM 750000 /* default user memory */ ! 20: # endif ! 21: #endif !pdp11 ! 22: /* ! 23: * Define FBITS for machines with several MB of physical memory, to use ! 24: * table lookup for (b <= FBITS). If FBITS is made too large, performance ! 25: * will decrease due to increased swapping/paging. Since the program minus ! 26: * the fast lookup table is about a half Meg, we can allocate the rest of ! 27: * available physical memory to the fast lookup table. ! 28: * ! 29: * If FBITS is set to 12, a 2 MB array is allocated, but only 1 MB is ! 30: * addressed for parity-free input (i.e. text). ! 31: * ! 32: * FBITS=10 yields 1/2 meg lookup table + 4K code memory ! 33: * FBITS=11 yields 1 meg lookup table + 8K code memory ! 34: * FBITS=12 yields 2 meg lookup table + 16K code memory ! 35: * FBITS=13 yields 4 meg lookup table + 32K code memory ! 36: * ! 37: */ ! 38: ! 39: #ifdef USERMEM ! 40: # if USERMEM >= (2621440+SACREDMEM) ! 41: # if USERMEM >= (4718592+SACREDMEM) ! 42: # define FBITS 13 ! 43: # define PBITS 16 ! 44: # else 2.5M <= USERMEM < 4.5M ! 45: # define FBITS 12 ! 46: # define PBITS 16 ! 47: # endif USERMEM <=> 4.5M ! 48: # else USERMEM < 2.5M ! 49: # if USERMEM >= (1572864+SACREDMEM) ! 50: # define FBITS 11 ! 51: # define PBITS 16 ! 52: # else USERMEM < 1.5M ! 53: # if USERMEM >= (1048576+SACREDMEM) ! 54: # define FBITS 10 ! 55: # define PBITS 16 ! 56: # else USERMEM < 1M ! 57: # if USERMEM >= (631808+SACREDMEM) ! 58: # define PBITS 16 ! 59: # else ! 60: # if USERMEM >= (329728+SACREDMEM) ! 61: # define PBITS 15 ! 62: # else ! 63: # if USERMEM >= (178176+SACREDMEM) ! 64: # define PBITS 14 ! 65: # else ! 66: # if USERMEM >= (99328+SACREDMEM) ! 67: # define PBITS 13 ! 68: # else ! 69: # define PBITS 12 ! 70: # endif ! 71: # endif ! 72: # endif ! 73: # endif ! 74: # undef USERMEM ! 75: # endif USERMEM <=> 1M ! 76: # endif USERMEM <=> 1.5M ! 77: # endif USERMEM <=> 2.5M ! 78: #endif USERMEM ! 79: ! 80: #ifdef PBITS /* Preferred BITS for this memory size */ ! 81: # ifndef BITS ! 82: # define BITS PBITS ! 83: # endif BITS ! 84: #endif PBITS ! 85: ! 86: #if BITS == 16 ! 87: # define HSIZE 69001 /* 95% occupancy */ ! 88: #endif ! 89: #if BITS == 15 ! 90: # define HSIZE 35023 /* 94% occupancy */ ! 91: #endif ! 92: #if BITS == 14 ! 93: # define HSIZE 18013 /* 91% occupancy */ ! 94: #endif ! 95: #if BITS == 13 ! 96: # define HSIZE 9001 /* 91% occupancy */ ! 97: #endif ! 98: #if BITS == 12 ! 99: # define HSIZE 5003 /* 80% occupancy */ ! 100: #endif ! 101: #if BITS == 11 ! 102: # define HSIZE 2591 /* 79% occupancy */ ! 103: #endif ! 104: #if BITS == 10 ! 105: # define HSIZE 1291 /* 79% occupancy */ ! 106: #endif ! 107: #if BITS == 9 ! 108: # define HSIZE 691 /* 74% occupancy */ ! 109: #endif ! 110: /* BITS < 9 will cause an error */ ! 111: ! 112: /* ! 113: * a code_int must be able to hold 2**BITS values of type int, and also -1 ! 114: */ ! 115: #if BITS > 15 ! 116: typedef long int code_int; ! 117: #else ! 118: typedef int code_int; ! 119: #endif ! 120: ! 121: #ifdef interdata ! 122: typedef unsigned long int count_int; ! 123: typedef unsigned short int count_short; ! 124: #else ! 125: typedef long int count_int; ! 126: #endif ! 127: ! 128: #ifdef NO_UCHAR ! 129: typedef char char_type; ! 130: #else UCHAR ! 131: typedef unsigned char char_type; ! 132: #endif UCHAR ! 133: char_type magic_header[] = { "\037\235" }; /* 1F 9D */ ! 134: ! 135: /* Defines for third byte of header */ ! 136: #define BIT_MASK 0x1f ! 137: #define BLOCK_MASK 0x80 ! 138: /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is ! 139: a fourth header byte (for expansion). ! 140: */ ! 141: #define INIT_BITS 9 /* initial number of bits/code */ ! 142: ! 143: /* ! 144: * compress.c - File compression ala IEEE Computer June 1984. ! 145: * ! 146: * Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) ! 147: * Jim McKie (decvax!mcvax!jim) ! 148: * Steve Davies (decvax!vax135!petsd!peora!srd) ! 149: * Ken Turkowski (decvax!decwrl!turtlevax!ken) ! 150: * James A. Woods (decvax!ihnp4!ames!jaw) ! 151: * Joe Orost (decvax!vax135!petsd!joe) ! 152: * ! 153: * $Header: compress.c,v 3.0 84/11/27 11:50:00 joe Exp $ ! 154: * $Log: compress.c,v $ ! 155: * Revision 3.0 84/11/27 11:50:00 petsd!joe ! 156: * Set HSIZE depending on BITS. Set BITS depending on USERMEM. Unrolled ! 157: * loops in clear routines. Added "-C" flag for 2.0 compatability. Used ! 158: * unsigned compares on Perkin-Elmer. Fixed foreground check. ! 159: * ! 160: * Revision 2.7 84/11/16 19:35:39 ames!jaw ! 161: * Cache common hash codes based on input statistics; this improves ! 162: * performance for low-density raster images. Pass on #ifdef bundle ! 163: * from Turkowski. ! 164: * ! 165: * Revision 2.6 84/11/05 19:18:21 ames!jaw ! 166: * Vary size of hash tables to reduce time for small files. ! 167: * Tune PDP-11 hash function. ! 168: * ! 169: * Revision 2.5 84/10/30 20:15:14 ames!jaw ! 170: * Junk chaining; replace with the simpler (and, on the VAX, faster) ! 171: * double hashing, discussed within. Make block compression standard. ! 172: * ! 173: * Revision 2.4 84/10/16 11:11:11 ames!jaw ! 174: * Introduce adaptive reset for block compression, to boost the rate ! 175: * another several percent. (See mailing list notes.) ! 176: * ! 177: * Revision 2.3 84/09/22 22:00:00 petsd!joe ! 178: * Implemented "-B" block compress. Implemented REVERSE sorting of tab_next. ! 179: * Bug fix for last bits. Changed fwrite to putchar loop everywhere. ! 180: * ! 181: * Revision 2.2 84/09/18 14:12:21 ames!jaw ! 182: * Fold in news changes, small machine typedef from thomas, ! 183: * #ifdef interdata from joe. ! 184: * ! 185: * Revision 2.1 84/09/10 12:34:56 ames!jaw ! 186: * Configured fast table lookup for 32-bit machines. ! 187: * This cuts user time in half for b <= FBITS, and is useful for news batching ! 188: * from VAX to PDP sites. Also sped up decompress() [fwrite->putc] and ! 189: * added signal catcher [plus beef in writeerr()] to delete effluvia. ! 190: * ! 191: * Revision 2.0 84/08/28 22:00:00 petsd!joe ! 192: * Add check for foreground before prompting user. Insert maxbits into ! 193: * compressed file. Force file being uncompressed to end with ".Z". ! 194: * Added "-c" flag and "zcat". Prepared for release. ! 195: * ! 196: * Revision 1.10 84/08/24 18:28:00 turtlevax!ken ! 197: * Will only compress regular files (no directories), added a magic number ! 198: * header (plus an undocumented -n flag to handle old files without headers), ! 199: * added -f flag to force overwriting of possibly existing destination file, ! 200: * otherwise the user is prompted for a response. Will tack on a .Z to a ! 201: * filename if it doesn't have one when decompressing. Will only replace ! 202: * file if it was compressed. ! 203: * ! 204: * Revision 1.9 84/08/16 17:28:00 turtlevax!ken ! 205: * Removed scanargs(), getopt(), added .Z extension and unlimited number of ! 206: * filenames to compress. Flags may be clustered (-Ddvb12) or separated ! 207: * (-D -d -v -b 12), or combination thereof. Modes and other status is ! 208: * copied with copystat(). -O bug for 4.2 seems to have disappeared with ! 209: * 1.8. ! 210: * ! 211: * Revision 1.8 84/08/09 23:15:00 joe ! 212: * Made it compatible with vax version, installed jim's fixes/enhancements ! 213: * ! 214: * Revision 1.6 84/08/01 22:08:00 joe ! 215: * Sped up algorithm significantly by sorting the compress chain. ! 216: * ! 217: * Revision 1.5 84/07/13 13:11:00 srd ! 218: * Added C version of vax asm routines. Changed structure to arrays to ! 219: * save much memory. Do unsigned compares where possible (faster on ! 220: * Perkin-Elmer) ! 221: * ! 222: * Revision 1.4 84/07/05 03:11:11 thomas ! 223: * Clean up the code a little and lint it. (Lint complains about all ! 224: * the regs used in the asm, but I'm not going to "fix" this.) ! 225: * ! 226: * Revision 1.3 84/07/05 02:06:54 thomas ! 227: * Minor fixes. ! 228: * ! 229: * Revision 1.2 84/07/05 00:27:27 thomas ! 230: * Add variable bit length output. ! 231: * ! 232: */ ! 233: #ifndef lint ! 234: static char rcs_ident[] = "$Header: compress.c,v 3.0 84/11/27 11:50:00 joe Exp $"; ! 235: #endif !lint ! 236: ! 237: #include <stdio.h> ! 238: #include <ctype.h> ! 239: #include <signal.h> ! 240: #include <sys/types.h> ! 241: #include <sys/stat.h> ! 242: ! 243: #define ARGVAL() (*++(*argv) || (--argc && *++argv)) ! 244: ! 245: int n_bits; /* number of bits/code */ ! 246: int maxbits = BITS; /* user settable max # bits/code */ ! 247: code_int maxcode; /* maximum code, given n_bits */ ! 248: code_int maxmaxcode = 1 << BITS; /* should NEVER generate this code */ ! 249: #ifdef COMPATIBLE /* But wrong! */ ! 250: # define MAXCODE(n_bits) (1 << (n_bits) - 1) ! 251: #else COMPATIBLE ! 252: # define MAXCODE(n_bits) ((1 << (n_bits)) - 1) ! 253: #endif COMPATIBLE ! 254: ! 255: /* ! 256: * One code could conceivably represent (1<<BITS) characters, but ! 257: * to get a code of length N requires an input string of at least ! 258: * N*(N-1)/2 characters. With 5000 chars in the stack, an input ! 259: * file would have to contain a 25Mb string of a single character. ! 260: * This seems unlikely. ! 261: */ ! 262: #ifdef SHORT_INT ! 263: # define MAXSTACK 5000 /* size of output stack */ ! 264: #else !SHORT_INT ! 265: # define MAXSTACK 8000 /* size of output stack */ ! 266: #endif !SHORT_INT ! 267: ! 268: count_int htab [HSIZE]; ! 269: unsigned short codetab [HSIZE]; ! 270: code_int hsize = HSIZE; /* for dynamic table sizing */ ! 271: count_int fsize; ! 272: ! 273: #define tab_prefix codetab /* prefix code for this entry */ ! 274: char_type tab_suffix[1<<BITS]; /* last char in this entry */ ! 275: ! 276: #ifdef USERMEM ! 277: short ftable [(1 << FBITS) * 256]; ! 278: count_int fcodemem [1 << FBITS]; ! 279: #endif USERMEM ! 280: ! 281: code_int free_ent = 0; /* first unused entry */ ! 282: int exit_stat = 0; ! 283: ! 284: code_int getcode(); ! 285: ! 286: Usage() { ! 287: #ifdef DEBUG ! 288: fprintf(stderr,"Usage: compress [-dDvqfFc] [-b maxbits] [file ...]\n"); ! 289: } ! 290: int debug = 0; ! 291: #else DEBUG ! 292: fprintf(stderr,"Usage: compress [-dfFqc] [-b maxbits] [file ...]\n"); ! 293: } ! 294: #endif DEBUG ! 295: int nomagic = 0; /* Use a 2 byte magic number header, unless old file */ ! 296: int zcat_flg = 0; /* Write output on stdout, suppress messages */ ! 297: int quiet = 0; /* don't tell me about compression */ ! 298: ! 299: /* ! 300: * block compression parameters -- after all codes are used up, ! 301: * and compression rate changes, start over. ! 302: */ ! 303: int block_compress = BLOCK_MASK; ! 304: int clear_flg = 0; ! 305: double ratio = 0.0; /* compression ratio for last block */ ! 306: #define CHECK_GAP 10000 /* ratio check interval */ ! 307: count_int checkpoint = CHECK_GAP; ! 308: /* ! 309: * the next two codes should not be changed lightly, as they must not ! 310: * lie within the contiguous general code space. ! 311: */ ! 312: #define FIRST 257 /* first free entry */ ! 313: #define CLEAR 256 /* table clear output code */ ! 314: ! 315: int force = 0; ! 316: char ofname [100]; ! 317: #ifdef DEBUG ! 318: int verbose = 0; ! 319: #endif DEBUG ! 320: int (*bgnd_flag)(); ! 321: ! 322: /***************************************************************** ! 323: * TAG( main ) ! 324: * ! 325: * Algorithm from "A Technique for High Performance Data Compression", ! 326: * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19. ! 327: * ! 328: * Usage: compress [-dfFqc] [-b bits] [file ...] ! 329: * Inputs: ! 330: * -d: If given, decompression is done instead. ! 331: * ! 332: * -c: Write output on stdout, don't remove original. ! 333: * ! 334: * -b: Parameter limits the max number of bits/code. ! 335: * ! 336: * -f: Forces output file to be generated, even if one already ! 337: * exists; if -f is not used, the user will be prompted if ! 338: * the stdin is a tty, otherwise, the output file will not ! 339: * be overwritten. ! 340: * ! 341: * -F: Forces output file to be generated, even if no space is ! 342: * saved by compressing. ! 343: * ! 344: * -q: No output, unless error ! 345: * ! 346: * file ...: Files to be compressed. If none specified, stdin ! 347: * is used. ! 348: * Outputs: ! 349: * file.Z: Compressed form of file with same mode, owner, and utimes ! 350: * or stdout (if stdin used as input) ! 351: * ! 352: * Assumptions: ! 353: * When filenames are given, replaces with the compressed version ! 354: * (.Z suffix) only if the file decreased in size. ! 355: * Algorithm: ! 356: * Modified Lempel-Ziv method (LZW). Basically finds common ! 357: * substrings and replaces them with a variable size code. This is ! 358: * deterministic, and can be done on the fly. Thus, the decompression ! 359: * procedure needs no input table, but tracks the way the table was ! 360: * built. ! 361: */ ! 362: ! 363: main( argc, argv ) ! 364: register int argc; char **argv; ! 365: { ! 366: int do_decomp = 0; ! 367: int overwrite = 0; /* Do not overwrite unless given -f flag */ ! 368: char tempname[100]; ! 369: char **filelist, **fileptr; ! 370: char *cp, *rindex(); ! 371: struct stat statbuf; ! 372: extern onintr(); ! 373: ! 374: ! 375: if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) ! 376: signal ( SIGINT, onintr ); ! 377: ! 378: #ifdef COMPATIBLE ! 379: nomagic = 1; /* Original didn't have a magic number */ ! 380: #endif COMPATIBLE ! 381: ! 382: filelist = fileptr = (char **)(malloc(argc * sizeof(*argv))); ! 383: *filelist = NULL; ! 384: ! 385: if((cp = rindex(argv[0], '/')) != 0) { ! 386: cp++; ! 387: } else { ! 388: cp = argv[0]; ! 389: } ! 390: if(strcmp(cp, "uncompress") == 0) { ! 391: do_decomp = 1; ! 392: } else if(strcmp(cp, "zcat") == 0) { ! 393: do_decomp = 1; ! 394: zcat_flg = 1; ! 395: } ! 396: ! 397: #ifdef BSD4_2 ! 398: /* 4.2BSD dependent - take it out if not */ ! 399: setlinebuf( stderr ); ! 400: #endif BSD4_2 ! 401: ! 402: /* Argument Processing ! 403: * All flags are optional. ! 404: * -D => debug ! 405: * -d => do_decomp ! 406: * -v => verbose ! 407: * -f => force overwrite of output file ! 408: * -n => no header: useful to uncompress old files ! 409: * -b maxbits => maxbits. If -b is specified, then maxbits MUST be ! 410: * given also. ! 411: * -c => cat all output to stdout ! 412: * -C => generate output compatable with compress 2.0. ! 413: * if a string is left, must be an input filename. ! 414: */ ! 415: for (argc--, argv++; argc > 0; argc--, argv++) { ! 416: if (**argv == '-') { /* A flag argument */ ! 417: while (*++(*argv)) { /* Process all flags in this arg */ ! 418: switch (**argv) { ! 419: #ifdef DEBUG ! 420: case 'D': ! 421: debug = 1; ! 422: break; ! 423: case 'v': ! 424: verbose = 1; ! 425: break; ! 426: #endif DEBUG ! 427: case 'd': ! 428: do_decomp = 1; ! 429: break; ! 430: case 'f': ! 431: overwrite = 1; ! 432: break; ! 433: case 'n': ! 434: nomagic = 1; ! 435: break; ! 436: case 'C': ! 437: block_compress = 0; ! 438: break; ! 439: case 'b': ! 440: if (!ARGVAL()) { ! 441: fprintf(stderr, "Missing maxbits\n"); ! 442: Usage(); ! 443: exit(1); ! 444: } ! 445: maxbits = atoi(*argv); ! 446: goto nextarg; ! 447: case 'c': ! 448: zcat_flg = 1; ! 449: break; ! 450: case 'q': ! 451: quiet = 1; ! 452: break; ! 453: case 'F': ! 454: force = 1; ! 455: break; ! 456: default: ! 457: fprintf(stderr, "Unknown flag: '%c'; ", **argv); ! 458: Usage(); ! 459: exit(1); ! 460: } ! 461: } ! 462: } ! 463: else { /* Input file name */ ! 464: *fileptr++ = *argv; /* Build input file list */ ! 465: *fileptr = NULL; ! 466: /* goto nextarg; */ ! 467: } ! 468: nextarg: continue; ! 469: } ! 470: ! 471: if(maxbits < INIT_BITS) maxbits = INIT_BITS; ! 472: if (maxbits > BITS) maxbits = BITS; ! 473: maxmaxcode = 1 << maxbits; ! 474: ! 475: if (*filelist != NULL) { ! 476: for (fileptr = filelist; *fileptr; fileptr++) { ! 477: exit_stat = 0; ! 478: if (do_decomp != 0) { /* DECOMPRESSION */ ! 479: /* Check for .Z suffix */ ! 480: if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) { ! 481: /* No .Z: tack one on */ ! 482: strcpy(tempname, *fileptr); ! 483: strcat(tempname, ".Z"); ! 484: *fileptr = tempname; ! 485: } ! 486: /* Open input file */ ! 487: if ((freopen(*fileptr, "r", stdin)) == NULL) { ! 488: perror(*fileptr); continue; ! 489: } ! 490: /* Check the magic number */ ! 491: if (nomagic == 0) { ! 492: if ((getchar() != (magic_header[0] & 0xFF)) ! 493: || (getchar() != (magic_header[1] & 0xFF))) { ! 494: fprintf(stderr, "%s: not in compressed format\n", ! 495: *fileptr); ! 496: continue; ! 497: } ! 498: maxbits = getchar(); /* set -b from file */ ! 499: block_compress = maxbits & BLOCK_MASK; ! 500: maxbits &= BIT_MASK; ! 501: maxmaxcode = 1 << maxbits; ! 502: if(maxbits > BITS) { ! 503: fprintf(stderr, ! 504: "%s: compressed with %d bits, can only handle %d bits\n", ! 505: *fileptr, maxbits, BITS); ! 506: continue; ! 507: } ! 508: } ! 509: /* Generate output filename */ ! 510: strcpy(ofname, *fileptr); ! 511: ofname[strlen(*fileptr) - 2] = '\0'; /* Strip off .Z */ ! 512: } else { /* COMPRESSION */ ! 513: if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0) { ! 514: fprintf(stderr, "%s: already has .Z suffix -- no change\n", ! 515: *fileptr); ! 516: continue; ! 517: } ! 518: /* Open input file */ ! 519: if ((freopen(*fileptr, "r", stdin)) == NULL) { ! 520: perror(*fileptr); continue; ! 521: } ! 522: stat ( *fileptr, &statbuf ); ! 523: fsize = (long) statbuf.st_size; ! 524: /* ! 525: * tune hash table size for small files -- ad hoc ! 526: */ ! 527: #if HSIZE > 5003 ! 528: if ( fsize < (1 << 12) ) ! 529: hsize = 5003; ! 530: #if HSIZE > 9001 ! 531: else if ( fsize < (1 << 13) ) ! 532: hsize = 9001; ! 533: #if HSIZE > 18013 ! 534: else if ( fsize < (1 << 14) ) ! 535: hsize = 18013; ! 536: #if HSIZE > 35023 ! 537: else if ( fsize < (1 << 15) ) ! 538: hsize = 35023; ! 539: else if ( fsize < 47000 ) ! 540: hsize = 50021; ! 541: #endif HSIZE > 35023 ! 542: #endif HSIZE > 18013 ! 543: #endif HSIZE > 9001 ! 544: else ! 545: #endif HSIZE > 5003 ! 546: hsize = HSIZE; ! 547: /* Generate output filename */ ! 548: strcpy(ofname, *fileptr); ! 549: #ifndef BSD4_2 /* Short filenames */ ! 550: if ((cp=rindex(ofname,'/')) != NULL) cp++; ! 551: else cp = ofname; ! 552: if (strlen(cp) > 12) { ! 553: fprintf(stderr,"%s: filename too long to tack on .Z\n",cp); ! 554: continue; ! 555: } ! 556: #endif BSD4_2 /* Long filenames allowed */ ! 557: strcat(ofname, ".Z"); ! 558: } ! 559: /* Check for overwrite of existing file */ ! 560: if (overwrite == 0 && zcat_flg == 0) { ! 561: if (stat(ofname, &statbuf) == 0) { ! 562: char response[2]; ! 563: response[0] = 'n'; ! 564: fprintf(stderr, "%s already exists;", ofname); ! 565: if (foreground()) { ! 566: fprintf(stderr, " do you wish to overwrite (y or n)? ", ! 567: ofname); ! 568: fflush(stderr); ! 569: read(2, response, 2); ! 570: while (response[1] != '\n') { ! 571: if (read(2, response+1, 1) < 0) { /* Ack! */ ! 572: perror("stderr"); break; ! 573: } ! 574: } ! 575: } ! 576: if (response[0] != 'y') { ! 577: fprintf(stderr, "\tnot overwritten\n"); ! 578: continue; ! 579: } ! 580: } ! 581: } ! 582: if(zcat_flg == 0) { /* Open output file */ ! 583: if (freopen(ofname, "w", stdout) == NULL) { ! 584: perror(ofname); ! 585: continue; ! 586: } ! 587: if(!quiet) ! 588: fprintf(stderr, "%s: ", *fileptr); ! 589: } ! 590: ! 591: /* Actually do the compression/decompression */ ! 592: if (do_decomp == 0) compress(); ! 593: #ifndef DEBUG ! 594: else decompress(); ! 595: #else DEBUG ! 596: else if (debug == 0) decompress(); ! 597: else printcodes(); ! 598: if (verbose) dump_tab(); ! 599: #endif DEBUG ! 600: if(zcat_flg == 0) { ! 601: copystat(*fileptr, ofname); /* Copy stats */ ! 602: if(exit_stat || (!quiet)) ! 603: putc('\n', stderr); ! 604: } ! 605: } ! 606: } else { /* Standard input */ ! 607: if (do_decomp == 0) { ! 608: compress(); ! 609: if(!quiet) ! 610: putc('\n', stderr); ! 611: } else { ! 612: /* Check the magic number */ ! 613: if (nomagic == 0) { ! 614: if ((getchar()!=(magic_header[0] & 0xFF)) ! 615: || (getchar()!=(magic_header[1] & 0xFF))) { ! 616: fprintf(stderr, "stdin: not in compressed format\n"); ! 617: exit(1); ! 618: } ! 619: maxbits = getchar(); /* set -b from file */ ! 620: block_compress = maxbits & BLOCK_MASK; ! 621: maxbits &= BIT_MASK; ! 622: maxmaxcode = 1 << maxbits; ! 623: fsize = 100000; /* assume stdin large for USERMEM */ ! 624: if(maxbits > BITS) { ! 625: fprintf(stderr, ! 626: "stdin: compressed with %d bits, can only handle %d bits\n", ! 627: maxbits, BITS); ! 628: exit(1); ! 629: } ! 630: } ! 631: #ifndef DEBUG ! 632: decompress(); ! 633: #else DEBUG ! 634: if (debug == 0) decompress(); ! 635: else printcodes(); ! 636: if (verbose) dump_tab(); ! 637: #endif DEBUG ! 638: } ! 639: } ! 640: exit(exit_stat); ! 641: } ! 642: ! 643: static int offset; ! 644: long int in_count = 1; /* length of input */ ! 645: long int bytes_out; /* length of compressed output */ ! 646: long int out_count = 0; /* # of codes output (for debugging) */ ! 647: ! 648: #define HOG_CHECK ((count_int) 2000) /* Number of chars to read b4 check */ ! 649: #define MAX_CACHE ((count_int) 1<<BITS) /* Next line is this constant too */ ! 650: unsigned short hashcache [1<<BITS]; /* common hash short circuit cache */ ! 651: count_int cfreq [256]; /* character counts */ ! 652: #ifndef vax ! 653: char chog; /* most common character from input */ ! 654: # define CHOG ' ' /* Assume space is most frequent */ ! 655: #else ! 656: int chog; /* char arith slow on VAX */ ! 657: # define CHOG (int) ' ' /* Assume space is most frequent */ ! 658: #endif ! 659: int cstat_flg = 0; /* on after determining char hog */ ! 660: ! 661: /* ! 662: * compress stdin to stdout ! 663: * ! 664: * Algorithm: on large machines, for maxbits <= FBITS, use fast direct table ! 665: * lookup on the prefix code / next character combination. For smaller code ! 666: * size, use open addressing modular division double hashing (no chaining), ala ! 667: * Knuth vol. 3, sec. 6.4 Algorithm D, along with G. Knott's relatively-prime ! 668: * secondary probe. Do block compression with an adaptive reset, whereby the ! 669: * code table is cleared when the compression ratio decreases, but after the ! 670: * table fills. The variable-length output codes are re-sized at this point, ! 671: * and a special CLEAR code is generated for the decompressor. For the ! 672: * megamemory version, the sparse array is cleared indirectly through a ! 673: * "shadow" output code history. Late additions: for the hashing code, ! 674: * construct the table according to file size for noticeable speed improvement ! 675: * on small files. Also detect and cache codes associated with the most ! 676: * common character to bypass hash calculation on these codes (a characteristic ! 677: * of highly-compressable raster images). Please direct questions about this ! 678: * implementation to ames!jaw. ! 679: */ ! 680: ! 681: ! 682: compress() { ! 683: register long fcode; ! 684: register code_int i = 0; ! 685: register int c; ! 686: register code_int ent; ! 687: register int disp; ! 688: register code_int hsize_reg; ! 689: ! 690: #ifndef COMPATIBLE ! 691: if (nomagic == 0) { ! 692: putchar(magic_header[0]); putchar(magic_header[1]); ! 693: putchar((char)(maxbits | block_compress)); ! 694: } ! 695: #endif COMPATIBLE ! 696: ! 697: offset = 0; ! 698: bytes_out = 0; ! 699: out_count = 0; ! 700: clear_flg = 0; ! 701: ratio = 0.0; ! 702: in_count = 1; ! 703: checkpoint = CHECK_GAP; ! 704: maxcode = MAXCODE(n_bits = INIT_BITS); ! 705: free_ent = ((block_compress) ? FIRST : 256 ); ! 706: ent = getchar (); ! 707: ! 708: #ifdef USERMEM ! 709: if ( maxbits <= FBITS && (fsize >= 30000) ) { /* use hashing on small files */ ! 710: ! 711: while ( (c = getchar()) != (unsigned) EOF ) { ! 712: in_count++; ! 713: fcode = (long) (((long) c << maxbits) + ent); ! 714: if ( ftable [fcode] != 0 ) /* test for code in "string" table */ ! 715: ent = ftable [fcode]; ! 716: else { ! 717: output ( (code_int) ent ); ! 718: out_count++; ! 719: ent = c; ! 720: if ( free_ent >= maxmaxcode ) { ! 721: if ( (count_int)in_count < checkpoint || (!block_compress) ) ! 722: continue; ! 723: else { ! 724: clear (); ! 725: i = 0; ! 726: } ! 727: } else { /* put code in table */ ! 728: ftable [fcode] = (short) free_ent++; ! 729: fcodemem [i++] = fcode; /* memorize for block compression */ ! 730: } ! 731: } ! 732: } ! 733: goto fin; ! 734: } ! 735: #endif USERMEM ! 736: ! 737: chog = CHOG; /* assumed character for the hog */ ! 738: cstat_flg = 0; ! 739: hsize_reg = hsize; ! 740: cl_hash(hsize_reg); /* clear hash tables */ ! 741: ! 742: while ( (c = getchar()) != (unsigned) EOF ) { ! 743: in_count++; ! 744: if ( cstat_flg == 0 ) { ! 745: cfreq [c]++; /* gather frequencies at start of input */ ! 746: if ( (count_int)in_count > HOG_CHECK ) { ! 747: cstat_flg = 1; ! 748: chog = hogtally(); /* compute char hog */ ! 749: if(chog != CHOG) /* fixup for wrong assumption */ ! 750: creset( (count_int) free_ent ); ! 751: } ! 752: } ! 753: if ( c == chog ) ! 754: if ( (i = hashcache [ent]) ) { /* cache -> code */ ! 755: ent = i; ! 756: continue; ! 757: } ! 758: fcode = (long) (((long) c << maxbits) + ent); ! 759: #ifdef SHORT_INT ! 760: i = (((c + 12347) * ent) & 077777) % HSIZE; /* avoid 'lrem' call */ ! 761: #else !SHORT_INT ! 762: i = fcode % hsize_reg; /* division hashing */ ! 763: #endif SHORT_INT ! 764: ! 765: if ( htab [i] == fcode ) { ! 766: ent = codetab [i]; ! 767: continue; ! 768: } else if ( (long)htab [i] < 0 ) /* empty slot */ ! 769: goto nomatch; ! 770: disp = hsize_reg - i; /* secondary hash (G. Knott) */ ! 771: if ( i == 0 ) ! 772: disp = 1; ! 773: probe: ! 774: if ( (i -= disp) < 0 ) ! 775: i += hsize_reg; ! 776: ! 777: if ( htab [i] == fcode ) { ! 778: ent = codetab [i]; ! 779: continue; ! 780: } ! 781: if ( (long)htab [i] > 0 ) ! 782: goto probe; ! 783: nomatch: ! 784: output ( (code_int) ent ); ! 785: out_count++; ! 786: #ifdef interdata ! 787: if ( (unsigned) free_ent < (unsigned) maxmaxcode) { ! 788: #else ! 789: if ( free_ent < maxmaxcode ) { ! 790: #endif ! 791: if ( c == chog ) /* code -> cache */ ! 792: hashcache [ent] = free_ent; ! 793: /* code -> hashtable */ ! 794: codetab [i] = free_ent++; ! 795: htab [i] = fcode; ! 796: } ! 797: else if ( (count_int)in_count >= checkpoint && block_compress ) ! 798: clear (); ! 799: ent = c; ! 800: } ! 801: fin: ! 802: /* ! 803: * Put out the final code. ! 804: */ ! 805: output( (code_int)ent ); ! 806: out_count++; ! 807: output( (code_int)-1 ); ! 808: ! 809: /* ! 810: * Print out stats on stderr ! 811: */ ! 812: if(zcat_flg == 0 && !quiet) { ! 813: #ifdef DEBUG ! 814: fprintf( stderr, ! 815: "%ld chars in, %ld codes (%ld bytes) out, compression factor %g\n", ! 816: in_count, out_count, bytes_out, ! 817: (double)in_count / (double)bytes_out ); ! 818: fprintf( stderr, "\tCompression as in compact: %5.2f%%\n", ! 819: 100.0 * ( in_count - bytes_out ) / (double) in_count ); ! 820: fprintf( stderr, "\tLargest code was %d (%d bits)\n", free_ent - 1, n_bits ); ! 821: #else DEBUG ! 822: fprintf( stderr, "Compression: %5.2f%%", ! 823: 100.0 * ( in_count - bytes_out ) / (double) in_count ); ! 824: #endif DEBUG ! 825: } ! 826: if(bytes_out > in_count) /* exit(2) if no savings */ ! 827: exit_stat = 2; ! 828: return; ! 829: } ! 830: ! 831: /***************************************************************** ! 832: * TAG( output ) ! 833: * ! 834: * Output the given code. ! 835: * Inputs: ! 836: * code: A n_bits-bit integer. If == -1, then EOF. This assumes ! 837: * that n_bits =< (long)wordsize - 1. ! 838: * Outputs: ! 839: * Outputs code to the file. ! 840: * Assumptions: ! 841: * Chars are 8 bits long. ! 842: * Algorithm: ! 843: * Maintain a BITS character long buffer (so that 8 codes will ! 844: * fit in it exactly). Use the VAX insv instruction to insert each ! 845: * code in turn. When the buffer fills up empty it and start over. ! 846: */ ! 847: ! 848: static char buf[BITS]; ! 849: ! 850: #ifndef vax ! 851: char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; ! 852: char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; ! 853: #endif !vax ! 854: ! 855: output( code ) ! 856: code_int code; ! 857: { ! 858: #ifdef DEBUG ! 859: static int col = 0; ! 860: #endif DEBUG ! 861: ! 862: /* ! 863: * On the VAX, it is important to have the register declarations ! 864: * in exactly the order given, or the asm will break. ! 865: */ ! 866: register int r_off = offset, bits= n_bits; ! 867: register char * bp = buf; ! 868: ! 869: if ( code >= 0 ) { ! 870: #ifdef DEBUG ! 871: if ( verbose ) ! 872: fprintf( stderr, "%5d%c", code, ! 873: (col+=6) >= 74 ? (col = 0, '\n') : ' ' ); ! 874: #endif DEBUG ! 875: #ifdef vax ! 876: /* VAX DEPENDENT!! Implementation on other machines may be ! 877: * difficult. ! 878: * ! 879: * Translation: Insert BITS bits from the argument starting at ! 880: * offset bits from the beginning of buf. ! 881: */ ! 882: 0; /* C compiler bug ?? */ ! 883: asm( "insv 4(ap),r11,r10,(r9)" ); ! 884: #else not a vax ! 885: /* WARNING: byte/bit numbering on the vax is simulated by the following code ! 886: */ ! 887: /* ! 888: * Get to the first byte. ! 889: */ ! 890: bp += (r_off >> 3); ! 891: r_off &= 7; ! 892: /* ! 893: * Since code is always >= 8 bits, only need to mask the first ! 894: * hunk on the left. ! 895: */ ! 896: *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off]; ! 897: bp++; ! 898: bits -= (8 - r_off); ! 899: code >>= 8 - r_off; ! 900: /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ ! 901: if ( bits >= 8 ) { ! 902: *bp++ = code; ! 903: code >>= 8; ! 904: bits -= 8; ! 905: } ! 906: /* Last bits. */ ! 907: if(bits) ! 908: *bp = code; ! 909: #endif vax ! 910: offset += n_bits; ! 911: if ( offset == (n_bits << 3) ) { ! 912: bp = buf; ! 913: bits = n_bits; ! 914: bytes_out += bits; ! 915: do ! 916: putchar(*bp++); ! 917: while(--bits); ! 918: if (ferror(stdout)) ! 919: writeerr(); ! 920: offset = 0; ! 921: } ! 922: ! 923: /* ! 924: * If the next entry is going to be too big for the code size, ! 925: * then increase it, if possible. ! 926: */ ! 927: if ( free_ent > maxcode || (clear_flg > 0)) { ! 928: /* ! 929: * Write the whole buffer, because the input side won't ! 930: * discover the size increase until after it has read it. ! 931: */ ! 932: if ( offset > 0 ) { ! 933: if( fwrite( buf, 1, n_bits, stdout ) != n_bits) ! 934: writeerr(); ! 935: bytes_out += n_bits; ! 936: } ! 937: offset = 0; ! 938: ! 939: if ( clear_flg ) { ! 940: maxcode = MAXCODE (n_bits = INIT_BITS); ! 941: clear_flg = 0; ! 942: } else { ! 943: n_bits++; ! 944: if ( n_bits == maxbits ) ! 945: maxcode = maxmaxcode; ! 946: else ! 947: maxcode = MAXCODE(n_bits); ! 948: } ! 949: #ifdef DEBUG ! 950: if ( debug ) { ! 951: fprintf( stderr, "\nChange to %d bits\n", n_bits ); ! 952: col = 0; ! 953: } ! 954: #endif DEBUG ! 955: } ! 956: } else { ! 957: /* ! 958: * At EOF, write the rest of the buffer. ! 959: */ ! 960: if ( offset > 0 ) ! 961: fwrite( buf, 1, (offset + 7) / 8, stdout ); ! 962: bytes_out += (offset + 7) / 8; ! 963: offset = 0; ! 964: fflush( stdout ); ! 965: #ifdef DEBUG ! 966: if ( verbose ) ! 967: fprintf( stderr, "\n" ); ! 968: #endif DEBUG ! 969: if( ferror( stdout ) ) ! 970: writeerr(); ! 971: } ! 972: } ! 973: ! 974: decompress() { ! 975: register int stack_top = MAXSTACK; ! 976: register code_int code, oldcode, incode; ! 977: register int finchar; ! 978: char stack[MAXSTACK]; ! 979: ! 980: /* ! 981: * As above, initialize the first 256 entries in the table. ! 982: */ ! 983: maxcode = MAXCODE(n_bits = INIT_BITS); ! 984: for ( code = 255; code >= 0; code-- ) { ! 985: tab_prefix[code] = 0; ! 986: tab_suffix[code] = (char_type)code; ! 987: } ! 988: free_ent = ((block_compress) ? FIRST : 256 ); ! 989: ! 990: finchar = oldcode = getcode(); ! 991: putchar( (char)finchar ); /* first code must be 8 bits = char */ ! 992: ! 993: while ( (code = getcode()) != -1 ) { ! 994: ! 995: if ( (code == CLEAR) && block_compress ) { ! 996: for ( code = 255; code > 0; code -= 4 ) { ! 997: tab_prefix [code-3] = 0; ! 998: tab_prefix [code-2] = 0; ! 999: tab_prefix [code-1] = 0; ! 1000: tab_prefix [code] = 0; ! 1001: } ! 1002: clear_flg = 1; ! 1003: free_ent = FIRST - 1; ! 1004: if ( (code = getcode ()) == -1 ) /* O, untimely death! */ ! 1005: break; ! 1006: } ! 1007: incode = code; ! 1008: /* ! 1009: * Special case for KwKwK string. ! 1010: */ ! 1011: if ( code >= free_ent ) { ! 1012: stack[--stack_top] = finchar; ! 1013: code = oldcode; ! 1014: } ! 1015: ! 1016: /* ! 1017: * Generate output characters in reverse order ! 1018: */ ! 1019: #ifdef interdata ! 1020: while ( ((unsigned long)code) >= ((unsigned long)256) ) { ! 1021: #else !interdata ! 1022: while ( code >= 256 ) { ! 1023: #endif interdata ! 1024: stack[--stack_top] = tab_suffix[code]; ! 1025: code = tab_prefix[code]; ! 1026: } ! 1027: stack[--stack_top] = finchar = tab_suffix[code]; ! 1028: ! 1029: /* ! 1030: * And put them out in forward order ! 1031: */ ! 1032: for ( ; stack_top < MAXSTACK; stack_top++ ) ! 1033: putchar(stack[stack_top]); ! 1034: if (ferror(stdout)) ! 1035: writeerr ( ); ! 1036: stack_top = MAXSTACK; ! 1037: ! 1038: /* ! 1039: * Generate the new entry. ! 1040: */ ! 1041: if ( (code=free_ent) < maxmaxcode ) { ! 1042: tab_prefix[code] = (unsigned short)oldcode; ! 1043: tab_suffix[code] = finchar; ! 1044: free_ent = code+1; ! 1045: } ! 1046: /* ! 1047: * Remember previous code. ! 1048: */ ! 1049: oldcode = incode; ! 1050: } ! 1051: fflush( stdout ); ! 1052: if(ferror(stdout)) ! 1053: writeerr(); ! 1054: } ! 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 NO_UCHAR ! 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 NO_UCHAR ! 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. Mostly 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: dump_tab() /* dump string table */ ! 1181: { ! 1182: register int i; ! 1183: register ent; ! 1184: char stack[4 * MAXSTACK]; /* \nnn makes it 4 times bigger */ ! 1185: int stack_top = 4 * MAXSTACK; ! 1186: ! 1187: for ( i = 0; i < free_ent; i++ ) { ! 1188: ent = i; ! 1189: if ( isascii(tab_suffix[ent]) && isprint(tab_suffix[ent]) ) ! 1190: fprintf( stderr, "%5d: %5d/'%c' \"", ! 1191: ent, tab_prefix[ent], tab_suffix[ent] ); ! 1192: else ! 1193: fprintf( stderr, "%5d: %5d/\\%03o \"", ! 1194: ent, tab_prefix[ent], tab_suffix[ent] ); ! 1195: stack[--stack_top] = '\n'; ! 1196: stack[--stack_top] = '"'; ! 1197: for ( ; ent != NULL; ! 1198: ent = (ent >= FIRST ? tab_prefix[ent] : NULL) ) { ! 1199: if ( isascii(tab_suffix[ent]) && isprint(tab_suffix[ent]) ) ! 1200: stack[--stack_top] = tab_suffix[ent]; ! 1201: else { ! 1202: switch( tab_suffix[ent] ) { ! 1203: case '\n': stack[--stack_top] = 'n'; break; ! 1204: case '\t': stack[--stack_top] = 't'; break; ! 1205: case '\b': stack[--stack_top] = 'b'; break; ! 1206: case '\f': stack[--stack_top] = 'f'; break; ! 1207: case '\r': stack[--stack_top] = 'r'; break; ! 1208: default: ! 1209: stack[--stack_top] = '0' + tab_suffix[ent] % 8; ! 1210: stack[--stack_top] = '0' + (tab_suffix[ent] / 8) % 8; ! 1211: stack[--stack_top] = '0' + tab_suffix[ent] / 64; ! 1212: break; ! 1213: } ! 1214: stack[--stack_top] = '\\'; ! 1215: } ! 1216: } ! 1217: fwrite( &stack[stack_top], 1, 4 * MAXSTACK - stack_top, stderr ); ! 1218: stack_top = 4 * MAXSTACK; ! 1219: } ! 1220: } ! 1221: #endif DEBUG ! 1222: ! 1223: /***************************************************************** ! 1224: * TAG( writeerr ) ! 1225: * ! 1226: * Exits with a message. We only check for write errors often enough ! 1227: * to avoid a lot of "file system full" messages, not on every write. ! 1228: * ferror() check after fflush will catch any others (I trust). ! 1229: * ! 1230: */ ! 1231: ! 1232: writeerr() ! 1233: { ! 1234: perror ( ofname ); ! 1235: unlink ( ofname ); ! 1236: exit ( 1 ); ! 1237: } ! 1238: ! 1239: copystat(ifname, ofname) ! 1240: char *ifname, *ofname; ! 1241: { ! 1242: struct stat statbuf; ! 1243: int mode; ! 1244: time_t timep[2]; ! 1245: ! 1246: fclose(stdout); ! 1247: if (stat(ifname, &statbuf)) { /* Get stat on input file */ ! 1248: perror(ifname); ! 1249: return; ! 1250: } ! 1251: if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) { ! 1252: if(quiet) ! 1253: fprintf(stderr, "%s: ", ifname); ! 1254: fprintf(stderr, " -- not a regular file: unchanged"); ! 1255: exit_stat = 1; ! 1256: } else if (statbuf.st_nlink > 1) { ! 1257: if(quiet) ! 1258: fprintf(stderr, "%s: ", ifname); ! 1259: fprintf(stderr, " -- has %d other links: unchanged", ! 1260: statbuf.st_nlink - 1); ! 1261: exit_stat = 1; ! 1262: } else if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */ ! 1263: fprintf(stderr, " -- file unchanged"); ! 1264: } else { /* ***** Successful Compression ***** */ ! 1265: exit_stat = 0; ! 1266: mode = statbuf.st_mode & 07777; ! 1267: if (chmod(ofname, mode)) /* Copy modes */ ! 1268: perror(ofname); ! 1269: chown(ofname, statbuf.st_uid, statbuf.st_gid); /* Copy ownership */ ! 1270: timep[0] = statbuf.st_atime; ! 1271: timep[1] = statbuf.st_mtime; ! 1272: utime(ofname, timep); /* Update last accessed and modified times */ ! 1273: if (unlink(ifname)) /* Remove input file */ ! 1274: perror(ifname); ! 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: * This routine returns 1 if we are running in the foreground and stderr ! 1286: * is a tty. ! 1287: */ ! 1288: foreground() ! 1289: { ! 1290: if(bgnd_flag) { /* background? */ ! 1291: return(0); ! 1292: } else { /* foreground */ ! 1293: if(isatty(2)) { /* and stderr is a tty */ ! 1294: return(1); ! 1295: } else { ! 1296: return(0); ! 1297: } ! 1298: } ! 1299: } ! 1300: ! 1301: onintr ( ) ! 1302: { ! 1303: unlink ( ofname ); ! 1304: exit ( 1 ); ! 1305: } ! 1306: ! 1307: clear () /* table clear for block compress */ ! 1308: { ! 1309: register code_int i; ! 1310: register count_int *p, *endp; ! 1311: register unsigned short *q; ! 1312: ! 1313: #ifdef DEBUG ! 1314: if(debug) ! 1315: fprintf ( stderr, "count: %ld ratio: %f\n", in_count, ! 1316: (double) in_count / (double) bytes_out ); ! 1317: #endif DEBUG ! 1318: ! 1319: checkpoint = in_count + CHECK_GAP; ! 1320: if ( (double) in_count / (double) bytes_out > ratio ) ! 1321: ratio = (double) in_count / (double) bytes_out; ! 1322: else { ! 1323: ratio = 0.0; ! 1324: #ifdef USERMEM ! 1325: if ( maxbits <= FBITS ) /* sparse array clear */ ! 1326: for ( i = (1 << maxbits) - 1; i >= 0; i-- ) ! 1327: ftable [fcodemem [i]] = 0; /* indirect thru "shadow" */ ! 1328: else ! 1329: #endif USERMEM /* hash table clear */ ! 1330: { ! 1331: endp = &htab [hsize]; ! 1332: for ( p = &htab [0], q = &codetab [0]; p < endp; ) { ! 1333: *p++ = -1; ! 1334: *q++ = 0; ! 1335: } ! 1336: creset ( MAX_CACHE ); ! 1337: } ! 1338: free_ent = FIRST; ! 1339: clear_flg = 1; ! 1340: output ( (code_int) CLEAR ); ! 1341: #ifdef DEBUG ! 1342: if(debug) ! 1343: fprintf ( stderr, "clear\n" ); ! 1344: #endif DEBUG ! 1345: } ! 1346: } ! 1347: ! 1348: creset ( n ) /* clear hash cache */ ! 1349: register count_int n; /* clear at least this many entries */ ! 1350: { ! 1351: register count_int i; ! 1352: register unsigned short *hash_p; ! 1353: register unsigned short zero = 0; ! 1354: static int nfiles = 0; ! 1355: ! 1356: if ( nfiles++ == 0 ) /* No clear needed if first time */ ! 1357: return; ! 1358: n = (n+15) & (-16); ! 1359: hash_p = hashcache + n; ! 1360: for ( i = n; i > 0; i -=16 ) { ! 1361: *(hash_p-16) = zero; ! 1362: *(hash_p-15) = zero; ! 1363: *(hash_p-14) = zero; ! 1364: *(hash_p-13) = zero; ! 1365: *(hash_p-12) = zero; ! 1366: *(hash_p-11) = zero; ! 1367: *(hash_p-10) = zero; ! 1368: *(hash_p-9) = zero; ! 1369: *(hash_p-8) = zero; ! 1370: *(hash_p-7) = zero; ! 1371: *(hash_p-6) = zero; ! 1372: *(hash_p-5) = zero; ! 1373: *(hash_p-4) = zero; ! 1374: *(hash_p-3) = zero; ! 1375: *(hash_p-2) = zero; ! 1376: *(hash_p-1) = zero; ! 1377: hash_p -= 16; ! 1378: } ! 1379: } ! 1380: ! 1381: hogtally () /* compute character code hog */ ! 1382: { ! 1383: register int i, most; ! 1384: ! 1385: for ( i = most = 0; i < 256; i++ ) ! 1386: if ( cfreq [i] >= cfreq [most] ) ! 1387: most = i; ! 1388: return ( most ); ! 1389: } ! 1390: ! 1391: cl_hash(hsize) ! 1392: register int hsize; ! 1393: { ! 1394: register count_int *htab_p = htab+hsize; ! 1395: register int i; ! 1396: register long m1 = -1; ! 1397: ! 1398: /* clear hashcache */ ! 1399: #define min(a,b) ((a>b) ? b : a) ! 1400: creset( min((count_int)hsize, MAX_CACHE) ); ! 1401: ! 1402: i = hsize - 16; ! 1403: do { ! 1404: *(htab_p-16) = m1; ! 1405: *(htab_p-15) = m1; ! 1406: *(htab_p-14) = m1; ! 1407: *(htab_p-13) = m1; ! 1408: *(htab_p-12) = m1; ! 1409: *(htab_p-11) = m1; ! 1410: *(htab_p-10) = m1; ! 1411: *(htab_p-9) = m1; ! 1412: *(htab_p-8) = m1; ! 1413: *(htab_p-7) = m1; ! 1414: *(htab_p-6) = m1; ! 1415: *(htab_p-5) = m1; ! 1416: *(htab_p-4) = m1; ! 1417: *(htab_p-3) = m1; ! 1418: *(htab_p-2) = m1; ! 1419: *(htab_p-1) = m1; ! 1420: htab_p -= 16; ! 1421: } while ((i -= 16) >= 0); ! 1422: for ( i += 16; i > 0; i-- ) ! 1423: *--htab_p = m1; ! 1424: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.