#if 0 static char sccsid[]= "@(#)compress.c @(#)compress.c 5.9 (Berkeley) 5/11/86"; #endif /* * Compress - data compression program. This is an EXTREMELY HACKED version * of the old compress program, solely to uncompress a -b12 stream. It runs * in standalone mode on PDP-11s, and it is typically used to uncompress and * fill a disk with an incoming compressed disk image. * * There's a whole lot of cruft I haven't bothered to take out, but it's * mostly cpp stuff which doesn't make it into the binary. * * Warren Toomey wkt@cs.adfa.oz.au 24th March 1998 */ #define min(a,b) ((a>b) ? b : a) #ifndef pdp11 #define pdp11 #endif /* * machine variants which require cc -Dmachine: pdp11, z8000, pcxt */ /* * Set USERMEM to the maximum amount of physical user memory available * in bytes. USERMEM is used to determine the maximum BITS that can be used * for compression. * * SACREDMEM is the amount of physical memory saved for others; compress * will hog the rest. */ #ifndef SACREDMEM #define SACREDMEM 0 #endif #ifndef USERMEM #define USERMEM 450000 /* default user memory */ #endif #ifdef interdata /* (Perkin-Elmer) */ #define SIGNED_COMPARE_SLOW /* signed compare is slower than unsigned */ #endif #ifdef pdp11 #define BITS 12 /* max bits/code for 16-bit machine */ #define NO_UCHAR /* also if "unsigned char" functions as signed char */ #undef USERMEM #endif /* pdp11 */ /* don't forget to compile with -i */ #ifdef z8000 #define BITS 12 #undef vax /* weird preprocessor */ #undef USERMEM #endif /* z8000 */ #ifdef pcxt #define BITS 12 #undef USERMEM #endif /* pcxt */ #ifdef USERMEM #if USERMEM >= (433484+SACREDMEM) #define PBITS 16 #else #if USERMEM >= (229600+SACREDMEM) #define PBITS 15 #else #if USERMEM >= (127536+SACREDMEM) #define PBITS 14 #else #if USERMEM >= (73464+SACREDMEM) #define PBITS 13 #else #define PBITS 12 #endif #endif #endif #endif #undef USERMEM #endif /* USERMEM */ #ifdef PBITS /* Preferred BITS for this memory size */ #ifndef BITS #define BITS PBITS #endif /* BITS */ #endif /* PBITS */ #if BITS == 16 #define HSIZE 69001 /* 95% occupancy */ #endif #if BITS == 15 #define HSIZE 35023 /* 94% occupancy */ #endif #if BITS == 14 #define HSIZE 18013 /* 91% occupancy */ #endif #if BITS == 13 #define HSIZE 9001 /* 91% occupancy */ #endif #if BITS <= 12 #define HSIZE 5003 /* 80% occupancy */ #endif #ifdef M_XENIX /* Stupid compiler can't handle arrays with */ #if BITS == 16 /* more than 65535 bytes - so we fake it */ #define XENIX_16 #else #if BITS > 13 /* Code only handles BITS = 12, 13, or 16 */ #define BITS 13 #endif #endif #endif /* * a code_int must be able to hold 2**BITS values of type int, and also -1 */ #if BITS > 15 typedef long int code_int; #else typedef int code_int; #endif #ifdef SIGNED_COMPARE_SLOW typedef unsigned long int count_int; typedef unsigned short int count_short; #else typedef long int count_int; #endif #ifdef NO_UCHAR typedef char char_type; #else typedef unsigned char char_type; #endif /* UCHAR */ char_type magic_header[] = {"\037\235"}; /* 1F 9D */ /* Defines for third byte of header */ #define BIT_MASK 0x1f #define BLOCK_MASK 0x80 /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is * a fourth header byte (for expansion). */ #define INIT_BITS 9 /* initial number of bits/code */ /* * compress.c - File compression ala IEEE Computer, June 1984. * * Authors: Spencer W. Thomas (decvax!utah-cs!thomas) * Jim McKie (decvax!mcvax!jim) * Steve Davies (decvax!vax135!petsd!peora!srd) * Ken Turkowski (decvax!decwrl!turtlevax!ken) * James A. Woods (decvax!ihnp4!ames!jaw) * Joe Orost (decvax!vax135!petsd!joe) * * Revision 4.0 85/07/30 12:50:00 joe * Removed ferror() calls in output routine on every output except first. * Prepared for release to the world. * */ #include #include #include #include #include int n_bits; /* number of bits/code */ int maxbits = BITS; /* user settable max # bits/code */ code_int maxcode; /* maximum code, given n_bits */ code_int maxmaxcode = 1 << BITS;/* should NEVER generate this code */ #ifdef COMPATIBLE /* But wrong! */ #define MAXCODE(n_bits) (1 << (n_bits) - 1) #else #define MAXCODE(n_bits) ((1 << (n_bits)) - 1) #endif /* COMPATIBLE */ #ifdef XENIX_16 count_int htab0[8192]; count_int htab1[8192]; count_int htab2[8192]; count_int htab3[8192]; count_int htab4[8192]; count_int htab5[8192]; count_int htab6[8192]; count_int htab7[8192]; count_int htab8[HSIZE - 65536]; count_int *htab[9] = { htab0, htab1, htab2, htab3, htab4, htab5, htab6, htab7, htab8}; #define htabof(i) (htab[(i) >> 13][(i) & 0x1fff]) unsigned short code0tab[16384]; unsigned short code1tab[16384]; unsigned short code2tab[16384]; unsigned short code3tab[16384]; unsigned short code4tab[16384]; unsigned short *codetab[5] = { code0tab, code1tab, code2tab, code3tab, code4tab}; #define codetabof(i) (codetab[(i) >> 14][(i) & 0x3fff]) #else /* Normal machine */ #ifdef sel /* gould base register braindamage */ /*NOBASE*/ count_int htab[HSIZE]; unsigned short codetab[HSIZE]; /*NOBASE*/ #else count_int htab[HSIZE]; unsigned short codetab[HSIZE]; #endif /* sel */ #define htabof(i) htab[i] #define codetabof(i) codetab[i] #endif /* XENIX_16 */ code_int hsize = HSIZE; /* for dynamic table sizing */ count_int fsize; /* * To save much memory, we overlay the table used by compress() with those * used by decompress(). The tab_prefix table is the same size and type * as the codetab. The tab_suffix table needs 2**BITS characters. We * get this from the beginning of htab. The output stack uses the rest * of htab, and contains characters. There is plenty of room for any * possible stack (stack used to be 8000 characters). */ #define tab_prefixof(i) codetabof(i) #ifdef XENIX_16 #define tab_suffixof(i) ((char_type *)htab[(i)>>15])[(i) & 0x7fff] #define de_stack ((char_type *)(htab2)) #else /* Normal machine */ #define tab_suffixof(i) ((char_type *)(htab))[i] #define de_stack ((char_type *)&tab_suffixof(1< BITS) { printf("input compressed with %d bits, can only handle %d bits\n", maxbits, BITS); exit(1); } hsize = HSIZE; decompress(i, j); printf("Image written, looping indefintely\n"); while (1) ; } /* * Decompress stdin to stdout. This routine adapts to the codes in the * file building the "string" table on-the-fly; requiring no table to * be stored in the compressed file. The tables used herein are shared * with those of the compress() routine. See the definitions above. */ #define BSIZE 512 char buf[BSIZE]; int decompress(in, out) int in, out; { register char_type *stackp; register int finchar; register code_int code, oldcode, incode; int cnt = 0; /* * As above, initialize the first 256 entries in the table. */ maxcode = MAXCODE(n_bits = INIT_BITS); for (code = 255; code >= 0; code--) { tab_prefixof(code) = 0; tab_suffixof(code) = (char_type) code; } free_ent = ((block_compress) ? FIRST : 256); finchar = oldcode = getcode(in); if (oldcode == -1) /* EOF already? */ return (0); /* Get out of here */ buf[cnt++] = (char) finchar; /* first code must be 8 bits = char */ if (cnt == BSIZE) { write(out, buf, BSIZE); cnt = 0; } stackp = de_stack; while ((code = getcode(in)) > -1) { if ((code == CLEAR) && block_compress) { for (code = 255; code >= 0; code--) tab_prefixof(code) = 0; clear_flg = 1; free_ent = FIRST - 1; if ((code = getcode(in)) == -1) /* O, untimely death! */ break; } incode = code; /* * Special case for KwKwK string. */ if (code >= free_ent) { *stackp++ = finchar; code = oldcode; } /* * Generate output characters in reverse order */ #ifdef SIGNED_COMPARE_SLOW while (((unsigned long) code) >= ((unsigned long) 256)) { #else while (code >= 256) { #endif *stackp++ = tab_suffixof(code); code = tab_prefixof(code); } *stackp++ = finchar = tab_suffixof(code); /* * And put them out in forward order */ do { buf[cnt++] = *--stackp; if (cnt == BSIZE) { write(out, buf, BSIZE); cnt = 0; } } while (stackp > de_stack); /* * Generate the new entry. */ if ((code = free_ent) < maxmaxcode) { tab_prefixof(code) = (unsigned short) oldcode; tab_suffixof(code) = finchar; free_ent = code + 1; } /* * Remember previous code. */ oldcode = incode; } if (cnt) write(out, buf, BSIZE); return (0); } char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; /***************************************************************** * TAG( getcode ) * * Read one code from the standard input. If EOF, return -1. * Inputs: * stdin * Outputs: * code or -1 is returned. */ code_int getcode(in) int in; { /* * On the VAX, it is important to have the register declarations in exactly * the order given, or the asm will break. */ register code_int code; static int offset = 0, size = 0; static char_type buf[BITS]; register int r_off, bits; register char_type *bp = buf; if (clear_flg > 0 || offset >= size || free_ent > maxcode) { /* * If the next entry will be too big for the current code size, then we * must increase the size. This implies reading a new buffer full, too. */ if (free_ent > maxcode) { n_bits++; if (n_bits == maxbits) maxcode = maxmaxcode; /* won't get any bigger now */ else maxcode = MAXCODE(n_bits); } if (clear_flg > 0) { maxcode = MAXCODE(n_bits = INIT_BITS); clear_flg = 0; } size = myread(in, buf, n_bits); if (size <= 0) return -1; /* end of file */ offset = 0; /* Round size down to integral number of codes */ size = (size << 3) - (n_bits - 1); } r_off = offset; bits = n_bits; #ifdef vax asm("extzv r10,r9,(r8),r11"); #else /* not a vax */ /* * Get to the first byte. */ bp += (r_off >> 3); r_off &= 7; /* Get first part (low order bits) */ #ifdef NO_UCHAR code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff; #else code = (*bp++ >> r_off); #endif /* NO_UCHAR */ bits -= (8 - r_off); r_off = 8 - r_off; /* now, offset into code word */ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ if (bits >= 8) { #ifdef NO_UCHAR code |= (*bp++ & 0xff) << r_off; #else code |= *bp++ << r_off; #endif /* NO_UCHAR */ r_off += 8; bits -= 8; } /* high order bits. */ code |= (*bp & rmask[bits]) << r_off; #endif /* vax */ offset += n_bits; return code; } static char mybuf[512]; static int mycnt = 512; /* Fudge a read of < 512 bytes */ myread(fdesc, buf, count) int fdesc; char *buf; int count; { int j, i = 0; while (count) { if (mycnt == 512) { j= read(fdesc, mybuf, 512); if (j==0) return(-1); mycnt = 0; } while (count && (mycnt != 512)) { *buf++ = mybuf[mycnt++]; i++; count--; } } return (i); }