/* * nushk.c - P8 ShrinkIt compress/uncompress routines * * NuLib v3.0 February 1991 Freeware (distribute, don't sell) * By Andy McFadden (fadden@cory.berkeley.edu) */ #ifdef APW segment "Compress" #endif #include "nudefs.h" #include #include #ifdef MSDOS /* For file IO */ # include # include # include # include #endif #include "nuread.h" /* need CalcCRC() */ #include "nupak.h" #include "nuetc.h" #define BLKSIZ 4096 /*#define DEBUG /* do verbose debugging output */ /*#define DEBUG1 /* debugging output in main routine */ static onebyt *ibuf; /* large buffer (usually set to packBuffer) */ onebyt lbuf[BLKSIZ+7]; /* temporary buffer for storing data after LZW */ onebyt rbuf[BLKSIZ+7]; /* temporary buffer for storing data after RLE */ /* * P8 ShrinkIt compression routines * Copyright 1989 Kent Dickey * * C translation by Kent Dickey / Andy McFadden */ #define ESCAPE_CHAR 0xdb #define HSIZE 4219 /* Must be prime */ struct ht { int entry; int prefix; unsigned char chr; } htab[HSIZE]; int s_at_bit; int s_at_byte; int mask[] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff }; int bit_tab[] = { 0,9,10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12 }; /* * Output code to buffer. */ int put_code(code, ent, bfr) int code; register int ent; char *bfr; { int lo_byte; long mycode; int bits; bits = bit_tab[(ent >> 8)]; /* if (((s_at_bit + bits + 7) / 8) + s_at_byte > BLKSIZ) {*/ if (((s_at_bit + bits + 7) >> 3) + s_at_byte > BLKSIZ) { return(-1); } mycode = (long)(code & mask[bits]); /* fprintf(stderr,"Byte: %d, %lx\n", s_at_byte, mycode); */ lo_byte = bfr[s_at_byte] & mask[s_at_bit]; if (s_at_bit != 0) { mycode <<= s_at_bit; } bfr[s_at_byte++] = (unsigned char)lo_byte | (char)(mycode & 0xff); bfr[s_at_byte] = (unsigned char)((mycode >>= 8) & 0xff); if ((s_at_bit += bits) >= 16) { bfr[++s_at_byte] = (char)((mycode >>= 8) & 0xff); } s_at_bit &= 0x07; return(0); } /* * Try LZW compression on the buffer. * * Compresses from "buffer" to "outbuf". "inlen" is the #of bytes of data in * "buffer." Returns the #of bytes of data placed into "outbuf", or -1 on * failure. */ int do_LZW(bufr, inlen, outbuf) unsigned char *bufr; int inlen; unsigned char *outbuf; { int ent, prefix; register int index; register unsigned char k; register unsigned char *inbuf, *endbuf; s_at_byte = 0; s_at_bit =0; ent = 0x101; inbuf = bufr; endbuf = bufr + inlen; k = ((char)*inbuf++); Loop0: prefix = (int)k; Loop1: if (inbuf >= endbuf) { if (put_code(prefix, ent, outbuf) < 0) { return(BLKSIZ+2); } if (s_at_bit == 0) return(s_at_byte); else return(s_at_byte+1); } k = (unsigned char)*inbuf++; index = (prefix + (k<<4)) & 0xfff; Check_ent: if (htab[index].entry == 0) { /* Entry is 0... */ if (put_code(prefix, ent, outbuf) < 0) { return(-1); /* failed */ } htab[index].entry = ent++; htab[index].prefix = prefix; htab[index].chr = k; goto Loop0; } else if (htab[index].prefix == prefix) { /* Same prefix... */ if (htab[index].chr == k) { /* It's HERE! Yeah! */ prefix = htab[index].entry; goto Loop1; } goto Sec_hash; } /* Check for more...secondary hash on index */ else { Sec_hash: index = (index + (unsigned int)(k) + 1) % HSIZE; /* fprintf(stderr,"New ind: %d, k=%d\n", index, (unsigned int)k); */ goto Check_ent; } } /* * Clear out the hash table. */ void ClearTab() { register int i; for(i=0; i < HSIZE; i++) { htab[i].entry = 0; } } /* * Do run-length encoding * * Takes input from srcptr, and writes to dstptr. Maximum expansion is * (BLKSIZ / 2) + (BLKSIZ / 2) * 3 == 2 * BLKSIZ * Output of form char count * * This really isn't very pretty, but it works. */ int do_RLE(srcptr, dstptr) register onebyt *srcptr, *dstptr; { int found, scount, dcount; register onebyt c, lastc, tlastc; c = *(srcptr++); scount = 1; dcount = 0; found = 1; /* one char has been found */ lastc = '\0'; while (scount < BLKSIZ) { tlastc = lastc; lastc = c; c = *(srcptr++); scount++; if (found == 1) { /* no run found */ if (c != lastc) { /* no run starting */ if (lastc == ESCAPE_CHAR) { *(dstptr++) = ESCAPE_CHAR; dcount++; *(dstptr++) = lastc; dcount++; *(dstptr++) = 0; dcount++; /* found one */ } else { *(dstptr++) = lastc; dcount++; } found = 1; } else { found = 2; /* they matched, so two in a row */ } } else if (found == 2) { /* got two, try for three */ if (c != lastc) { /* only got two in a row */ if (lastc == ESCAPE_CHAR) { /* and tlastc as well */ *(dstptr++) = ESCAPE_CHAR; dcount++; *(dstptr++) = lastc; dcount++; *(dstptr++) = 1; dcount++; /* found two */ } else { *(dstptr++) = tlastc; dcount++; *(dstptr++) = lastc; dcount++; } found = 1; } else { /* found 3, got a run going */ found = 3; } } else { /* (found >= 3), got a run going */ if (c == lastc) { /* found another */ found++; } if ((c != lastc) || (found > 256)) { /* end, or too many */ *(dstptr++) = ESCAPE_CHAR; dcount++; *(dstptr++) = lastc; dcount++; *(dstptr++) = (found > 256) ? 255 : found-1; dcount++; found = 1; /* c has something other than the run char */ /* or found is 257-256 = 1 */ } } } /* while */ /* reached end of buffer; flush what was left */ if (found == 1) { if (c == ESCAPE_CHAR) { *(dstptr++) = ESCAPE_CHAR; dcount++; *(dstptr++) = c; dcount++; *(dstptr++) = 0; dcount++; } else { *(dstptr++) = c; dcount++; } } else if (found == 2) { /* maybe have if lastc == c == ESCAPE_CHAR? */ if (lastc == ESCAPE_CHAR) { *(dstptr++) = ESCAPE_CHAR; dcount++; *(dstptr++) = lastc; dcount++; *(dstptr++) = 0; dcount++; } else { *(dstptr++) = lastc; dcount++; } if (c == ESCAPE_CHAR) { *(dstptr++) = ESCAPE_CHAR; dcount++; *(dstptr++) = c; dcount++; *(dstptr++) = 0; dcount++; } else { *(dstptr++) = c; dcount++; } } else { /* found >= 3, in the middle of processing a run */ *(dstptr++) = ESCAPE_CHAR; dcount++; *(dstptr++) = c; dcount++; *(dstptr++) = found-1; dcount++; } return (dcount); } /* * Main compression entry point. * * Returns actual thread_format used. * * Note that "copybuf" should be at least twice as big as BLKSIZ. */ long pak_SHK(srcfd, dstfd, length, copybuf) int srcfd, dstfd; long length; /* uncompressed size */ onebyt *copybuf; { unsigned int partial; /* size for partial read/write */ onebyt *rptr, *out_buf; register int idx; onebyt scratch[8]; long srcposn, /* start in source file */ startposn, /* start in dest file */ endposn; /* end in dest file */ long unc_len = length, comp_len = 0L; twobyt CRC; int rlesize, lzwsize, out_size; /* length after compression */ int sc; /* spin counter */ static char *procName = "pak_SHK"; CRC = 0; if ((srcposn = lseek(srcfd, 0L, S_REL)) < 0) /* only used if */ Fatal("Bad seek (srcposn)", procName); /* compress fails */ if ((startposn = lseek(dstfd, 0L, S_REL)) < 0) Fatal("Bad seek (startposn)", procName); lseek(dstfd, 4L, S_REL); /* leave room for 4-byte header */ comp_len += 4L; sc = 0; do { /* have to handle when length == 0L */ if (length > (long) BLKSIZ) { partial = (unsigned int) BLKSIZ; length -= (long) BLKSIZ; } else { partial = (unsigned int) length; length = 0L; for (idx = partial; idx < BLKSIZ; idx++) /* fill in zeroes */ *(copybuf + idx) = 0; } if (partial > 0) { /* should work anyway, but let's be careful */ if (read(srcfd, copybuf, partial) != partial) Fatal("Source read failed", procName); } /* calc CRC on all 4096 bytes */ CRC = CalcCRC(CRC, (onebyt *) copybuf, BLKSIZ); rlesize = do_RLE(copybuf, copybuf + BLKSIZ+1); /* pack 4096 bytes */ if (rlesize < 0x1000) { /* did it pack or expand? */ rptr = copybuf + BLKSIZ+1; /* use packed version */ } else { rlesize = 0x1000; /* just store original */ rptr = copybuf; } ClearTab(); lzwsize = do_LZW(rptr, rlesize, lbuf); /* compress from rle to lzw */ if ((lzwsize > rlesize) || (lzwsize < 0)) { /* lzw failed, use rle'd copy */ scratch[2] = 0; out_size = rlesize; out_buf = rptr; } else { /* lzw succeeded, use it */ scratch[2] = 1; /* LZW on */ out_size = lzwsize; out_buf = lbuf; } scratch[0] = (onebyt) (rlesize & 0x00ff); /* NOT out_size */ scratch[1] = (onebyt) ((rlesize >> 8) & 0x00ff); if (write(dstfd, scratch, 3) != 3) Fatal("Dest hdr write failed", procName); comp_len += 3; comp_len += out_size; if (comp_len > unc_len) goto bad_compress; /* you didn't see this */ if (write(dstfd, out_buf, out_size) != out_size) /* need to do CRLF */ Fatal("Dest write failed", procName); sc++; if (sc == 15) { sc = 0; Spin(); } } while (length != 0L); if ((endposn = lseek(dstfd, 0L, S_REL)) < 0) Fatal("Bad seek (now)", procName); if (lseek(dstfd, startposn, S_ABS) < 0) Fatal("Bad seek (to4)", procName); scratch[0] = (char) CRC; scratch[1] = (char) (CRC >> 8); scratch[2] = 0; scratch[3] = ESCAPE_CHAR; if (write(dstfd, scratch, 4) != 4) Fatal("Dest hdr write failed", procName); if (lseek(dstfd, endposn, S_ABS) < 0) Fatal("Bad seek (last)", procName); if (comp_len != endposn - startposn) { printf( "internal error: comp_len=%ld, endposn=%ld, startposn=%ld (%ld)\n", comp_len, endposn, startposn, endposn - startposn); } packedSize = comp_len; return (0x0002); /* SHK packing */ bad_compress: /* I'm too lazy to do a procedure call... */ if (verbose) { printf("storing..."); fflush(stdout); } if (lseek(srcfd, srcposn, S_ABS) < 0) Fatal("Bad seek (srcposn in bad_compress)", procName); if (lseek(dstfd, startposn, S_ABS) < 0) Fatal("Bad seek (startposn in bad_compress)", procName); FCopy(srcfd, dstfd, unc_len, copybuf, FALSE); packedSize = unc_len; return (0x0000); /* no compression */ } /* * P8 ShrinkIt uncompression routines * * Copyright 1989 Kent Dickey * C translation by Kent Dickey / Andy McFadden * Modifications for LZW-II by Andy Nicholas */ static int inf; /* to make Getc() calls happy */ static BOOLEAN type2; /* true if working with LZW-II format */ static onebyt escape_char; typedef struct { unsigned char chr; int prefix; } Table_ent; static Table_ent Real_tab[BLKSIZ-256]; /* first 256 don't exist */ static Table_ent *Table; static int Mask_tab[16] = { 0x0000, 0x01ff, 0x03ff, 0x03ff, 0x07ff, 0x07ff, 0x07ff, 0x07ff, 0x0fff, 0x0fff, 0x0fff, 0x0fff, 0x0fff, 0x0fff, 0x0fff, 0x0fff }; static int Number[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 }; static onebyt Stack[100]; /* simulated stack; should be <= 64 */ static int out_bytes, stack_ptr, entry, at_bit, at_byte; static onebyt last_byte; /* used in get_code */ /* fake Getc(); easier to make this a macro than to change the code */ #ifdef DEBUG onebyt Getc(foo) int foo; /* this is ignored */ { return (*(ibuf++)); } #else /* if not debugging, use a macro */ # define Getc(foo) *(ibuf++) #endif /* DEBUG */ /* * Stack operations; used by undo_LZW */ #ifdef DEBUG void push(a_byte) unsigned char a_byte; { if (stack_ptr > 100) { printf("\n*** stack_ptr exceeded 100 in push() [%d]\n", stack_ptr); exit (-1); } Stack[stack_ptr++] = a_byte; } #else /* if not debugging, use a macro */ # define push(a_byte) Stack[stack_ptr++] = a_byte #endif /* DEBUG */ #ifdef DEBUG void dump_stack(buffer) unsigned char *buffer; { printf("--- Going to dump stack, stack_ptr = %d, out_bytes = %d\n", stack_ptr, out_bytes); while (stack_ptr > 0) { *(buffer + out_bytes++) = Stack[--stack_ptr]; } } #else /* if not debugging, use a macro */ # define dump_stack(buffer) while (stack_ptr > 0) { \ *( buffer +out_bytes++) = Stack[--stack_ptr];\ } #endif /* DEBUG */ /* * Decipher LZW codes. */ static int get_code(/*Buffer*/) /*unsigned char *Buffer;*/ { register int num_bits, old_bit, last_bit; long value, mask; unsigned char byte1, byte2, byte3; /* get compressed chars... */ #ifdef DEBUG printf("ENT: bit=%d byte=%-4d last_byte=$%.2x ", at_bit, at_byte, last_byte); printf("Entry: %.4x \n", entry); #endif num_bits = ((entry+1) >> 8); /* get hi-byte of entry */ last_bit = at_bit + Number[num_bits] + 8; old_bit = at_bit; #ifdef DEBUG if (at_byte >= BLKSIZ) { fprintf(stderr, "at_byte exceeded BLKSIZ (4096) in get_code()\n"); exit (-1); } #endif if (at_bit == 0) last_byte = Getc(inf); byte1 = last_byte; /* first byte = last one used */ byte2 = Getc(inf); if (last_bit > 16) { /* get 3rd byte if nec. */ byte3 = Getc(inf); last_byte = byte3; } else { byte3 = 0; last_byte = byte2; } value = ((((long)byte3 << 8) + (long)byte2) << 8) + (long)byte1; /* value = (((Buffer[at_byte+2] << 8) + Buffer[at_byte+1]) << 8) + */ /* Buffer[at_byte]; */ mask = (long) Mask_tab[num_bits]; at_byte += (last_bit >> 3); /* new byte */ at_bit = (last_bit & 0x07); #ifdef DEBUG printf("| EX: value=$%.6x mask=$%.4x return=$%.3x\n", value, mask, ((value >> old_bit) & mask)); #endif if (old_bit) return ((value >> old_bit) & mask); else return (value & mask); /* shifting by zero may be undefined */ } /* * Un-LZW a range of bytes * * Reads data with get_code (eventually from packBuffer) and stores the * output in "buffer". */ static void undo_LZW(buffer, length) unsigned char *buffer; /* where to put output */ int length; /* uncompressed length of output */ { register int oldc, incode, finalc, ptr; /* initialize variables */ Table = Real_tab-256; entry = 0x101; /* start at $101 */ at_bit = at_byte = 0; out_bytes = 0; stack_ptr = 0; last_byte = 0; /* init last_byte */ oldc = incode = get_code(/*buffer*/); finalc = (oldc & 0xff); *(buffer + out_bytes++) = (unsigned char) incode; /* main loop */ while (out_bytes < length) { incode = ptr = get_code(/*buffer*/); if (ptr >= entry) { push(finalc); ptr = oldc; } while (ptr > 0xff) { push(Table[ptr].chr); ptr = Table[ptr].prefix; } /* ptr is now < 0x100 */ finalc = ptr; push(finalc); dump_stack(buffer); Table[entry].chr = (finalc & 0xff); /* mask to get unsigned?? byte */ Table[entry].prefix = oldc; entry++; oldc = incode; } } /* * Un-LZW-II a range of bytes (someday!) * * Reads data with get_code (eventually from packBuffer) and stores the * output in "buffer". Has additional code to support LZW-II's table * clears. */ static void undo_LZW_2(buffer, length) unsigned char *buffer; /* where to put output */ int length; /* uncompressed length of output */ { register int oldc, incode, finalc, ptr; /* initialize variables */ Table = Real_tab-256; entry = 0x101; /* start at $101 */ at_bit = at_byte = 0; out_bytes = 0; stack_ptr = 0; last_byte = 0; /* init last_byte */ oldc = incode = get_code(/*buffer*/); finalc = (oldc & 0xff); *(buffer + out_bytes++) = (unsigned char) incode; /* main loop */ while (out_bytes < length) { incode = ptr = get_code(/*buffer*/); if (ptr >= entry) { push(finalc); ptr = oldc; } while (ptr > 0xff) { push(Table[ptr].chr); ptr = Table[ptr].prefix; } /* ptr is now < 0x100 */ finalc = ptr; push(finalc); dump_stack(buffer); Table[entry].chr = (finalc & 0xff); /* mask to get unsigned?? byte */ Table[entry].prefix = oldc; entry++; oldc = incode; } } /* * Second pass... undo the Run Length Encoding. * * Copy data from inbuffer to outbuffer. Keep going until we've got * exactly BLKSIZ bytes. Note that this uses codes of the form * char count * which is different from some other programs. */ static void undo_RLE(inbuffer, outbuffer) unsigned char *inbuffer, *outbuffer; /*int length; /* how many bytes from LZW; just to make sure... */ { register unsigned char c; register int total, count; /* count is RLE reps */ #ifdef DEBUG /*printf("Starting undo_RLE, length = %d\n", length);*/ #endif total = 0; while (total < BLKSIZ) { c = *(inbuffer++); /*length--;*/ if (c == (onebyt) escape_char) { c = *(inbuffer++); /*length--;*/ count = *(inbuffer++); /*length--;*/ total += count +1; /* count of zero -> 1 byte */ while (count-- >= 0) { *(outbuffer++) = c; /*Putc(c, outf);*/ } } else { *(outbuffer++) = c; /*Putc(c, outf);*/ total++; } } if (total != 4096) fprintf(stderr, "internal error: bad undo_RLE\n"); #ifdef DEBUG /* printf("Exiting undo_RLE, length = %d (should be 0), total = %d (4096)\n", length, total);*/ #endif } /* * Main entry point. * * This is among the more hellish things I've written. Uses * a large buffer for efficiency reasons, and unpacks a stream of bytes * (LZW-II improves things a little). * If you find this hard to understand, imagine what it was like to debug. * * Could use some cleaning up, esp argument list... */ void unpak_SHK(srcfd,dstfd,comp_thread_eof,thread_eof,buffer, use_type2, thread_crc) int srcfd, dstfd; fourbyt comp_thread_eof, thread_eof; register onebyt *buffer; BOOLEAN use_type2; /* true if we should expect LZW-II */ twobyt thread_crc; { twobyt CRC, blkCRC; onebyt vol; onebyt *wrbuf; /* points to buffer we're about to write */ short unlen, lzwflag, rleflag, complen; /* should be short */ unsigned int partial, toread, still_in_buf; fourbyt tmp4; /* temporary 4-byte variable */ int cc; static char *procName = "unpak_SHK"; CRC = 0; type2 = use_type2; /* read min(PAKBUFSIZ, comp_thread_eof) bytes into buffer */ if (comp_thread_eof > (fourbyt) PAKBUFSIZ) { toread = (unsigned int) PAKBUFSIZ; comp_thread_eof -= (fourbyt) PAKBUFSIZ; } else { toread = (unsigned int) comp_thread_eof; /* read it all... */ comp_thread_eof = (fourbyt) 0; } /* do initial read */ #ifdef DEBUG1 printf("initial read = %u\n", toread); #endif if ((cc = read(srcfd, buffer, toread)) < toread) { #ifdef DEBUG1 printf("Only read %d bytes\n", cc); #endif Fatal("Bad read during uncompress", procName); } ibuf = buffer; /* set input pointer to start of buffer */ /* get header data */ if (type2) { blkCRC = thread_crc; } else { blkCRC = Getc(inf); blkCRC += (Getc(inf) << 8); } vol = (char) Getc(inf); /* disk volume #; not used here */ escape_char = (char) Getc(inf); /* RLE delimiter */ #ifdef DEBUG1 printf("vol = %d, escape_char = %x\n", vol, escape_char); #endif /* * main loop */ while (thread_eof != (fourbyt) 0) { /* note "unlen" is un-LZWed length (i.e., after RLE) */ if (type2) { unlen = Getc(inf); unlen += (Getc(inf) << 8); lzwflag = (unlen & 0x8000) ? 1 : 0; /* flag is hi bit */ unlen &= 0x1fff; /* strip extra stuff */ rleflag = (unlen != BLKSIZ); if (lzwflag) { /* will the real length bytes please stand up*/ complen = Getc(inf); complen += (Getc(inf) << 8); } } else { unlen = Getc(inf); unlen += (Getc(inf) << 8); lzwflag = Getc(inf); rleflag = (unlen != BLKSIZ); } #ifdef DEBUG1 printf("Length after RLE = %d ($%.4x)\n", unlen, unlen); printf("LZW flag = %d, RLE flag = %d\n", lzwflag, rleflag); if (lzwflag != 0 && lzwflag != 1) { /* this is weird... */ for (lzwflag = -6; lzwflag < 3; lzwflag++) { printf("foo %d: %.2x\n", lzwflag, *(ibuf+lzwflag)); } } if (type2 && lzwflag) { printf("Length after RLE+LZW = %d ($%.4x)\n", complen, complen); } #endif /* If it looks like we're going to run out of room, shift & read /* Mostly a guess; LZW length is less than unlen... This is /* complicated and very prone to errors. /* tmp4 is the number of bytes between the current ptr and the end; /* some (16-bit) compilers yack if it's all one statement.*/ tmp4 = (fourbyt) buffer + (fourbyt) PAKBUFSIZ; tmp4 -= (fourbyt) ibuf; if (tmp4 < (unlen + 6)) { /* 6 = 3/4 byte header + two just in case */ still_in_buf = tmp4; #ifdef DEBUG1 printf("--- unlen = %d, space left = %d bytes\n", unlen, still_in_buf); #endif BCopy((onebyt *) ibuf, (onebyt *) buffer, still_in_buf, FALSE); if (comp_thread_eof != (fourbyt) 0) { /* no read, just shift */ if (comp_thread_eof > ((fourbyt) PAKBUFSIZ - still_in_buf)){ toread = (unsigned int) PAKBUFSIZ - still_in_buf; comp_thread_eof -= (fourbyt) PAKBUFSIZ - still_in_buf; } else { toread = (unsigned int) comp_thread_eof; comp_thread_eof = (fourbyt) 0; } #ifdef DEBUG1 printf("--- reading another %u bytes\n", toread); #endif if (read(srcfd, buffer+still_in_buf, toread) < toread) Fatal("Unable to read [middle]", procName); if (verbose) Spin(); } ibuf = buffer; } /* how much of the buffered data do we really need? */ if (thread_eof > (fourbyt) BLKSIZ) { partial = (unsigned int) BLKSIZ; thread_eof -= (fourbyt) BLKSIZ; } else { partial = (unsigned int) thread_eof; /* last block of file */ thread_eof = (fourbyt) 0; } /* * undo_LZW reads from ibuf (using Getc()) and writes to lbuf * undo_LZW_2 does what undo_LZW does, but for LZW-II. * undo_RLE reads from where you tell it and writes to rbuf * * This is really insane... */ if (lzwflag && rleflag) { if (type2) undo_LZW_2(lbuf, unlen); /* from ibuf -> lbuf */ else undo_LZW(lbuf, unlen); /* from ibuf -> lbuf */ undo_RLE(lbuf, rbuf); /* from lbuf -> rbuf */ wrbuf = rbuf; /* write rbuf */ CRC = CalcCRC(CRC, (onebyt *) rbuf, BLKSIZ); /* always 4K bytes */ } else if (lzwflag && !rleflag) { if (type2) undo_LZW_2(lbuf, unlen); /* from ibuf -> lbuf */ else undo_LZW(lbuf, unlen); /* from ibuf -> lbuf */ wrbuf = lbuf; /* write lbuf */ CRC = CalcCRC(CRC, (onebyt *) lbuf, BLKSIZ); } else if (!lzwflag && rleflag) { undo_RLE(ibuf, rbuf); /* from ibuf -> rbuf */ wrbuf = rbuf; /* write rbuf */ CRC = CalcCRC(CRC, (onebyt *) rbuf, BLKSIZ); ibuf += unlen; /* have to skip over RLE-only data */ /* normally ibuf is advanced by Getc() calls */ } else { wrbuf = ibuf; /* write ibuf */ CRC = CalcCRC(CRC, (onebyt *) ibuf, BLKSIZ); ibuf += partial; /* skip over uncompressed data */ /* normally ibuf is advanced by Getc() calls */ } #ifdef DEBUG1 printf("Writing %d bytes.\n", partial); #endif if (crlf(dstfd, wrbuf, partial) < partial) /* write wrbuf */ Fatal("Bad write", procName); } if (CRC != blkCRC) { fprintf(stderr, "WARNING: CRC does not match..."); if (verbose) fprintf(stderr, "\n"); else fprintf(stderr, "extract with V suboption to see filenames.\n"); } }