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