|
|
1.1 root 1: /* unlzw.c -- decompress files in LZW format.
2: * The code in this file is directly derived from the public domain 'compress'
3: * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
4: * Ken Turkowski, Dave Mack and Peter Jannesen.
5: *
6: * This is a temporary version which will be rewritten in some future version
7: * to accomodate in-memory decompression.
8: */
9:
10: #ifndef lint
11: static char rcsid[] = "$Id: unlzw.c,v 0.11 1993/02/24 18:23:13 jloup Exp $";
12: #endif
13:
14: #include "tailor.h"
15: #include "gzip.h"
16: #include "lzw.h"
17:
18: #include <stdio.h>
19:
20: #ifdef HAVE_UNISTD_H
21: # include <sys/types.h>
22: # include <unistd.h>
23: #endif
24:
25: typedef unsigned char char_type;
26: typedef long code_int;
27: typedef unsigned long count_int;
28: typedef unsigned short count_short;
29: typedef unsigned long cmp_code_int;
30:
31: #define MAXCODE(n) (1L << (n))
32:
33: #ifndef REGISTERS
34: # define REGISTERS 2
35: #endif
36: #define REG1
37: #define REG2
38: #define REG3
39: #define REG4
40: #define REG5
41: #define REG6
42: #define REG7
43: #define REG8
44: #define REG9
45: #define REG10
46: #define REG11
47: #define REG12
48: #define REG13
49: #define REG14
50: #define REG15
51: #define REG16
52: #if REGISTERS >= 1
53: # undef REG1
54: # define REG1 register
55: #endif
56: #if REGISTERS >= 2
57: # undef REG2
58: # define REG2 register
59: #endif
60: #if REGISTERS >= 3
61: # undef REG3
62: # define REG3 register
63: #endif
64: #if REGISTERS >= 4
65: # undef REG4
66: # define REG4 register
67: #endif
68: #if REGISTERS >= 5
69: # undef REG5
70: # define REG5 register
71: #endif
72: #if REGISTERS >= 6
73: # undef REG6
74: # define REG6 register
75: #endif
76: #if REGISTERS >= 7
77: # undef REG7
78: # define REG7 register
79: #endif
80: #if REGISTERS >= 8
81: # undef REG8
82: # define REG8 register
83: #endif
84: #if REGISTERS >= 9
85: # undef REG9
86: # define REG9 register
87: #endif
88: #if REGISTERS >= 10
89: # undef REG10
90: # define REG10 register
91: #endif
92: #if REGISTERS >= 11
93: # undef REG11
94: # define REG11 register
95: #endif
96: #if REGISTERS >= 12
97: # undef REG12
98: # define REG12 register
99: #endif
100: #if REGISTERS >= 13
101: # undef REG13
102: # define REG13 register
103: #endif
104: #if REGISTERS >= 14
105: # undef REG14
106: # define REG14 register
107: #endif
108: #if REGISTERS >= 15
109: # undef REG15
110: # define REG15 register
111: #endif
112: #if REGISTERS >= 16
113: # undef REG16
114: # define REG16 register
115: #endif
116:
117: #ifndef BYTEORDER
118: # define BYTEORDER 0000
119: #endif
120:
121: #ifndef NOALLIGN
122: # define NOALLIGN 0
123: #endif
124:
125:
126: union bytes {
127: long word;
128: struct {
129: #if BYTEORDER == 4321
130: char_type b1;
131: char_type b2;
132: char_type b3;
133: char_type b4;
134: #else
135: #if BYTEORDER == 1234
136: char_type b4;
137: char_type b3;
138: char_type b2;
139: char_type b1;
140: #else
141: # undef BYTEORDER
142: int dummy;
143: #endif
144: #endif
145: } bytes;
146: };
147:
148: #if BYTEORDER == 4321 && NOALLIGN == 1
149: # define input(b,o,c,n,m){ \
150: (c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \
151: (o) += (n); \
152: }
153: #else
154: # define input(b,o,c,n,m){ \
155: REG1 char_type *p = &(b)[(o)>>3]; \
156: (c) = ((((long)(p[0]))|((long)(p[1])<<8)| \
157: ((long)(p[2])<<16))>>((o)&0x7))&(m); \
158: (o) += (n); \
159: }
160: #endif
161:
162: #ifndef MAXSEG_64K
163: /* DECLARE(ush, tab_prefix, (1<<BITS)); -- prefix code */
164: # define tab_prefixof(i) tab_prefix[i]
165: # define clear_tab_prefixof() memzero(tab_prefix, 256);
166: #else
167: /* DECLARE(ush, tab_prefix0, (1<<(BITS-1)); -- prefix for even codes */
168: /* DECLARE(ush, tab_prefix1, (1<<(BITS-1)); -- prefix for odd codes */
169: ush *tab_prefix[2];
170: # define tab_prefixof(i) tab_prefix[(i)&1][(i)>>1]
171: # define clear_tab_prefixof() \
172: memzero(tab_prefix0, 128), \
173: memzero(tab_prefix1, 128);
174: #endif
175: #define de_stack ((char_type *)(&d_buf[DIST_BUFSIZE-1]))
176: #define tab_suffixof(i) tab_suffix[i]
177:
178: int block_mode = BLOCK_MODE; /* block compress mode -C compatible with 2.0 */
179:
180: /* ============================================================================
181: * Decompress in to out. This routine adapts to the codes in the
182: * file building the "string" table on-the-fly; requiring no table to
183: * be stored in the compressed file.
184: * IN assertions: the buffer inbuf contains already the beginning of
185: * the compressed data, from offsets iptr to insize-1 included.
186: * The magic header has already been checked and skipped.
187: * bytes_in and bytes_out have been initialized.
188: */
189: void unlzw(in, out)
190: int in, out; /* input and output file descriptors */
191: {
192: REG2 char_type *stackp;
193: REG3 code_int code;
194: REG4 int finchar;
195: REG5 code_int oldcode;
196: REG6 code_int incode;
197: REG7 long inbits;
198: REG8 long posbits;
199: REG9 int outpos;
200: /* REG10 int insize; (global) */
201: REG11 unsigned bitmask;
202: REG12 code_int free_ent;
203: REG13 code_int maxcode;
204: REG14 code_int maxmaxcode;
205: REG15 int n_bits;
206: REG16 int rsize;
207:
208: #ifdef MAXSEG_64K
209: tab_prefix[0] = tab_prefix0;
210: tab_prefix[1] = tab_prefix1;
211: #endif
212: maxbits = get_byte();
213: block_mode = maxbits & BLOCK_MODE;
214: if ((maxbits & LZW_RESERVED) != 0) {
215: WARN((stderr, "%s: warning, unknown flags 0x%x\n",
216: ifname, maxbits & LZW_RESERVED));
217: }
218: maxbits &= BIT_MASK;
219: maxmaxcode = MAXCODE(maxbits);
220:
221: if (maxbits > BITS) {
222: fprintf(stderr,
223: "%s: compressed with %d bits, can only handle %d bits\n",
224: ifname, maxbits, BITS);
225: exit_code = ERROR;
226: return;
227: }
228: rsize = insize;
229: maxcode = MAXCODE(n_bits = INIT_BITS)-1;
230: bitmask = (1<<n_bits)-1;
231: oldcode = -1;
232: finchar = 0;
233: outpos = 0;
234: posbits = inptr<<3;
235:
236: free_ent = ((block_mode) ? FIRST : 256);
237:
238: clear_tab_prefixof(); /* Initialize the first 256 entries in the table. */
239:
240: for (code = 255 ; code >= 0 ; --code) {
241: tab_suffixof(code) = (char_type)code;
242: }
243: do {
244: REG1 int i;
245: int e;
246: int o;
247:
248: resetbuf:
249: e = insize-(o = (posbits>>3));
250:
251: for (i = 0 ; i < e ; ++i) {
252: inbuf[i] = inbuf[i+o];
253: }
254: insize = e;
255: posbits = 0;
256:
257: if (insize < INBUF_EXTRA) {
258: if ((rsize = read(in, inbuf+insize, INBUFSIZ)) == EOF) {
259: read_error();
260: }
261: insize += rsize;
262: }
263: inbits = ((rsize != 0) ? ((long)insize - insize%n_bits)<<3 :
264: ((long)insize<<3)-(n_bits-1));
265:
266: while (inbits > posbits) {
267: if (free_ent > maxcode) {
268: posbits = ((posbits-1) +
269: ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
270: ++n_bits;
271: if (n_bits == maxbits) {
272: maxcode = maxmaxcode;
273: } else {
274: maxcode = MAXCODE(n_bits)-1;
275: }
276: bitmask = (1<<n_bits)-1;
277: goto resetbuf;
278: }
279: input(inbuf,posbits,code,n_bits,bitmask);
280:
281: if (oldcode == -1) {
282: outbuf[outpos++] = (char_type)(finchar = (int)(oldcode=code));
283: continue;
284: }
285: if (code == CLEAR && block_mode) {
286: clear_tab_prefixof();
287: free_ent = FIRST - 1;
288: posbits = ((posbits-1) +
289: ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
290: maxcode = MAXCODE(n_bits = INIT_BITS)-1;
291: bitmask = (1<<n_bits)-1;
292: goto resetbuf;
293: }
294: incode = code;
295: stackp = de_stack;
296:
297: if (code >= free_ent) { /* Special case for KwKwK string. */
298: if (code > free_ent) {
299:
300: REG1 char_type *p;
301:
302: posbits -= n_bits;
303: p = &inbuf[posbits>>3];
304:
305: fprintf(stderr,
306: "code:%ld free_ent:%ld n_bits:%d insize:%u\n",
307: code, free_ent, n_bits, insize);
308: fprintf(stderr,
309: "posbits:%ld inbuf:%02X %02X %02X %02X %02X\n",
310: posbits, p[-1],p[0],p[1],p[2],p[3]);
311: if (!test && outpos > 0
312: && write(out, outbuf, outpos) != outpos) {
313: write_error();
314: }
315: error("Corrupt input. Use zcat to recover some data.");
316: }
317: *--stackp = (char_type)finchar;
318: code = oldcode;
319: }
320:
321: while ((cmp_code_int)code >= (cmp_code_int)256) {
322: /* Generate output characters in reverse order */
323: *--stackp = tab_suffixof(code);
324: code = tab_prefixof(code);
325: }
326: *--stackp = (char_type)(finchar = tab_suffixof(code));
327:
328: /* And put them out in forward order */
329: {
330: REG1 int i;
331:
332: if (outpos+(i = (de_stack-stackp)) >= OUTBUFSIZ) {
333: do {
334: if (i > OUTBUFSIZ-outpos) i = OUTBUFSIZ-outpos;
335:
336: if (i > 0) {
337: memcpy(outbuf+outpos, stackp, i);
338: outpos += i;
339: }
340: if (outpos >= OUTBUFSIZ) {
341: if (!test && write(out, outbuf, outpos) != outpos){
342: write_error();
343: }
344: outpos = 0;
345: }
346: stackp+= i;
347: } while ((i = (de_stack-stackp)) > 0);
348: } else {
349: memcpy(outbuf+outpos, stackp, i);
350: outpos += i;
351: }
352: }
353:
354: if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */
355:
356: tab_prefixof(code) = (unsigned short)oldcode;
357: tab_suffixof(code) = (char_type)finchar;
358: free_ent = code+1;
359: }
360: oldcode = incode; /* Remember previous code. */
361: }
362: bytes_in += rsize;
363:
364: } while (rsize != 0);
365:
366: if (!test && outpos > 0 && write(out, outbuf, outpos) != outpos) {
367: write_error();
368: }
369: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.