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