File: /usr/src/linux/fs/cramfs/inflate/infcodes.c

1     /* infcodes.c -- process literals and length/distance pairs
2      * Copyright (C) 1995-1998 Mark Adler
3      * For conditions of distribution and use, see copyright notice in zlib.h 
4      */
5     
6     #include "zutil.h"
7     #include "inftrees.h"
8     #include "infblock.h"
9     #include "infcodes.h"
10     #include "infutil.h"
11     #include "inffast.h"
12     
13     /* simplify the use of the inflate_huft type with some defines */
14     #define exop word.what.Exop
15     #define bits word.what.Bits
16     
17     typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
18           START,    /* x: set up for LEN */
19           LEN,      /* i: get length/literal/eob next */
20           LENEXT,   /* i: getting length extra (have base) */
21           DIST,     /* i: get distance next */
22           DISTEXT,  /* i: getting distance extra */
23           COPY,     /* o: copying bytes in window, waiting for space */
24           LIT,      /* o: got literal, waiting for output space */
25           WASH,     /* o: got eob, possibly still output waiting */
26           END,      /* x: got eob and all data flushed */
27           BADCODE}  /* x: got error */
28     inflate_codes_mode;
29     
30     /* inflate codes private state */
31     struct inflate_codes_state {
32     
33       /* mode */
34       inflate_codes_mode mode;      /* current inflate_codes mode */
35     
36       /* mode dependent information */
37       uInt len;
38       union {
39         struct {
40           inflate_huft *tree;       /* pointer into tree */
41           uInt need;                /* bits needed */
42         } code;             /* if LEN or DIST, where in tree */
43         uInt lit;           /* if LIT, literal */
44         struct {
45           uInt get;                 /* bits to get for extra */
46           uInt dist;                /* distance back to copy from */
47         } copy;             /* if EXT or COPY, where and how much */
48       } sub;                /* submode */
49     
50       /* mode independent information */
51       Byte lbits;           /* ltree bits decoded per branch */
52       Byte dbits;           /* dtree bits decoder per branch */
53       inflate_huft *ltree;          /* literal/length/eob tree */
54       inflate_huft *dtree;          /* distance tree */
55     
56     };
57     
58     
59     inflate_codes_statef *cramfs_inflate_codes_new(bl, bd, tl, td, z)
60     uInt bl, bd;
61     inflate_huft *tl;
62     inflate_huft *td; /* need separate declaration for Borland C++ */
63     z_streamp z;
64     {
65       inflate_codes_statef *c;
66       static inflate_codes_statef memory_allocation;
67     
68       c = &memory_allocation;
69       {
70         c->mode = START;
71         c->lbits = (Byte)bl;
72         c->dbits = (Byte)bd;
73         c->ltree = tl;
74         c->dtree = td;
75       }
76       return c;
77     }
78     
79     
80     int cramfs_inflate_codes(s, z, r)
81     inflate_blocks_statef *s;
82     z_streamp z;
83     int r;
84     {
85       uInt j;               /* temporary storage */
86       inflate_huft *t;      /* temporary pointer */
87       uInt e;               /* extra bits or operation */
88       uLong b;              /* bit buffer */
89       uInt k;               /* bits in bit buffer */
90       Bytef *p;             /* input data pointer */
91       uInt n;               /* bytes available there */
92       Bytef *q;             /* output window write pointer */
93       uInt m;               /* bytes to end of window or read pointer */
94       Bytef *f;             /* pointer to copy strings from */
95       inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
96     
97       /* copy input/output information to locals (UPDATE macro restores) */
98       LOAD
99     
100       /* process input and output based on current state */
101       while (1) switch (c->mode)
102       {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
103         case START:         /* x: set up for LEN */
104     #ifndef SLOW
105           if (m >= 258 && n >= 10)
106           {
107             UPDATE
108             r = cramfs_inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
109             LOAD
110             if (r != Z_OK)
111             {
112               c->mode = r == Z_STREAM_END ? WASH : BADCODE;
113               break;
114             }
115           }
116     #endif /* !SLOW */
117           c->sub.code.need = c->lbits;
118           c->sub.code.tree = c->ltree;
119           c->mode = LEN;
120         case LEN:           /* i: get length/literal/eob next */
121           j = c->sub.code.need;
122           NEEDBITS(j)
123           t = c->sub.code.tree + ((uInt)b & cramfs_inflate_mask[j]);
124           DUMPBITS(t->bits)
125           e = (uInt)(t->exop);
126           if (e == 0)               /* literal */
127           {
128             c->sub.lit = t->base;
129             c->mode = LIT;
130             break;
131           }
132           if (e & 16)               /* length */
133           {
134             c->sub.copy.get = e & 15;
135             c->len = t->base;
136             c->mode = LENEXT;
137             break;
138           }
139           if ((e & 64) == 0)        /* next table */
140           {
141             c->sub.code.need = e;
142             c->sub.code.tree = t + t->base;
143             break;
144           }
145           if (e & 32)               /* end of block */
146           {
147             c->mode = WASH;
148             break;
149           }
150           c->mode = BADCODE;        /* invalid code */
151           z->msg = (char*)"invalid literal/length code";
152           r = Z_DATA_ERROR;
153           LEAVE
154         case LENEXT:        /* i: getting length extra (have base) */
155           j = c->sub.copy.get;
156           NEEDBITS(j)
157           c->len += (uInt)b & cramfs_inflate_mask[j];
158           DUMPBITS(j)
159           c->sub.code.need = c->dbits;
160           c->sub.code.tree = c->dtree;
161           c->mode = DIST;
162         case DIST:          /* i: get distance next */
163           j = c->sub.code.need;
164           NEEDBITS(j)
165           t = c->sub.code.tree + ((uInt)b & cramfs_inflate_mask[j]);
166           DUMPBITS(t->bits)
167           e = (uInt)(t->exop);
168           if (e & 16)               /* distance */
169           {
170             c->sub.copy.get = e & 15;
171             c->sub.copy.dist = t->base;
172             c->mode = DISTEXT;
173             break;
174           }
175           if ((e & 64) == 0)        /* next table */
176           {
177             c->sub.code.need = e;
178             c->sub.code.tree = t + t->base;
179             break;
180           }
181           c->mode = BADCODE;        /* invalid code */
182           z->msg = (char*)"invalid distance code";
183           r = Z_DATA_ERROR;
184           LEAVE
185         case DISTEXT:       /* i: getting distance extra */
186           j = c->sub.copy.get;
187           NEEDBITS(j)
188           c->sub.copy.dist += (uInt)b & cramfs_inflate_mask[j];
189           DUMPBITS(j)
190           c->mode = COPY;
191         case COPY:          /* o: copying bytes in window, waiting for space */
192     #ifndef __TURBOC__ /* Turbo C bug for following expression */
193           f = (uInt)(q - s->window) < c->sub.copy.dist ?
194               s->end - (c->sub.copy.dist - (q - s->window)) :
195               q - c->sub.copy.dist;
196     #else
197           f = q - c->sub.copy.dist;
198           if ((uInt)(q - s->window) < c->sub.copy.dist)
199             f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
200     #endif
201           while (c->len)
202           {
203             NEEDOUT
204             OUTBYTE(*f++)
205             if (f == s->end)
206               f = s->window;
207             c->len--;
208           }
209           c->mode = START;
210           break;
211         case LIT:           /* o: got literal, waiting for output space */
212           NEEDOUT
213           OUTBYTE(c->sub.lit)
214           c->mode = START;
215           break;
216         case WASH:          /* o: got eob, possibly more output */
217           if (k > 7)        /* return unused byte, if any */
218           {
219             k -= 8;
220             n++;
221             p--;            /* can always return one */
222           }
223           FLUSH
224           if (s->read != s->write)
225             LEAVE
226           c->mode = END;
227         case END:
228           r = Z_STREAM_END;
229           LEAVE
230         case BADCODE:       /* x: got error */
231           r = Z_DATA_ERROR;
232           LEAVE
233         default:
234           r = Z_STREAM_ERROR;
235           LEAVE
236       }
237     #ifdef NEED_DUMMY_RETURN
238       return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
239     #endif
240     }
241     
242     
243     void cramfs_inflate_codes_free(c, z)
244     inflate_codes_statef *c;
245     z_streamp z;
246     {
247     }
248