/*--------------------------------------------------------------------- LZin modules written by L. Granroth 07-19-90 to provide binary stream input from compressed files using on-the-fly LZW decompression. The input files must be compatible with standard Unix compress using the 12-bit option. The entry points are designed to be callable from VAX/VMS and MS FORTRAN. ---------------------------------------------------------------------*/ /* Get the usual include files */ #include /* Define some useful constants */ #define BITS 12 #define HSIZE 5003 /* 80% occupancy */ #define BIT_MASK 0x1F #define INIT_BITS 9 /* initial number of bits/code */ #define BLOCK_MASK 0x80 #define FIRST 257 /* first free entry */ #define CLEAR 256 /* table clear output code */ /* Define some useful macros */ #define MAXCODE(n_bits) ((1 << (n_bits)) - 1) #define htabof(i) htab[i] #define codetabof(i) codetab[i] #define tab_prefixof(i) codetabof (i) #define tab_suffixof(i) ((char_type *) (htab))[i] #define de_stack ((char_type *) &tab_suffixof (1 << BITS)) /* Set up our typedefs */ typedef short int code_int; typedef short int count_int; typedef unsigned char char_type; /* Declare the global variables */ static char_type rmask[9] = { (char_type) 0x00, (char_type) 0x01, (char_type) 0x03, (char_type) 0x07, (char_type) 0x0F, (char_type) 0x1F, (char_type) 0x3F, (char_type) 0x7F, (char_type) 0xFF}; static int n_bits; /* number of bits/code */ static int maxbits = BITS; /* user settable max # bits/code */ static code_int maxcode; /* maximum code, given n_bits */ static code_int maxmaxcode = 1 << BITS; /* should NEVER generate this code */ static count_int htab [HSIZE]; static unsigned short codetab [HSIZE]; static code_int free_ent = 0; /* first unused entry */ extern FILE *datunit; static int initialize = 0; /* Define our function prototypes */ code_int getcode(void); /* * Block compression parameters -- after all codes are used up, * and compression rate changes, start over. * */ static int block_compress = BLOCK_MASK; static int clear_flg = 0; /*---------------------------------------------------------------------*/ int LZOPEN (fname) const char *fname; { /* Open input file */ if (datunit) fclose (datunit); if (!(datunit = fopen (fname, "rb"))) return (0); /* Check the magic number */ if ((fgetc (datunit) != 0x1F) || (fgetc (datunit) != 0x9D)) { fprintf (stderr, "%s: not in compressed format\n", fname); return (0); } maxbits = fgetc (datunit); /* set bits from file */ block_compress = maxbits & BLOCK_MASK; maxbits &= BIT_MASK; maxmaxcode = 1 << maxbits; if (maxbits > BITS) { fprintf (stderr, "%s: compressed with %d bits, can only handle %d bits\n", fname, maxbits, BITS); return (0); } initialize = 1; return (1); } /*---------------------------------------------------------------------*/ int LZREAD (bufp, request) char_type *bufp; const int *request; { static char_type *stackp; static code_int code, oldcode, incode, finchar; int count; count = 0; if (ferror (datunit)) perror ("LZread"); if (initialize) { initialize = 0; /* 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(); stackp = de_stack; if (oldcode == -1) return (0); /* EOF already??? */ *bufp++ = (char_type) oldcode; count = 1; } /* if initialize */ while (stackp > de_stack) { *bufp++ = (char_type) *--stackp; if (++count >= *request) return (count); } while ((code = getcode ( )) > -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 ( )) == -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 */ while (code >= 256) { *stackp++ = tab_suffixof (code); code = tab_prefixof (code); } *stackp++ = finchar = tab_suffixof (code); /* 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; /* return characters in forward order */ while (stackp > de_stack) { *bufp++ = (char_type) *--stackp; if (++count >= *request) return (count); } } return (count); } /* * g e t c o d e * * Read one code from the standard input. If EOF, return -1. * */ code_int getcode ( ) { 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 = fread (buf, 1, n_bits, datunit); /* printf ("fread %d\n", size); DEBUG */ if (size <= 0) return (-1); /* End of file */ offset = 0; /* Round size down to an integral number of codes */ size = (size << 3) - (n_bits - 1); } r_off = offset; bits = n_bits; /* Get to the first byte */ bp += (r_off >> 3); r_off &= 7; /* Get first part (low order bits) */ code = (*bp++ >> r_off); 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) { code |= *bp++ << r_off; r_off += 8; bits -= 8; } /* Handle the high order bits */ code |= (*bp & rmask[bits]) << r_off; offset += n_bits; return (code); } /*---------------------------------------------------------------------*/ int LZCLOSE ( ) { return (fclose (datunit)); }