1*593dc095SDavid du Colombier /* infback.c -- inflate using a call-back interface
2*593dc095SDavid du Colombier * Copyright (C) 1995-2003 Mark Adler
3*593dc095SDavid du Colombier * For conditions of distribution and use, see copyright notice in zlib.h
4*593dc095SDavid du Colombier */
5*593dc095SDavid du Colombier
6*593dc095SDavid du Colombier /*
7*593dc095SDavid du Colombier This code is largely copied from inflate.c. Normally either infback.o or
8*593dc095SDavid du Colombier inflate.o would be linked into an application--not both. The interface
9*593dc095SDavid du Colombier with inffast.c is retained so that optimized assembler-coded versions of
10*593dc095SDavid du Colombier inflate_fast() can be used with either inflate.c or infback.c.
11*593dc095SDavid du Colombier */
12*593dc095SDavid du Colombier
13*593dc095SDavid du Colombier #include "zutil.h"
14*593dc095SDavid du Colombier #include "inftrees.h"
15*593dc095SDavid du Colombier #include "inflate.h"
16*593dc095SDavid du Colombier #include "inffast.h"
17*593dc095SDavid du Colombier
18*593dc095SDavid du Colombier /* function prototypes */
19*593dc095SDavid du Colombier local void fixedtables OF((struct inflate_state FAR *state));
20*593dc095SDavid du Colombier
21*593dc095SDavid du Colombier /*
22*593dc095SDavid du Colombier strm provides memory allocation functions in zalloc and zfree, or
23*593dc095SDavid du Colombier Z_NULL to use the library memory allocation functions.
24*593dc095SDavid du Colombier
25*593dc095SDavid du Colombier windowBits is in the range 8..15, and window is a user-supplied
26*593dc095SDavid du Colombier window and output buffer that is 2**windowBits bytes.
27*593dc095SDavid du Colombier */
inflateBackInit_(strm,windowBits,window,version,stream_size)28*593dc095SDavid du Colombier int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
29*593dc095SDavid du Colombier z_stream FAR *strm;
30*593dc095SDavid du Colombier int windowBits;
31*593dc095SDavid du Colombier unsigned char FAR *window;
32*593dc095SDavid du Colombier const char *version;
33*593dc095SDavid du Colombier int stream_size;
34*593dc095SDavid du Colombier {
35*593dc095SDavid du Colombier struct inflate_state FAR *state;
36*593dc095SDavid du Colombier
37*593dc095SDavid du Colombier if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
38*593dc095SDavid du Colombier stream_size != (int)(sizeof(z_stream)))
39*593dc095SDavid du Colombier return Z_VERSION_ERROR;
40*593dc095SDavid du Colombier if (strm == Z_NULL || window == Z_NULL ||
41*593dc095SDavid du Colombier windowBits < 8 || windowBits > 15)
42*593dc095SDavid du Colombier return Z_STREAM_ERROR;
43*593dc095SDavid du Colombier strm->msg = Z_NULL; /* in case we return an error */
44*593dc095SDavid du Colombier if (strm->zalloc == (alloc_func)0) {
45*593dc095SDavid du Colombier strm->zalloc = zcalloc;
46*593dc095SDavid du Colombier strm->opaque = (voidpf)0;
47*593dc095SDavid du Colombier }
48*593dc095SDavid du Colombier if (strm->zfree == (free_func)0) strm->zfree = zcfree;
49*593dc095SDavid du Colombier state = (struct inflate_state FAR *)ZALLOC(strm, 1,
50*593dc095SDavid du Colombier sizeof(struct inflate_state));
51*593dc095SDavid du Colombier if (state == Z_NULL) return Z_MEM_ERROR;
52*593dc095SDavid du Colombier Tracev((stderr, "inflate: allocated\n"));
53*593dc095SDavid du Colombier strm->state = (voidpf)state;
54*593dc095SDavid du Colombier state->wbits = windowBits;
55*593dc095SDavid du Colombier state->wsize = 1U << windowBits;
56*593dc095SDavid du Colombier state->window = window;
57*593dc095SDavid du Colombier state->write = 0;
58*593dc095SDavid du Colombier state->whave = 0;
59*593dc095SDavid du Colombier return Z_OK;
60*593dc095SDavid du Colombier }
61*593dc095SDavid du Colombier
62*593dc095SDavid du Colombier /*
63*593dc095SDavid du Colombier Return state with length and distance decoding tables and index sizes set to
64*593dc095SDavid du Colombier fixed code decoding. Normally this returns fixed tables from inffixed.h.
65*593dc095SDavid du Colombier If BUILDFIXED is defined, then instead this routine builds the tables the
66*593dc095SDavid du Colombier first time it's called, and returns those tables the first time and
67*593dc095SDavid du Colombier thereafter. This reduces the size of the code by about 2K bytes, in
68*593dc095SDavid du Colombier exchange for a little execution time. However, BUILDFIXED should not be
69*593dc095SDavid du Colombier used for threaded applications, since the rewriting of the tables and virgin
70*593dc095SDavid du Colombier may not be thread-safe.
71*593dc095SDavid du Colombier */
fixedtables(state)72*593dc095SDavid du Colombier local void fixedtables(state)
73*593dc095SDavid du Colombier struct inflate_state FAR *state;
74*593dc095SDavid du Colombier {
75*593dc095SDavid du Colombier #ifdef BUILDFIXED
76*593dc095SDavid du Colombier static int virgin = 1;
77*593dc095SDavid du Colombier static code *lenfix, *distfix;
78*593dc095SDavid du Colombier static code fixed[544];
79*593dc095SDavid du Colombier
80*593dc095SDavid du Colombier /* build fixed huffman tables if first call (may not be thread safe) */
81*593dc095SDavid du Colombier if (virgin) {
82*593dc095SDavid du Colombier unsigned sym, bits;
83*593dc095SDavid du Colombier static code *next;
84*593dc095SDavid du Colombier
85*593dc095SDavid du Colombier /* literal/length table */
86*593dc095SDavid du Colombier sym = 0;
87*593dc095SDavid du Colombier while (sym < 144) state->lens[sym++] = 8;
88*593dc095SDavid du Colombier while (sym < 256) state->lens[sym++] = 9;
89*593dc095SDavid du Colombier while (sym < 280) state->lens[sym++] = 7;
90*593dc095SDavid du Colombier while (sym < 288) state->lens[sym++] = 8;
91*593dc095SDavid du Colombier next = fixed;
92*593dc095SDavid du Colombier lenfix = next;
93*593dc095SDavid du Colombier bits = 9;
94*593dc095SDavid du Colombier inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
95*593dc095SDavid du Colombier
96*593dc095SDavid du Colombier /* distance table */
97*593dc095SDavid du Colombier sym = 0;
98*593dc095SDavid du Colombier while (sym < 32) state->lens[sym++] = 5;
99*593dc095SDavid du Colombier distfix = next;
100*593dc095SDavid du Colombier bits = 5;
101*593dc095SDavid du Colombier inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
102*593dc095SDavid du Colombier
103*593dc095SDavid du Colombier /* do this just once */
104*593dc095SDavid du Colombier virgin = 0;
105*593dc095SDavid du Colombier }
106*593dc095SDavid du Colombier #else /* !BUILDFIXED */
107*593dc095SDavid du Colombier # include "inffixed.h"
108*593dc095SDavid du Colombier #endif /* BUILDFIXED */
109*593dc095SDavid du Colombier state->lencode = lenfix;
110*593dc095SDavid du Colombier state->lenbits = 9;
111*593dc095SDavid du Colombier state->distcode = distfix;
112*593dc095SDavid du Colombier state->distbits = 5;
113*593dc095SDavid du Colombier }
114*593dc095SDavid du Colombier
115*593dc095SDavid du Colombier /* Macros for inflateBack(): */
116*593dc095SDavid du Colombier
117*593dc095SDavid du Colombier /* Load returned state from inflate_fast() */
118*593dc095SDavid du Colombier #define LOAD() \
119*593dc095SDavid du Colombier do { \
120*593dc095SDavid du Colombier put = strm->next_out; \
121*593dc095SDavid du Colombier left = strm->avail_out; \
122*593dc095SDavid du Colombier next = strm->next_in; \
123*593dc095SDavid du Colombier have = strm->avail_in; \
124*593dc095SDavid du Colombier hold = state->hold; \
125*593dc095SDavid du Colombier bits = state->bits; \
126*593dc095SDavid du Colombier } while (0)
127*593dc095SDavid du Colombier
128*593dc095SDavid du Colombier /* Set state from registers for inflate_fast() */
129*593dc095SDavid du Colombier #define RESTORE() \
130*593dc095SDavid du Colombier do { \
131*593dc095SDavid du Colombier strm->next_out = put; \
132*593dc095SDavid du Colombier strm->avail_out = left; \
133*593dc095SDavid du Colombier strm->next_in = next; \
134*593dc095SDavid du Colombier strm->avail_in = have; \
135*593dc095SDavid du Colombier state->hold = hold; \
136*593dc095SDavid du Colombier state->bits = bits; \
137*593dc095SDavid du Colombier } while (0)
138*593dc095SDavid du Colombier
139*593dc095SDavid du Colombier /* Clear the input bit accumulator */
140*593dc095SDavid du Colombier #define INITBITS() \
141*593dc095SDavid du Colombier do { \
142*593dc095SDavid du Colombier hold = 0; \
143*593dc095SDavid du Colombier bits = 0; \
144*593dc095SDavid du Colombier } while (0)
145*593dc095SDavid du Colombier
146*593dc095SDavid du Colombier /* Assure that some input is available. If input is requested, but denied,
147*593dc095SDavid du Colombier then return a Z_BUF_ERROR from inflateBack(). */
148*593dc095SDavid du Colombier #define PULL() \
149*593dc095SDavid du Colombier do { \
150*593dc095SDavid du Colombier if (have == 0) { \
151*593dc095SDavid du Colombier have = in(in_desc, &next); \
152*593dc095SDavid du Colombier if (have == 0) { \
153*593dc095SDavid du Colombier next = Z_NULL; \
154*593dc095SDavid du Colombier ret = Z_BUF_ERROR; \
155*593dc095SDavid du Colombier goto inf_leave; \
156*593dc095SDavid du Colombier } \
157*593dc095SDavid du Colombier } \
158*593dc095SDavid du Colombier } while (0)
159*593dc095SDavid du Colombier
160*593dc095SDavid du Colombier /* Get a byte of input into the bit accumulator, or return from inflateBack()
161*593dc095SDavid du Colombier with an error if there is no input available. */
162*593dc095SDavid du Colombier #define PULLBYTE() \
163*593dc095SDavid du Colombier do { \
164*593dc095SDavid du Colombier PULL(); \
165*593dc095SDavid du Colombier have--; \
166*593dc095SDavid du Colombier hold += (unsigned long)(*next++) << bits; \
167*593dc095SDavid du Colombier bits += 8; \
168*593dc095SDavid du Colombier } while (0)
169*593dc095SDavid du Colombier
170*593dc095SDavid du Colombier /* Assure that there are at least n bits in the bit accumulator. If there is
171*593dc095SDavid du Colombier not enough available input to do that, then return from inflateBack() with
172*593dc095SDavid du Colombier an error. */
173*593dc095SDavid du Colombier #define NEEDBITS(n) \
174*593dc095SDavid du Colombier do { \
175*593dc095SDavid du Colombier while (bits < (unsigned)(n)) \
176*593dc095SDavid du Colombier PULLBYTE(); \
177*593dc095SDavid du Colombier } while (0)
178*593dc095SDavid du Colombier
179*593dc095SDavid du Colombier /* Return the low n bits of the bit accumulator (n < 16) */
180*593dc095SDavid du Colombier #define BITS(n) \
181*593dc095SDavid du Colombier ((unsigned)hold & ((1U << (n)) - 1))
182*593dc095SDavid du Colombier
183*593dc095SDavid du Colombier /* Remove n bits from the bit accumulator */
184*593dc095SDavid du Colombier #define DROPBITS(n) \
185*593dc095SDavid du Colombier do { \
186*593dc095SDavid du Colombier hold >>= (n); \
187*593dc095SDavid du Colombier bits -= (unsigned)(n); \
188*593dc095SDavid du Colombier } while (0)
189*593dc095SDavid du Colombier
190*593dc095SDavid du Colombier /* Remove zero to seven bits as needed to go to a byte boundary */
191*593dc095SDavid du Colombier #define BYTEBITS() \
192*593dc095SDavid du Colombier do { \
193*593dc095SDavid du Colombier hold >>= bits & 7; \
194*593dc095SDavid du Colombier bits -= bits & 7; \
195*593dc095SDavid du Colombier } while (0)
196*593dc095SDavid du Colombier
197*593dc095SDavid du Colombier /* Assure that some output space is available, by writing out the window
198*593dc095SDavid du Colombier if it's full. If the write fails, return from inflateBack() with a
199*593dc095SDavid du Colombier Z_BUF_ERROR. */
200*593dc095SDavid du Colombier #define ROOM() \
201*593dc095SDavid du Colombier do { \
202*593dc095SDavid du Colombier if (left == 0) { \
203*593dc095SDavid du Colombier put = state->window; \
204*593dc095SDavid du Colombier left = state->wsize; \
205*593dc095SDavid du Colombier state->whave = left; \
206*593dc095SDavid du Colombier if (out(out_desc, put, left)) { \
207*593dc095SDavid du Colombier ret = Z_BUF_ERROR; \
208*593dc095SDavid du Colombier goto inf_leave; \
209*593dc095SDavid du Colombier } \
210*593dc095SDavid du Colombier } \
211*593dc095SDavid du Colombier } while (0)
212*593dc095SDavid du Colombier
213*593dc095SDavid du Colombier /*
214*593dc095SDavid du Colombier strm provides the memory allocation functions and window buffer on input,
215*593dc095SDavid du Colombier and provides information on the unused input on return. For Z_DATA_ERROR
216*593dc095SDavid du Colombier returns, strm will also provide an error message.
217*593dc095SDavid du Colombier
218*593dc095SDavid du Colombier in() and out() are the call-back input and output functions. When
219*593dc095SDavid du Colombier inflateBack() needs more input, it calls in(). When inflateBack() has
220*593dc095SDavid du Colombier filled the window with output, or when it completes with data in the
221*593dc095SDavid du Colombier window, it calls out() to write out the data. The application must not
222*593dc095SDavid du Colombier change the provided input until in() is called again or inflateBack()
223*593dc095SDavid du Colombier returns. The application must not change the window/output buffer until
224*593dc095SDavid du Colombier inflateBack() returns.
225*593dc095SDavid du Colombier
226*593dc095SDavid du Colombier in() and out() are called with a descriptor parameter provided in the
227*593dc095SDavid du Colombier inflateBack() call. This parameter can be a structure that provides the
228*593dc095SDavid du Colombier information required to do the read or write, as well as accumulated
229*593dc095SDavid du Colombier information on the input and output such as totals and check values.
230*593dc095SDavid du Colombier
231*593dc095SDavid du Colombier in() should return zero on failure. out() should return non-zero on
232*593dc095SDavid du Colombier failure. If either in() or out() fails, than inflateBack() returns a
233*593dc095SDavid du Colombier Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
234*593dc095SDavid du Colombier was in() or out() that caused in the error. Otherwise, inflateBack()
235*593dc095SDavid du Colombier returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
236*593dc095SDavid du Colombier error, or Z_MEM_ERROR if it could not allocate memory for the state.
237*593dc095SDavid du Colombier inflateBack() can also return Z_STREAM_ERROR if the input parameters
238*593dc095SDavid du Colombier are not correct, i.e. strm is Z_NULL or the state was not initialized.
239*593dc095SDavid du Colombier */
inflateBack(strm,in,in_desc,out,out_desc)240*593dc095SDavid du Colombier int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
241*593dc095SDavid du Colombier z_stream FAR *strm;
242*593dc095SDavid du Colombier in_func in;
243*593dc095SDavid du Colombier void FAR *in_desc;
244*593dc095SDavid du Colombier out_func out;
245*593dc095SDavid du Colombier void FAR *out_desc;
246*593dc095SDavid du Colombier {
247*593dc095SDavid du Colombier struct inflate_state FAR *state;
248*593dc095SDavid du Colombier unsigned char FAR *next; /* next input */
249*593dc095SDavid du Colombier unsigned char FAR *put; /* next output */
250*593dc095SDavid du Colombier unsigned have, left; /* available input and output */
251*593dc095SDavid du Colombier unsigned long hold; /* bit buffer */
252*593dc095SDavid du Colombier unsigned bits; /* bits in bit buffer */
253*593dc095SDavid du Colombier unsigned copy; /* number of stored or match bytes to copy */
254*593dc095SDavid du Colombier unsigned char FAR *from; /* where to copy match bytes from */
255*593dc095SDavid du Colombier code this; /* current decoding table entry */
256*593dc095SDavid du Colombier code last; /* parent table entry */
257*593dc095SDavid du Colombier unsigned len; /* length to copy for repeats, bits to drop */
258*593dc095SDavid du Colombier int ret; /* return code */
259*593dc095SDavid du Colombier static const unsigned short order[19] = /* permutation of code lengths */
260*593dc095SDavid du Colombier {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
261*593dc095SDavid du Colombier
262*593dc095SDavid du Colombier /* Check that the strm exists and that the state was initialized */
263*593dc095SDavid du Colombier if (strm == Z_NULL || strm->state == Z_NULL)
264*593dc095SDavid du Colombier return Z_STREAM_ERROR;
265*593dc095SDavid du Colombier state = (struct inflate_state FAR *)strm->state;
266*593dc095SDavid du Colombier
267*593dc095SDavid du Colombier /* Reset the state */
268*593dc095SDavid du Colombier strm->msg = Z_NULL;
269*593dc095SDavid du Colombier state->mode = TYPE;
270*593dc095SDavid du Colombier state->last = 0;
271*593dc095SDavid du Colombier state->whave = 0;
272*593dc095SDavid du Colombier next = strm->next_in;
273*593dc095SDavid du Colombier have = next != Z_NULL ? strm->avail_in : 0;
274*593dc095SDavid du Colombier hold = 0;
275*593dc095SDavid du Colombier bits = 0;
276*593dc095SDavid du Colombier put = state->window;
277*593dc095SDavid du Colombier left = state->wsize;
278*593dc095SDavid du Colombier
279*593dc095SDavid du Colombier /* Inflate until end of block marked as last */
280*593dc095SDavid du Colombier for (;;)
281*593dc095SDavid du Colombier switch (state->mode) {
282*593dc095SDavid du Colombier case TYPE:
283*593dc095SDavid du Colombier /* determine and dispatch block type */
284*593dc095SDavid du Colombier if (state->last) {
285*593dc095SDavid du Colombier BYTEBITS();
286*593dc095SDavid du Colombier state->mode = DONE;
287*593dc095SDavid du Colombier break;
288*593dc095SDavid du Colombier }
289*593dc095SDavid du Colombier NEEDBITS(3);
290*593dc095SDavid du Colombier state->last = BITS(1);
291*593dc095SDavid du Colombier DROPBITS(1);
292*593dc095SDavid du Colombier switch (BITS(2)) {
293*593dc095SDavid du Colombier case 0: /* stored block */
294*593dc095SDavid du Colombier Tracev((stderr, "inflate: stored block%s\n",
295*593dc095SDavid du Colombier state->last ? " (last)" : ""));
296*593dc095SDavid du Colombier state->mode = STORED;
297*593dc095SDavid du Colombier break;
298*593dc095SDavid du Colombier case 1: /* fixed block */
299*593dc095SDavid du Colombier fixedtables(state);
300*593dc095SDavid du Colombier Tracev((stderr, "inflate: fixed codes block%s\n",
301*593dc095SDavid du Colombier state->last ? " (last)" : ""));
302*593dc095SDavid du Colombier state->mode = LEN; /* decode codes */
303*593dc095SDavid du Colombier break;
304*593dc095SDavid du Colombier case 2: /* dynamic block */
305*593dc095SDavid du Colombier Tracev((stderr, "inflate: dynamic codes block%s\n",
306*593dc095SDavid du Colombier state->last ? " (last)" : ""));
307*593dc095SDavid du Colombier state->mode = TABLE;
308*593dc095SDavid du Colombier break;
309*593dc095SDavid du Colombier case 3:
310*593dc095SDavid du Colombier strm->msg = (char *)"invalid block type";
311*593dc095SDavid du Colombier state->mode = BAD;
312*593dc095SDavid du Colombier }
313*593dc095SDavid du Colombier DROPBITS(2);
314*593dc095SDavid du Colombier break;
315*593dc095SDavid du Colombier
316*593dc095SDavid du Colombier case STORED:
317*593dc095SDavid du Colombier /* get and verify stored block length */
318*593dc095SDavid du Colombier BYTEBITS(); /* go to byte boundary */
319*593dc095SDavid du Colombier NEEDBITS(32);
320*593dc095SDavid du Colombier if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
321*593dc095SDavid du Colombier strm->msg = (char *)"invalid stored block lengths";
322*593dc095SDavid du Colombier state->mode = BAD;
323*593dc095SDavid du Colombier break;
324*593dc095SDavid du Colombier }
325*593dc095SDavid du Colombier state->length = (unsigned)hold & 0xffff;
326*593dc095SDavid du Colombier Tracev((stderr, "inflate: stored length %u\n",
327*593dc095SDavid du Colombier state->length));
328*593dc095SDavid du Colombier INITBITS();
329*593dc095SDavid du Colombier
330*593dc095SDavid du Colombier /* copy stored block from input to output */
331*593dc095SDavid du Colombier while (state->length != 0) {
332*593dc095SDavid du Colombier copy = state->length;
333*593dc095SDavid du Colombier PULL();
334*593dc095SDavid du Colombier ROOM();
335*593dc095SDavid du Colombier if (copy > have) copy = have;
336*593dc095SDavid du Colombier if (copy > left) copy = left;
337*593dc095SDavid du Colombier zmemcpy(put, next, copy);
338*593dc095SDavid du Colombier have -= copy;
339*593dc095SDavid du Colombier next += copy;
340*593dc095SDavid du Colombier left -= copy;
341*593dc095SDavid du Colombier put += copy;
342*593dc095SDavid du Colombier state->length -= copy;
343*593dc095SDavid du Colombier }
344*593dc095SDavid du Colombier Tracev((stderr, "inflate: stored end\n"));
345*593dc095SDavid du Colombier state->mode = TYPE;
346*593dc095SDavid du Colombier break;
347*593dc095SDavid du Colombier
348*593dc095SDavid du Colombier case TABLE:
349*593dc095SDavid du Colombier /* get dynamic table entries descriptor */
350*593dc095SDavid du Colombier NEEDBITS(14);
351*593dc095SDavid du Colombier state->nlen = BITS(5) + 257;
352*593dc095SDavid du Colombier DROPBITS(5);
353*593dc095SDavid du Colombier state->ndist = BITS(5) + 1;
354*593dc095SDavid du Colombier DROPBITS(5);
355*593dc095SDavid du Colombier state->ncode = BITS(4) + 4;
356*593dc095SDavid du Colombier DROPBITS(4);
357*593dc095SDavid du Colombier #ifndef PKZIP_BUG_WORKAROUND
358*593dc095SDavid du Colombier if (state->nlen > 286 || state->ndist > 30) {
359*593dc095SDavid du Colombier strm->msg = (char *)"too many length or distance symbols";
360*593dc095SDavid du Colombier state->mode = BAD;
361*593dc095SDavid du Colombier break;
362*593dc095SDavid du Colombier }
363*593dc095SDavid du Colombier #endif
364*593dc095SDavid du Colombier Tracev((stderr, "inflate: table sizes ok\n"));
365*593dc095SDavid du Colombier
366*593dc095SDavid du Colombier /* get code length code lengths (not a typo) */
367*593dc095SDavid du Colombier state->have = 0;
368*593dc095SDavid du Colombier while (state->have < state->ncode) {
369*593dc095SDavid du Colombier NEEDBITS(3);
370*593dc095SDavid du Colombier state->lens[order[state->have++]] = (unsigned short)BITS(3);
371*593dc095SDavid du Colombier DROPBITS(3);
372*593dc095SDavid du Colombier }
373*593dc095SDavid du Colombier while (state->have < 19)
374*593dc095SDavid du Colombier state->lens[order[state->have++]] = 0;
375*593dc095SDavid du Colombier state->next = state->codes;
376*593dc095SDavid du Colombier state->lencode = (code const FAR *)(state->next);
377*593dc095SDavid du Colombier state->lenbits = 7;
378*593dc095SDavid du Colombier ret = inflate_table(CODES, state->lens, 19, &(state->next),
379*593dc095SDavid du Colombier &(state->lenbits), state->work);
380*593dc095SDavid du Colombier if (ret) {
381*593dc095SDavid du Colombier strm->msg = (char *)"invalid code lengths set";
382*593dc095SDavid du Colombier state->mode = BAD;
383*593dc095SDavid du Colombier break;
384*593dc095SDavid du Colombier }
385*593dc095SDavid du Colombier Tracev((stderr, "inflate: code lengths ok\n"));
386*593dc095SDavid du Colombier
387*593dc095SDavid du Colombier /* get length and distance code code lengths */
388*593dc095SDavid du Colombier state->have = 0;
389*593dc095SDavid du Colombier while (state->have < state->nlen + state->ndist) {
390*593dc095SDavid du Colombier for (;;) {
391*593dc095SDavid du Colombier this = state->lencode[BITS(state->lenbits)];
392*593dc095SDavid du Colombier if ((unsigned)(this.bits) <= bits) break;
393*593dc095SDavid du Colombier PULLBYTE();
394*593dc095SDavid du Colombier }
395*593dc095SDavid du Colombier if (this.val < 16) {
396*593dc095SDavid du Colombier NEEDBITS(this.bits);
397*593dc095SDavid du Colombier DROPBITS(this.bits);
398*593dc095SDavid du Colombier state->lens[state->have++] = this.val;
399*593dc095SDavid du Colombier }
400*593dc095SDavid du Colombier else {
401*593dc095SDavid du Colombier if (this.val == 16) {
402*593dc095SDavid du Colombier NEEDBITS(this.bits + 2);
403*593dc095SDavid du Colombier DROPBITS(this.bits);
404*593dc095SDavid du Colombier if (state->have == 0) {
405*593dc095SDavid du Colombier strm->msg = (char *)"invalid bit length repeat";
406*593dc095SDavid du Colombier state->mode = BAD;
407*593dc095SDavid du Colombier break;
408*593dc095SDavid du Colombier }
409*593dc095SDavid du Colombier len = (unsigned)(state->lens[state->have - 1]);
410*593dc095SDavid du Colombier copy = 3 + BITS(2);
411*593dc095SDavid du Colombier DROPBITS(2);
412*593dc095SDavid du Colombier }
413*593dc095SDavid du Colombier else if (this.val == 17) {
414*593dc095SDavid du Colombier NEEDBITS(this.bits + 3);
415*593dc095SDavid du Colombier DROPBITS(this.bits);
416*593dc095SDavid du Colombier len = 0;
417*593dc095SDavid du Colombier copy = 3 + BITS(3);
418*593dc095SDavid du Colombier DROPBITS(3);
419*593dc095SDavid du Colombier }
420*593dc095SDavid du Colombier else {
421*593dc095SDavid du Colombier NEEDBITS(this.bits + 7);
422*593dc095SDavid du Colombier DROPBITS(this.bits);
423*593dc095SDavid du Colombier len = 0;
424*593dc095SDavid du Colombier copy = 11 + BITS(7);
425*593dc095SDavid du Colombier DROPBITS(7);
426*593dc095SDavid du Colombier }
427*593dc095SDavid du Colombier if (state->have + copy > state->nlen + state->ndist) {
428*593dc095SDavid du Colombier strm->msg = (char *)"invalid bit length repeat";
429*593dc095SDavid du Colombier state->mode = BAD;
430*593dc095SDavid du Colombier break;
431*593dc095SDavid du Colombier }
432*593dc095SDavid du Colombier while (copy--)
433*593dc095SDavid du Colombier state->lens[state->have++] = (unsigned short)len;
434*593dc095SDavid du Colombier }
435*593dc095SDavid du Colombier }
436*593dc095SDavid du Colombier
437*593dc095SDavid du Colombier /* handle error breaks in while */
438*593dc095SDavid du Colombier if (state->mode == BAD) break;
439*593dc095SDavid du Colombier
440*593dc095SDavid du Colombier /* build code tables */
441*593dc095SDavid du Colombier state->next = state->codes;
442*593dc095SDavid du Colombier state->lencode = (code const FAR *)(state->next);
443*593dc095SDavid du Colombier state->lenbits = 9;
444*593dc095SDavid du Colombier ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
445*593dc095SDavid du Colombier &(state->lenbits), state->work);
446*593dc095SDavid du Colombier if (ret) {
447*593dc095SDavid du Colombier strm->msg = (char *)"invalid literal/lengths set";
448*593dc095SDavid du Colombier state->mode = BAD;
449*593dc095SDavid du Colombier break;
450*593dc095SDavid du Colombier }
451*593dc095SDavid du Colombier state->distcode = (code const FAR *)(state->next);
452*593dc095SDavid du Colombier state->distbits = 6;
453*593dc095SDavid du Colombier ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
454*593dc095SDavid du Colombier &(state->next), &(state->distbits), state->work);
455*593dc095SDavid du Colombier if (ret) {
456*593dc095SDavid du Colombier strm->msg = (char *)"invalid distances set";
457*593dc095SDavid du Colombier state->mode = BAD;
458*593dc095SDavid du Colombier break;
459*593dc095SDavid du Colombier }
460*593dc095SDavid du Colombier Tracev((stderr, "inflate: codes ok\n"));
461*593dc095SDavid du Colombier state->mode = LEN;
462*593dc095SDavid du Colombier
463*593dc095SDavid du Colombier case LEN:
464*593dc095SDavid du Colombier /* use inflate_fast() if we have enough input and output */
465*593dc095SDavid du Colombier if (have >= 6 && left >= 258) {
466*593dc095SDavid du Colombier RESTORE();
467*593dc095SDavid du Colombier if (state->whave < state->wsize)
468*593dc095SDavid du Colombier state->whave = state->wsize - left;
469*593dc095SDavid du Colombier inflate_fast(strm, state->wsize);
470*593dc095SDavid du Colombier LOAD();
471*593dc095SDavid du Colombier break;
472*593dc095SDavid du Colombier }
473*593dc095SDavid du Colombier
474*593dc095SDavid du Colombier /* get a literal, length, or end-of-block code */
475*593dc095SDavid du Colombier for (;;) {
476*593dc095SDavid du Colombier this = state->lencode[BITS(state->lenbits)];
477*593dc095SDavid du Colombier if ((unsigned)(this.bits) <= bits) break;
478*593dc095SDavid du Colombier PULLBYTE();
479*593dc095SDavid du Colombier }
480*593dc095SDavid du Colombier if (this.op && (this.op & 0xf0) == 0) {
481*593dc095SDavid du Colombier last = this;
482*593dc095SDavid du Colombier for (;;) {
483*593dc095SDavid du Colombier this = state->lencode[last.val +
484*593dc095SDavid du Colombier (BITS(last.bits + last.op) >> last.bits)];
485*593dc095SDavid du Colombier if ((unsigned)(last.bits + this.bits) <= bits) break;
486*593dc095SDavid du Colombier PULLBYTE();
487*593dc095SDavid du Colombier }
488*593dc095SDavid du Colombier DROPBITS(last.bits);
489*593dc095SDavid du Colombier }
490*593dc095SDavid du Colombier DROPBITS(this.bits);
491*593dc095SDavid du Colombier state->length = (unsigned)this.val;
492*593dc095SDavid du Colombier
493*593dc095SDavid du Colombier /* process literal */
494*593dc095SDavid du Colombier if (this.op == 0) {
495*593dc095SDavid du Colombier Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
496*593dc095SDavid du Colombier "inflate: literal '%c'\n" :
497*593dc095SDavid du Colombier "inflate: literal 0x%02x\n", this.val));
498*593dc095SDavid du Colombier ROOM();
499*593dc095SDavid du Colombier *put++ = (unsigned char)(state->length);
500*593dc095SDavid du Colombier left--;
501*593dc095SDavid du Colombier state->mode = LEN;
502*593dc095SDavid du Colombier break;
503*593dc095SDavid du Colombier }
504*593dc095SDavid du Colombier
505*593dc095SDavid du Colombier /* process end of block */
506*593dc095SDavid du Colombier if (this.op & 32) {
507*593dc095SDavid du Colombier Tracevv((stderr, "inflate: end of block\n"));
508*593dc095SDavid du Colombier state->mode = TYPE;
509*593dc095SDavid du Colombier break;
510*593dc095SDavid du Colombier }
511*593dc095SDavid du Colombier
512*593dc095SDavid du Colombier /* invalid code */
513*593dc095SDavid du Colombier if (this.op & 64) {
514*593dc095SDavid du Colombier strm->msg = (char *)"invalid literal/length code";
515*593dc095SDavid du Colombier state->mode = BAD;
516*593dc095SDavid du Colombier break;
517*593dc095SDavid du Colombier }
518*593dc095SDavid du Colombier
519*593dc095SDavid du Colombier /* length code -- get extra bits, if any */
520*593dc095SDavid du Colombier state->extra = (unsigned)(this.op) & 15;
521*593dc095SDavid du Colombier if (state->extra != 0) {
522*593dc095SDavid du Colombier NEEDBITS(state->extra);
523*593dc095SDavid du Colombier state->length += BITS(state->extra);
524*593dc095SDavid du Colombier DROPBITS(state->extra);
525*593dc095SDavid du Colombier }
526*593dc095SDavid du Colombier Tracevv((stderr, "inflate: length %u\n", state->length));
527*593dc095SDavid du Colombier
528*593dc095SDavid du Colombier /* get distance code */
529*593dc095SDavid du Colombier for (;;) {
530*593dc095SDavid du Colombier this = state->distcode[BITS(state->distbits)];
531*593dc095SDavid du Colombier if ((unsigned)(this.bits) <= bits) break;
532*593dc095SDavid du Colombier PULLBYTE();
533*593dc095SDavid du Colombier }
534*593dc095SDavid du Colombier if ((this.op & 0xf0) == 0) {
535*593dc095SDavid du Colombier last = this;
536*593dc095SDavid du Colombier for (;;) {
537*593dc095SDavid du Colombier this = state->distcode[last.val +
538*593dc095SDavid du Colombier (BITS(last.bits + last.op) >> last.bits)];
539*593dc095SDavid du Colombier if ((unsigned)(last.bits + this.bits) <= bits) break;
540*593dc095SDavid du Colombier PULLBYTE();
541*593dc095SDavid du Colombier }
542*593dc095SDavid du Colombier DROPBITS(last.bits);
543*593dc095SDavid du Colombier }
544*593dc095SDavid du Colombier DROPBITS(this.bits);
545*593dc095SDavid du Colombier if (this.op & 64) {
546*593dc095SDavid du Colombier strm->msg = (char *)"invalid distance code";
547*593dc095SDavid du Colombier state->mode = BAD;
548*593dc095SDavid du Colombier break;
549*593dc095SDavid du Colombier }
550*593dc095SDavid du Colombier state->offset = (unsigned)this.val;
551*593dc095SDavid du Colombier
552*593dc095SDavid du Colombier /* get distance extra bits, if any */
553*593dc095SDavid du Colombier state->extra = (unsigned)(this.op) & 15;
554*593dc095SDavid du Colombier if (state->extra != 0) {
555*593dc095SDavid du Colombier NEEDBITS(state->extra);
556*593dc095SDavid du Colombier state->offset += BITS(state->extra);
557*593dc095SDavid du Colombier DROPBITS(state->extra);
558*593dc095SDavid du Colombier }
559*593dc095SDavid du Colombier if (state->offset > state->wsize - (state->whave < state->wsize ?
560*593dc095SDavid du Colombier left : 0)) {
561*593dc095SDavid du Colombier strm->msg = (char *)"invalid distance too far back";
562*593dc095SDavid du Colombier state->mode = BAD;
563*593dc095SDavid du Colombier break;
564*593dc095SDavid du Colombier }
565*593dc095SDavid du Colombier Tracevv((stderr, "inflate: distance %u\n", state->offset));
566*593dc095SDavid du Colombier
567*593dc095SDavid du Colombier /* copy match from window to output */
568*593dc095SDavid du Colombier do {
569*593dc095SDavid du Colombier ROOM();
570*593dc095SDavid du Colombier copy = state->wsize - state->offset;
571*593dc095SDavid du Colombier if (copy < left) {
572*593dc095SDavid du Colombier from = put + copy;
573*593dc095SDavid du Colombier copy = left - copy;
574*593dc095SDavid du Colombier }
575*593dc095SDavid du Colombier else {
576*593dc095SDavid du Colombier from = put - state->offset;
577*593dc095SDavid du Colombier copy = left;
578*593dc095SDavid du Colombier }
579*593dc095SDavid du Colombier if (copy > state->length) copy = state->length;
580*593dc095SDavid du Colombier state->length -= copy;
581*593dc095SDavid du Colombier left -= copy;
582*593dc095SDavid du Colombier do {
583*593dc095SDavid du Colombier *put++ = *from++;
584*593dc095SDavid du Colombier } while (--copy);
585*593dc095SDavid du Colombier } while (state->length != 0);
586*593dc095SDavid du Colombier break;
587*593dc095SDavid du Colombier
588*593dc095SDavid du Colombier case DONE:
589*593dc095SDavid du Colombier /* inflate stream terminated properly -- write leftover output */
590*593dc095SDavid du Colombier ret = Z_STREAM_END;
591*593dc095SDavid du Colombier if (left < state->wsize) {
592*593dc095SDavid du Colombier if (out(out_desc, state->window, state->wsize - left))
593*593dc095SDavid du Colombier ret = Z_BUF_ERROR;
594*593dc095SDavid du Colombier }
595*593dc095SDavid du Colombier goto inf_leave;
596*593dc095SDavid du Colombier
597*593dc095SDavid du Colombier case BAD:
598*593dc095SDavid du Colombier ret = Z_DATA_ERROR;
599*593dc095SDavid du Colombier goto inf_leave;
600*593dc095SDavid du Colombier
601*593dc095SDavid du Colombier default: /* can't happen, but makes compilers happy */
602*593dc095SDavid du Colombier ret = Z_STREAM_ERROR;
603*593dc095SDavid du Colombier goto inf_leave;
604*593dc095SDavid du Colombier }
605*593dc095SDavid du Colombier
606*593dc095SDavid du Colombier /* Return unused input */
607*593dc095SDavid du Colombier inf_leave:
608*593dc095SDavid du Colombier strm->next_in = next;
609*593dc095SDavid du Colombier strm->avail_in = have;
610*593dc095SDavid du Colombier return ret;
611*593dc095SDavid du Colombier }
612*593dc095SDavid du Colombier
inflateBackEnd(strm)613*593dc095SDavid du Colombier int ZEXPORT inflateBackEnd(strm)
614*593dc095SDavid du Colombier z_stream FAR *strm;
615*593dc095SDavid du Colombier {
616*593dc095SDavid du Colombier if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
617*593dc095SDavid du Colombier return Z_STREAM_ERROR;
618*593dc095SDavid du Colombier ZFREE(strm, strm->state);
619*593dc095SDavid du Colombier strm->state = Z_NULL;
620*593dc095SDavid du Colombier Tracev((stderr, "inflate: end\n"));
621*593dc095SDavid du Colombier return Z_OK;
622*593dc095SDavid du Colombier }
623