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