home *** CD-ROM | disk | FTP | other *** search
- From: uucpa@gamma.UUCP (UNIX-to-UNIX Copy)
- Newsgroups: comp.sources.misc
- Subject: v02i087: "Stripped" 16-bit uncompress
- Message-ID: <8804040317.AA15327@gamma.UUCP>
- Date: 4 Apr 88 03:17:49 GMT
- Approved: allbery@ncoast.UUCP
-
- comp.sources.misc: Volume 2, Issue 87
- Submitted-By: "UNIX-to-UNIX Copy" <uucpa@gamma.UUCP>
- Archive-Name: ucomp16
-
- The following is a stripped uncompress derived by rote from
- compress 3.x. I did not keep the proper headers for this file
- to give proper credit to the authors since what i was trying to do
- was to get the 16 bit decompression on a machine that simply would
- not allow the resultant executable size.
-
- MY APLOLOGIES AHEAD OF TIME!!!!!!!!
-
- this conversion should be modified to include the original
- notices and things. and is only published to fill the gap
- on the smaller machines that can't handle the regular compress
- software.
-
- sorry if this Tee 's anyone off.
-
- ron tribble
- ....mibte!ccd700!ron
-
- echo x - ucomp16.c
- sed 's/^X//' >ucomp16.c <<'*-*-END-of-ucomp16.c-*-*'
- X#define PBITS 16
- X#define BITS PBITS
- X
- Xunsigned char magic_header[] = {
- X "\037\235" }; /* 1F 9D */
- X
- X/* Defines for third byte of header */
- X#define BIT_MASK 0x1f
- X#define BLOCK_MASK 0x80
- X/* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
- Xa fourth header byte (for expansion).
- X*/
- X#define INIT_BITS 9 /* initial number of bits/code */
- X
- X#include <stdio.h>
- X
- Xint n_bits; /* number of bits/code */
- Xint maxbits = BITS; /* user settable max # bits/code */
- Xlong int maxcode; /* maximum code, given n_bits */
- Xlong int maxmaxcode = 1 << BITS; /* should NEVER generate this code */
- X# define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
- X
- X/*
- X* One code could conceivably represent (1<<BITS) characters, but
- X* to get a code of length N requires an input string of at least
- X* N*(N-1)/2 characters. With 5000 chars in the stack, an input
- X* file would have to contain a 25Mb string of a single character.
- X* This seems unlikely.
- X*/
- X# define MAXSTACK 8000 /* size of output stack */
- X
- Xunsigned short tab_prefix [69001];
- Xunsigned char tab_suffix[1<<BITS]; /* last char in this entry */
- X
- Xlong int free_ent = 0; /* first unused entry */
- Xint exit_stat = 0;
- X
- Xlong int getcode();
- X
- X/*
- X* block compression parameters -- after all codes are used up,
- X* and compression rate changes, start over.
- X*/
- Xint block_compress = BLOCK_MASK;
- Xint clear_flg = 0;
- X/*
- X* the next two codes should not be changed lightly, as they must not
- X* lie within the contiguous general code space.
- X*/
- X#define FIRST 257 /* first free entry */
- X#define CLEAR 256 /* table clear output code */
- X
- Xmain()
- X{
- X if(maxbits < INIT_BITS) maxbits = INIT_BITS;
- X if (maxbits > BITS) maxbits = BITS;
- X maxmaxcode = 1 << maxbits;
- X
- X exit_stat = 0;
- X /* Check the magic number */
- X if ((getchar() != (magic_header[0] & 0xFF))
- X || (getchar() != (magic_header[1] & 0xFF))) {
- X fprintf(stderr,"not in compressed format\n");
- X exit(1);
- X }
- X maxbits = getchar(); /* set -b from file */
- X block_compress = maxbits & BLOCK_MASK;
- X maxbits &= BIT_MASK;
- X maxmaxcode = 1 << maxbits;
- X if(maxbits > BITS) {
- X fprintf(stderr,
- X "compressed with %d bits, can only handle %d bits\n",
- X maxbits, BITS);
- X exit(1);
- X }
- X decompress();
- X exit(exit_stat);
- X}
- Xunsigned char rmask[9] = {
- X 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
- Xdecompress() {
- X register int stack_top = MAXSTACK;
- X register long int code, oldcode, incode;
- X register int finchar;
- X char stack[MAXSTACK];
- X
- X /*
- X* As above, initialize the first 256 entries in the table.
- X*/
- X maxcode = MAXCODE(n_bits = INIT_BITS);
- X for ( code = 255; code >= 0; code-- ) {
- X tab_prefix[code] = 0;
- X tab_suffix[code] = (unsigned char)code;
- X }
- X free_ent = ((block_compress) ? FIRST : 256 );
- X
- X finchar = oldcode = getcode();
- X putchar( (char)finchar ); /* first code must be 8 bits = char */
- X
- X while ( (code = getcode()) != -1 ) {
- X
- X if ( (code == CLEAR) && block_compress ) {
- X for ( code = 255; code > 0; code -= 4 ) {
- X tab_prefix [code-3] = 0;
- X tab_prefix [code-2] = 0;
- X tab_prefix [code-1] = 0;
- X tab_prefix [code] = 0;
- X }
- X clear_flg = 1;
- X free_ent = FIRST - 1;
- X if ( (code = getcode ()) == -1 ) /* O, untimely death! */
- X break;
- X }
- X incode = code;
- X /*
- X* Special case for KwKwK string.
- X*/
- X if ( code >= free_ent ) {
- X stack[--stack_top] = finchar;
- X code = oldcode;
- X }
- X
- X /*
- X* Generate output characters in reverse order
- X*/
- X while ( code >= 256 ) {
- X stack[--stack_top] = tab_suffix[code];
- X code = tab_prefix[code];
- X }
- X stack[--stack_top] = finchar = tab_suffix[code];
- X
- X /*
- X* And put them out in forward order
- X*/
- X for ( ; stack_top < MAXSTACK; stack_top++ )
- X putchar(stack[stack_top]);
- X if (ferror(stdout))
- X writeerr ( );
- X stack_top = MAXSTACK;
- X
- X /*
- X* Generate the new entry.
- X*/
- X if ( (code=free_ent) < maxmaxcode ) {
- X tab_prefix[code] = (unsigned short)oldcode;
- X tab_suffix[code] = finchar;
- X free_ent = code+1;
- X }
- X /*
- X* Remember previous code.
- X*/
- X oldcode = incode;
- X }
- X fflush( stdout );
- X if(ferror(stdout))
- X writeerr();
- X}
- X
- X
- X/*****************************************************************
- X* TAG( getcode )
- X*
- X* Read one code from the standard input. If EOF, return -1.
- X* Inputs:
- X* stdin
- X* Outputs:
- X* code or -1 is returned.
- X*/
- X
- Xlong int
- Xgetcode() {
- X /*
- X* On the VAX, it is important to have the register declarations
- X* in exactly the order given, or the asm will break.
- X*/
- X register long int code;
- X static int offset = 0, size = 0;
- X static unsigned char buf[BITS];
- X register int r_off, bits;
- X register unsigned char *bp = buf;
- X
- X if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
- X /*
- X* If the next entry will be too big for the current code
- X* size, then we must increase the size. This implies reading
- X* a new buffer full, too.
- X*/
- X if ( free_ent > maxcode ) {
- X n_bits++;
- X if ( n_bits == maxbits )
- X maxcode = maxmaxcode; /* won't get any bigger now */
- X else
- X maxcode = MAXCODE(n_bits);
- X }
- X if ( clear_flg > 0) {
- X maxcode = MAXCODE (n_bits = INIT_BITS);
- X clear_flg = 0;
- X }
- X size = fread( buf, 1, n_bits, stdin );
- X if ( size <= 0 )
- X return -1; /* end of file */
- X offset = 0;
- X /* Round size down to integral number of codes */
- X size = (size << 3) - (n_bits - 1);
- X }
- X r_off = offset;
- X bits = n_bits;
- X /*
- X* Get to the first byte.
- X*/
- X bp += (r_off >> 3);
- X r_off &= 7;
- X /* Get first part (low order bits) */
- X code = (*bp++ >> r_off);
- X bits -= (8 - r_off);
- X r_off = 8 - r_off; /* now, offset into code word */
- X /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- X if ( bits >= 8 ) {
- X code |= *bp++ << r_off;
- X r_off += 8;
- X bits -= 8;
- X }
- X /* high order bits. */
- X code |= (*bp & rmask[bits]) << r_off;
- X offset += n_bits;
- X
- X return code;
- X}
- X/*****************************************************************
- X* TAG( writeerr )
- X*
- X* Exits with a message. We only check for write errors often enough
- X* to avoid a lot of "file system full" messages, not on every write.
- X* ferror() check after fflush will catch any others (I trust).
- X*
- X*/
- X
- Xwriteerr()
- X{
- X exit ( 1 );
- X}
- *-*-END-of-ucomp16.c-*-*
- exit
-