xref: /plan9/sys/src/cmd/bzip2/lib/decompress.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
1*59cc4ca5SDavid du Colombier 
2*59cc4ca5SDavid du Colombier /*-------------------------------------------------------------*/
3*59cc4ca5SDavid du Colombier /*--- Decompression machinery                               ---*/
4*59cc4ca5SDavid du Colombier /*---                                          decompress.c ---*/
5*59cc4ca5SDavid du Colombier /*-------------------------------------------------------------*/
6*59cc4ca5SDavid du Colombier 
7*59cc4ca5SDavid du Colombier /*--
8*59cc4ca5SDavid du Colombier   This file is a part of bzip2 and/or libbzip2, a program and
9*59cc4ca5SDavid du Colombier   library for lossless, block-sorting data compression.
10*59cc4ca5SDavid du Colombier 
11*59cc4ca5SDavid du Colombier   Copyright (C) 1996-2000 Julian R Seward.  All rights reserved.
12*59cc4ca5SDavid du Colombier 
13*59cc4ca5SDavid du Colombier   Redistribution and use in source and binary forms, with or without
14*59cc4ca5SDavid du Colombier   modification, are permitted provided that the following conditions
15*59cc4ca5SDavid du Colombier   are met:
16*59cc4ca5SDavid du Colombier 
17*59cc4ca5SDavid du Colombier   1. Redistributions of source code must retain the above copyright
18*59cc4ca5SDavid du Colombier      notice, this list of conditions and the following disclaimer.
19*59cc4ca5SDavid du Colombier 
20*59cc4ca5SDavid du Colombier   2. The origin of this software must not be misrepresented; you must
21*59cc4ca5SDavid du Colombier      not claim that you wrote the original software.  If you use this
22*59cc4ca5SDavid du Colombier      software in a product, an acknowledgment in the product
23*59cc4ca5SDavid du Colombier      documentation would be appreciated but is not required.
24*59cc4ca5SDavid du Colombier 
25*59cc4ca5SDavid du Colombier   3. Altered source versions must be plainly marked as such, and must
26*59cc4ca5SDavid du Colombier      not be misrepresented as being the original software.
27*59cc4ca5SDavid du Colombier 
28*59cc4ca5SDavid du Colombier   4. The name of the author may not be used to endorse or promote
29*59cc4ca5SDavid du Colombier      products derived from this software without specific prior written
30*59cc4ca5SDavid du Colombier      permission.
31*59cc4ca5SDavid du Colombier 
32*59cc4ca5SDavid du Colombier   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
33*59cc4ca5SDavid du Colombier   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34*59cc4ca5SDavid du Colombier   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35*59cc4ca5SDavid du Colombier   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
36*59cc4ca5SDavid du Colombier   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37*59cc4ca5SDavid du Colombier   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38*59cc4ca5SDavid du Colombier   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39*59cc4ca5SDavid du Colombier   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40*59cc4ca5SDavid du Colombier   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41*59cc4ca5SDavid du Colombier   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42*59cc4ca5SDavid du Colombier   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43*59cc4ca5SDavid du Colombier 
44*59cc4ca5SDavid du Colombier   Julian Seward, Cambridge, UK.
45*59cc4ca5SDavid du Colombier   jseward@acm.org
46*59cc4ca5SDavid du Colombier   bzip2/libbzip2 version 1.0 of 21 March 2000
47*59cc4ca5SDavid du Colombier 
48*59cc4ca5SDavid du Colombier   This program is based on (at least) the work of:
49*59cc4ca5SDavid du Colombier      Mike Burrows
50*59cc4ca5SDavid du Colombier      David Wheeler
51*59cc4ca5SDavid du Colombier      Peter Fenwick
52*59cc4ca5SDavid du Colombier      Alistair Moffat
53*59cc4ca5SDavid du Colombier      Radford Neal
54*59cc4ca5SDavid du Colombier      Ian H. Witten
55*59cc4ca5SDavid du Colombier      Robert Sedgewick
56*59cc4ca5SDavid du Colombier      Jon L. Bentley
57*59cc4ca5SDavid du Colombier 
58*59cc4ca5SDavid du Colombier   For more information on these sources, see the manual.
59*59cc4ca5SDavid du Colombier --*/
60*59cc4ca5SDavid du Colombier 
61*59cc4ca5SDavid du Colombier 
62*59cc4ca5SDavid du Colombier #include "os.h"
63*59cc4ca5SDavid du Colombier #include "bzlib.h"
64*59cc4ca5SDavid du Colombier #include "bzlib_private.h"
65*59cc4ca5SDavid du Colombier 
66*59cc4ca5SDavid du Colombier 
67*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
68*59cc4ca5SDavid du Colombier static
makeMaps_d(DState * s)69*59cc4ca5SDavid du Colombier void makeMaps_d ( DState* s )
70*59cc4ca5SDavid du Colombier {
71*59cc4ca5SDavid du Colombier    Int32 i;
72*59cc4ca5SDavid du Colombier    s->nInUse = 0;
73*59cc4ca5SDavid du Colombier    for (i = 0; i < 256; i++)
74*59cc4ca5SDavid du Colombier       if (s->inUse[i]) {
75*59cc4ca5SDavid du Colombier          s->seqToUnseq[s->nInUse] = i;
76*59cc4ca5SDavid du Colombier          s->nInUse++;
77*59cc4ca5SDavid du Colombier       }
78*59cc4ca5SDavid du Colombier }
79*59cc4ca5SDavid du Colombier 
80*59cc4ca5SDavid du Colombier 
81*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
82*59cc4ca5SDavid du Colombier #define RETURN(rrr)                               \
83*59cc4ca5SDavid du Colombier    { retVal = rrr; goto save_state_and_return; };
84*59cc4ca5SDavid du Colombier 
85*59cc4ca5SDavid du Colombier #define GET_BITS(lll,vvv,nnn)                     \
86*59cc4ca5SDavid du Colombier    case lll: s->state = lll;                      \
87*59cc4ca5SDavid du Colombier    while (True) {                                 \
88*59cc4ca5SDavid du Colombier       if (s->bsLive >= nnn) {                     \
89*59cc4ca5SDavid du Colombier          UInt32 v;                                \
90*59cc4ca5SDavid du Colombier          v = (s->bsBuff >>                        \
91*59cc4ca5SDavid du Colombier              (s->bsLive-nnn)) & ((1 << nnn)-1);   \
92*59cc4ca5SDavid du Colombier          s->bsLive -= nnn;                        \
93*59cc4ca5SDavid du Colombier          vvv = v;                                 \
94*59cc4ca5SDavid du Colombier          break;                                   \
95*59cc4ca5SDavid du Colombier       }                                           \
96*59cc4ca5SDavid du Colombier       if (s->strm->avail_in == 0) RETURN(BZ_OK);  \
97*59cc4ca5SDavid du Colombier       s->bsBuff                                   \
98*59cc4ca5SDavid du Colombier          = (s->bsBuff << 8) |                     \
99*59cc4ca5SDavid du Colombier            ((UInt32)                              \
100*59cc4ca5SDavid du Colombier               (*((UChar*)(s->strm->next_in))));   \
101*59cc4ca5SDavid du Colombier       s->bsLive += 8;                             \
102*59cc4ca5SDavid du Colombier       s->strm->next_in++;                         \
103*59cc4ca5SDavid du Colombier       s->strm->avail_in--;                        \
104*59cc4ca5SDavid du Colombier       s->strm->total_in_lo32++;                   \
105*59cc4ca5SDavid du Colombier       if (s->strm->total_in_lo32 == 0)            \
106*59cc4ca5SDavid du Colombier          s->strm->total_in_hi32++;                \
107*59cc4ca5SDavid du Colombier    }
108*59cc4ca5SDavid du Colombier 
109*59cc4ca5SDavid du Colombier #define GET_UCHAR(lll,uuu)                        \
110*59cc4ca5SDavid du Colombier    GET_BITS(lll,uuu,8)
111*59cc4ca5SDavid du Colombier 
112*59cc4ca5SDavid du Colombier #define GET_BIT(lll,uuu)                          \
113*59cc4ca5SDavid du Colombier    GET_BITS(lll,uuu,1)
114*59cc4ca5SDavid du Colombier 
115*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
116*59cc4ca5SDavid du Colombier #define GET_MTF_VAL(label1,label2,lval)           \
117*59cc4ca5SDavid du Colombier {                                                 \
118*59cc4ca5SDavid du Colombier    if (groupPos == 0) {                           \
119*59cc4ca5SDavid du Colombier       groupNo++;                                  \
120*59cc4ca5SDavid du Colombier       if (groupNo >= nSelectors)                  \
121*59cc4ca5SDavid du Colombier          RETURN(BZ_DATA_ERROR);                   \
122*59cc4ca5SDavid du Colombier       groupPos = BZ_G_SIZE;                       \
123*59cc4ca5SDavid du Colombier       gSel = s->selector[groupNo];                \
124*59cc4ca5SDavid du Colombier       gMinlen = s->minLens[gSel];                 \
125*59cc4ca5SDavid du Colombier       gLimit = &(s->limit[gSel][0]);              \
126*59cc4ca5SDavid du Colombier       gPerm = &(s->perm[gSel][0]);                \
127*59cc4ca5SDavid du Colombier       gBase = &(s->base[gSel][0]);                \
128*59cc4ca5SDavid du Colombier    }                                              \
129*59cc4ca5SDavid du Colombier    groupPos--;                                    \
130*59cc4ca5SDavid du Colombier    zn = gMinlen;                                  \
131*59cc4ca5SDavid du Colombier    GET_BITS(label1, zvec, zn);                    \
132*59cc4ca5SDavid du Colombier    while (1) {                                    \
133*59cc4ca5SDavid du Colombier       if (zn > 20 /* the longest code */)         \
134*59cc4ca5SDavid du Colombier          RETURN(BZ_DATA_ERROR);                   \
135*59cc4ca5SDavid du Colombier       if (zvec <= gLimit[zn]) break;              \
136*59cc4ca5SDavid du Colombier       zn++;                                       \
137*59cc4ca5SDavid du Colombier       GET_BIT(label2, zj);                        \
138*59cc4ca5SDavid du Colombier       zvec = (zvec << 1) | zj;                    \
139*59cc4ca5SDavid du Colombier    };                                             \
140*59cc4ca5SDavid du Colombier    if (zvec - gBase[zn] < 0                       \
141*59cc4ca5SDavid du Colombier        || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE)  \
142*59cc4ca5SDavid du Colombier       RETURN(BZ_DATA_ERROR);                      \
143*59cc4ca5SDavid du Colombier    lval = gPerm[zvec - gBase[zn]];                \
144*59cc4ca5SDavid du Colombier }
145*59cc4ca5SDavid du Colombier 
146*59cc4ca5SDavid du Colombier 
147*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ2_decompress(DState * s)148*59cc4ca5SDavid du Colombier Int32 BZ2_decompress ( DState* s )
149*59cc4ca5SDavid du Colombier {
150*59cc4ca5SDavid du Colombier    UChar      uc;
151*59cc4ca5SDavid du Colombier    Int32      retVal;
152*59cc4ca5SDavid du Colombier    Int32      minLen, maxLen;
153*59cc4ca5SDavid du Colombier    bz_stream* strm = s->strm;
154*59cc4ca5SDavid du Colombier 
155*59cc4ca5SDavid du Colombier    /* stuff that needs to be saved/restored */
156*59cc4ca5SDavid du Colombier    Int32  i;
157*59cc4ca5SDavid du Colombier    Int32  j;
158*59cc4ca5SDavid du Colombier    Int32  t;
159*59cc4ca5SDavid du Colombier    Int32  alphaSize;
160*59cc4ca5SDavid du Colombier    Int32  nGroups;
161*59cc4ca5SDavid du Colombier    Int32  nSelectors;
162*59cc4ca5SDavid du Colombier    Int32  EOB;
163*59cc4ca5SDavid du Colombier    Int32  groupNo;
164*59cc4ca5SDavid du Colombier    Int32  groupPos;
165*59cc4ca5SDavid du Colombier    Int32  nextSym;
166*59cc4ca5SDavid du Colombier    Int32  nblockMAX;
167*59cc4ca5SDavid du Colombier    Int32  nblock;
168*59cc4ca5SDavid du Colombier    Int32  es;
169*59cc4ca5SDavid du Colombier    Int32  N;
170*59cc4ca5SDavid du Colombier    Int32  curr;
171*59cc4ca5SDavid du Colombier    Int32  zt;
172*59cc4ca5SDavid du Colombier    Int32  zn;
173*59cc4ca5SDavid du Colombier    Int32  zvec;
174*59cc4ca5SDavid du Colombier    Int32  zj;
175*59cc4ca5SDavid du Colombier    Int32  gSel;
176*59cc4ca5SDavid du Colombier    Int32  gMinlen;
177*59cc4ca5SDavid du Colombier    Int32* gLimit;
178*59cc4ca5SDavid du Colombier    Int32* gBase;
179*59cc4ca5SDavid du Colombier    Int32* gPerm;
180*59cc4ca5SDavid du Colombier 
181*59cc4ca5SDavid du Colombier    if (s->state == BZ_X_MAGIC_1) {
182*59cc4ca5SDavid du Colombier       /*initialise the save area*/
183*59cc4ca5SDavid du Colombier       s->save_i           = 0;
184*59cc4ca5SDavid du Colombier       s->save_j           = 0;
185*59cc4ca5SDavid du Colombier       s->save_t           = 0;
186*59cc4ca5SDavid du Colombier       s->save_alphaSize   = 0;
187*59cc4ca5SDavid du Colombier       s->save_nGroups     = 0;
188*59cc4ca5SDavid du Colombier       s->save_nSelectors  = 0;
189*59cc4ca5SDavid du Colombier       s->save_EOB         = 0;
190*59cc4ca5SDavid du Colombier       s->save_groupNo     = 0;
191*59cc4ca5SDavid du Colombier       s->save_groupPos    = 0;
192*59cc4ca5SDavid du Colombier       s->save_nextSym     = 0;
193*59cc4ca5SDavid du Colombier       s->save_nblockMAX   = 0;
194*59cc4ca5SDavid du Colombier       s->save_nblock      = 0;
195*59cc4ca5SDavid du Colombier       s->save_es          = 0;
196*59cc4ca5SDavid du Colombier       s->save_N           = 0;
197*59cc4ca5SDavid du Colombier       s->save_curr        = 0;
198*59cc4ca5SDavid du Colombier       s->save_zt          = 0;
199*59cc4ca5SDavid du Colombier       s->save_zn          = 0;
200*59cc4ca5SDavid du Colombier       s->save_zvec        = 0;
201*59cc4ca5SDavid du Colombier       s->save_zj          = 0;
202*59cc4ca5SDavid du Colombier       s->save_gSel        = 0;
203*59cc4ca5SDavid du Colombier       s->save_gMinlen     = 0;
204*59cc4ca5SDavid du Colombier       s->save_gLimit      = NULL;
205*59cc4ca5SDavid du Colombier       s->save_gBase       = NULL;
206*59cc4ca5SDavid du Colombier       s->save_gPerm       = NULL;
207*59cc4ca5SDavid du Colombier    }
208*59cc4ca5SDavid du Colombier 
209*59cc4ca5SDavid du Colombier    /*restore from the save area*/
210*59cc4ca5SDavid du Colombier    i           = s->save_i;
211*59cc4ca5SDavid du Colombier    j           = s->save_j;
212*59cc4ca5SDavid du Colombier    t           = s->save_t;
213*59cc4ca5SDavid du Colombier    alphaSize   = s->save_alphaSize;
214*59cc4ca5SDavid du Colombier    nGroups     = s->save_nGroups;
215*59cc4ca5SDavid du Colombier    nSelectors  = s->save_nSelectors;
216*59cc4ca5SDavid du Colombier    EOB         = s->save_EOB;
217*59cc4ca5SDavid du Colombier    groupNo     = s->save_groupNo;
218*59cc4ca5SDavid du Colombier    groupPos    = s->save_groupPos;
219*59cc4ca5SDavid du Colombier    nextSym     = s->save_nextSym;
220*59cc4ca5SDavid du Colombier    nblockMAX   = s->save_nblockMAX;
221*59cc4ca5SDavid du Colombier    nblock      = s->save_nblock;
222*59cc4ca5SDavid du Colombier    es          = s->save_es;
223*59cc4ca5SDavid du Colombier    N           = s->save_N;
224*59cc4ca5SDavid du Colombier    curr        = s->save_curr;
225*59cc4ca5SDavid du Colombier    zt          = s->save_zt;
226*59cc4ca5SDavid du Colombier    zn          = s->save_zn;
227*59cc4ca5SDavid du Colombier    zvec        = s->save_zvec;
228*59cc4ca5SDavid du Colombier    zj          = s->save_zj;
229*59cc4ca5SDavid du Colombier    gSel        = s->save_gSel;
230*59cc4ca5SDavid du Colombier    gMinlen     = s->save_gMinlen;
231*59cc4ca5SDavid du Colombier    gLimit      = s->save_gLimit;
232*59cc4ca5SDavid du Colombier    gBase       = s->save_gBase;
233*59cc4ca5SDavid du Colombier    gPerm       = s->save_gPerm;
234*59cc4ca5SDavid du Colombier 
235*59cc4ca5SDavid du Colombier    retVal = BZ_OK;
236*59cc4ca5SDavid du Colombier 
237*59cc4ca5SDavid du Colombier    switch (s->state) {
238*59cc4ca5SDavid du Colombier 
239*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_MAGIC_1, uc);
240*59cc4ca5SDavid du Colombier       if (uc != 'B') RETURN(BZ_DATA_ERROR_MAGIC);
241*59cc4ca5SDavid du Colombier 
242*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_MAGIC_2, uc);
243*59cc4ca5SDavid du Colombier       if (uc != 'Z') RETURN(BZ_DATA_ERROR_MAGIC);
244*59cc4ca5SDavid du Colombier 
245*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_MAGIC_3, uc)
246*59cc4ca5SDavid du Colombier       if (uc != 'h') RETURN(BZ_DATA_ERROR_MAGIC);
247*59cc4ca5SDavid du Colombier 
248*59cc4ca5SDavid du Colombier       GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
249*59cc4ca5SDavid du Colombier       if (s->blockSize100k < '1' ||
250*59cc4ca5SDavid du Colombier           s->blockSize100k > '9') RETURN(BZ_DATA_ERROR_MAGIC);
251*59cc4ca5SDavid du Colombier       s->blockSize100k -= '0';
252*59cc4ca5SDavid du Colombier 
253*59cc4ca5SDavid du Colombier       if (s->smallDecompress) {
254*59cc4ca5SDavid du Colombier          s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
255*59cc4ca5SDavid du Colombier          s->ll4  = BZALLOC(
256*59cc4ca5SDavid du Colombier                       ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar)
257*59cc4ca5SDavid du Colombier                    );
258*59cc4ca5SDavid du Colombier          if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
259*59cc4ca5SDavid du Colombier       } else {
260*59cc4ca5SDavid du Colombier          s->tt  = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
261*59cc4ca5SDavid du Colombier          if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
262*59cc4ca5SDavid du Colombier       }
263*59cc4ca5SDavid du Colombier 
264*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_1, uc);
265*59cc4ca5SDavid du Colombier 
266*59cc4ca5SDavid du Colombier       if (uc == 0x17) goto endhdr_2;
267*59cc4ca5SDavid du Colombier       if (uc != 0x31) RETURN(BZ_DATA_ERROR);
268*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_2, uc);
269*59cc4ca5SDavid du Colombier       if (uc != 0x41) RETURN(BZ_DATA_ERROR);
270*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_3, uc);
271*59cc4ca5SDavid du Colombier       if (uc != 0x59) RETURN(BZ_DATA_ERROR);
272*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_4, uc);
273*59cc4ca5SDavid du Colombier       if (uc != 0x26) RETURN(BZ_DATA_ERROR);
274*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_5, uc);
275*59cc4ca5SDavid du Colombier       if (uc != 0x53) RETURN(BZ_DATA_ERROR);
276*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_6, uc);
277*59cc4ca5SDavid du Colombier       if (uc != 0x59) RETURN(BZ_DATA_ERROR);
278*59cc4ca5SDavid du Colombier 
279*59cc4ca5SDavid du Colombier       s->currBlockNo++;
280*59cc4ca5SDavid du Colombier       if (s->verbosity >= 2)
281*59cc4ca5SDavid du Colombier          VPrintf1 ( "\n    [%d: huff+mtf ", s->currBlockNo );
282*59cc4ca5SDavid du Colombier 
283*59cc4ca5SDavid du Colombier       s->storedBlockCRC = 0;
284*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_BCRC_1, uc);
285*59cc4ca5SDavid du Colombier       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
286*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_BCRC_2, uc);
287*59cc4ca5SDavid du Colombier       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
288*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_BCRC_3, uc);
289*59cc4ca5SDavid du Colombier       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
290*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_BCRC_4, uc);
291*59cc4ca5SDavid du Colombier       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
292*59cc4ca5SDavid du Colombier 
293*59cc4ca5SDavid du Colombier       GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
294*59cc4ca5SDavid du Colombier 
295*59cc4ca5SDavid du Colombier       s->origPtr = 0;
296*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_ORIGPTR_1, uc);
297*59cc4ca5SDavid du Colombier       s->origPtr = (s->origPtr << 8) | ((Int32)uc);
298*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_ORIGPTR_2, uc);
299*59cc4ca5SDavid du Colombier       s->origPtr = (s->origPtr << 8) | ((Int32)uc);
300*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_ORIGPTR_3, uc);
301*59cc4ca5SDavid du Colombier       s->origPtr = (s->origPtr << 8) | ((Int32)uc);
302*59cc4ca5SDavid du Colombier 
303*59cc4ca5SDavid du Colombier       if (s->origPtr < 0)
304*59cc4ca5SDavid du Colombier          RETURN(BZ_DATA_ERROR);
305*59cc4ca5SDavid du Colombier       if (s->origPtr > 10 + 100000*s->blockSize100k)
306*59cc4ca5SDavid du Colombier          RETURN(BZ_DATA_ERROR);
307*59cc4ca5SDavid du Colombier 
308*59cc4ca5SDavid du Colombier       /*--- Receive the mapping table ---*/
309*59cc4ca5SDavid du Colombier       for (i = 0; i < 16; i++) {
310*59cc4ca5SDavid du Colombier          GET_BIT(BZ_X_MAPPING_1, uc);
311*59cc4ca5SDavid du Colombier          if (uc == 1)
312*59cc4ca5SDavid du Colombier             s->inUse16[i] = True; else
313*59cc4ca5SDavid du Colombier             s->inUse16[i] = False;
314*59cc4ca5SDavid du Colombier       }
315*59cc4ca5SDavid du Colombier 
316*59cc4ca5SDavid du Colombier       for (i = 0; i < 256; i++) s->inUse[i] = False;
317*59cc4ca5SDavid du Colombier 
318*59cc4ca5SDavid du Colombier       for (i = 0; i < 16; i++)
319*59cc4ca5SDavid du Colombier          if (s->inUse16[i])
320*59cc4ca5SDavid du Colombier             for (j = 0; j < 16; j++) {
321*59cc4ca5SDavid du Colombier                GET_BIT(BZ_X_MAPPING_2, uc);
322*59cc4ca5SDavid du Colombier                if (uc == 1) s->inUse[i * 16 + j] = True;
323*59cc4ca5SDavid du Colombier             }
324*59cc4ca5SDavid du Colombier       makeMaps_d ( s );
325*59cc4ca5SDavid du Colombier       if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
326*59cc4ca5SDavid du Colombier       alphaSize = s->nInUse+2;
327*59cc4ca5SDavid du Colombier 
328*59cc4ca5SDavid du Colombier       /*--- Now the selectors ---*/
329*59cc4ca5SDavid du Colombier       GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
330*59cc4ca5SDavid du Colombier       if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
331*59cc4ca5SDavid du Colombier       GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
332*59cc4ca5SDavid du Colombier       if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
333*59cc4ca5SDavid du Colombier       for (i = 0; i < nSelectors; i++) {
334*59cc4ca5SDavid du Colombier          j = 0;
335*59cc4ca5SDavid du Colombier          while (True) {
336*59cc4ca5SDavid du Colombier             GET_BIT(BZ_X_SELECTOR_3, uc);
337*59cc4ca5SDavid du Colombier             if (uc == 0) break;
338*59cc4ca5SDavid du Colombier             j++;
339*59cc4ca5SDavid du Colombier             if (j >= nGroups) RETURN(BZ_DATA_ERROR);
340*59cc4ca5SDavid du Colombier          }
341*59cc4ca5SDavid du Colombier          s->selectorMtf[i] = j;
342*59cc4ca5SDavid du Colombier       }
343*59cc4ca5SDavid du Colombier 
344*59cc4ca5SDavid du Colombier       /*--- Undo the MTF values for the selectors. ---*/
345*59cc4ca5SDavid du Colombier       {
346*59cc4ca5SDavid du Colombier          UChar pos[BZ_N_GROUPS], tmp, v;
347*59cc4ca5SDavid du Colombier          for (v = 0; v < nGroups; v++) pos[v] = v;
348*59cc4ca5SDavid du Colombier 
349*59cc4ca5SDavid du Colombier          for (i = 0; i < nSelectors; i++) {
350*59cc4ca5SDavid du Colombier             v = s->selectorMtf[i];
351*59cc4ca5SDavid du Colombier             tmp = pos[v];
352*59cc4ca5SDavid du Colombier             while (v > 0) { pos[v] = pos[v-1]; v--; }
353*59cc4ca5SDavid du Colombier             pos[0] = tmp;
354*59cc4ca5SDavid du Colombier             s->selector[i] = tmp;
355*59cc4ca5SDavid du Colombier          }
356*59cc4ca5SDavid du Colombier       }
357*59cc4ca5SDavid du Colombier 
358*59cc4ca5SDavid du Colombier       /*--- Now the coding tables ---*/
359*59cc4ca5SDavid du Colombier       for (t = 0; t < nGroups; t++) {
360*59cc4ca5SDavid du Colombier          GET_BITS(BZ_X_CODING_1, curr, 5);
361*59cc4ca5SDavid du Colombier          for (i = 0; i < alphaSize; i++) {
362*59cc4ca5SDavid du Colombier             while (True) {
363*59cc4ca5SDavid du Colombier                if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
364*59cc4ca5SDavid du Colombier                GET_BIT(BZ_X_CODING_2, uc);
365*59cc4ca5SDavid du Colombier                if (uc == 0) break;
366*59cc4ca5SDavid du Colombier                GET_BIT(BZ_X_CODING_3, uc);
367*59cc4ca5SDavid du Colombier                if (uc == 0) curr++; else curr--;
368*59cc4ca5SDavid du Colombier             }
369*59cc4ca5SDavid du Colombier             s->len[t][i] = curr;
370*59cc4ca5SDavid du Colombier          }
371*59cc4ca5SDavid du Colombier       }
372*59cc4ca5SDavid du Colombier 
373*59cc4ca5SDavid du Colombier       /*--- Create the Huffman decoding tables ---*/
374*59cc4ca5SDavid du Colombier       for (t = 0; t < nGroups; t++) {
375*59cc4ca5SDavid du Colombier          minLen = 32;
376*59cc4ca5SDavid du Colombier          maxLen = 0;
377*59cc4ca5SDavid du Colombier          for (i = 0; i < alphaSize; i++) {
378*59cc4ca5SDavid du Colombier             if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
379*59cc4ca5SDavid du Colombier             if (s->len[t][i] < minLen) minLen = s->len[t][i];
380*59cc4ca5SDavid du Colombier          }
381*59cc4ca5SDavid du Colombier          BZ2_hbCreateDecodeTables (
382*59cc4ca5SDavid du Colombier             &(s->limit[t][0]),
383*59cc4ca5SDavid du Colombier             &(s->base[t][0]),
384*59cc4ca5SDavid du Colombier             &(s->perm[t][0]),
385*59cc4ca5SDavid du Colombier             &(s->len[t][0]),
386*59cc4ca5SDavid du Colombier             minLen, maxLen, alphaSize
387*59cc4ca5SDavid du Colombier          );
388*59cc4ca5SDavid du Colombier          s->minLens[t] = minLen;
389*59cc4ca5SDavid du Colombier       }
390*59cc4ca5SDavid du Colombier 
391*59cc4ca5SDavid du Colombier       /*--- Now the MTF values ---*/
392*59cc4ca5SDavid du Colombier 
393*59cc4ca5SDavid du Colombier       EOB      = s->nInUse+1;
394*59cc4ca5SDavid du Colombier       nblockMAX = 100000 * s->blockSize100k;
395*59cc4ca5SDavid du Colombier       groupNo  = -1;
396*59cc4ca5SDavid du Colombier       groupPos = 0;
397*59cc4ca5SDavid du Colombier 
398*59cc4ca5SDavid du Colombier       for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
399*59cc4ca5SDavid du Colombier 
400*59cc4ca5SDavid du Colombier       /*-- MTF init --*/
401*59cc4ca5SDavid du Colombier       {
402*59cc4ca5SDavid du Colombier          Int32 ii, jj, kk;
403*59cc4ca5SDavid du Colombier          kk = MTFA_SIZE-1;
404*59cc4ca5SDavid du Colombier          for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
405*59cc4ca5SDavid du Colombier             for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
406*59cc4ca5SDavid du Colombier                s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
407*59cc4ca5SDavid du Colombier                kk--;
408*59cc4ca5SDavid du Colombier             }
409*59cc4ca5SDavid du Colombier             s->mtfbase[ii] = kk + 1;
410*59cc4ca5SDavid du Colombier          }
411*59cc4ca5SDavid du Colombier       }
412*59cc4ca5SDavid du Colombier       /*-- end MTF init --*/
413*59cc4ca5SDavid du Colombier 
414*59cc4ca5SDavid du Colombier       nblock = 0;
415*59cc4ca5SDavid du Colombier       GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
416*59cc4ca5SDavid du Colombier 
417*59cc4ca5SDavid du Colombier       while (True) {
418*59cc4ca5SDavid du Colombier 
419*59cc4ca5SDavid du Colombier          if (nextSym == EOB) break;
420*59cc4ca5SDavid du Colombier 
421*59cc4ca5SDavid du Colombier          if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
422*59cc4ca5SDavid du Colombier 
423*59cc4ca5SDavid du Colombier             es = -1;
424*59cc4ca5SDavid du Colombier             N = 1;
425*59cc4ca5SDavid du Colombier             do {
426*59cc4ca5SDavid du Colombier                if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
427*59cc4ca5SDavid du Colombier                if (nextSym == BZ_RUNB) es = es + (1+1) * N;
428*59cc4ca5SDavid du Colombier                N = N * 2;
429*59cc4ca5SDavid du Colombier                GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
430*59cc4ca5SDavid du Colombier             }
431*59cc4ca5SDavid du Colombier                while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
432*59cc4ca5SDavid du Colombier 
433*59cc4ca5SDavid du Colombier             es++;
434*59cc4ca5SDavid du Colombier             uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
435*59cc4ca5SDavid du Colombier             s->unzftab[uc] += es;
436*59cc4ca5SDavid du Colombier 
437*59cc4ca5SDavid du Colombier             if (s->smallDecompress)
438*59cc4ca5SDavid du Colombier                while (es > 0) {
439*59cc4ca5SDavid du Colombier                   if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
440*59cc4ca5SDavid du Colombier                   s->ll16[nblock] = (UInt16)uc;
441*59cc4ca5SDavid du Colombier                   nblock++;
442*59cc4ca5SDavid du Colombier                   es--;
443*59cc4ca5SDavid du Colombier                }
444*59cc4ca5SDavid du Colombier             else
445*59cc4ca5SDavid du Colombier                while (es > 0) {
446*59cc4ca5SDavid du Colombier                   if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
447*59cc4ca5SDavid du Colombier                   s->tt[nblock] = (UInt32)uc;
448*59cc4ca5SDavid du Colombier                   nblock++;
449*59cc4ca5SDavid du Colombier                   es--;
450*59cc4ca5SDavid du Colombier                };
451*59cc4ca5SDavid du Colombier 
452*59cc4ca5SDavid du Colombier             continue;
453*59cc4ca5SDavid du Colombier 
454*59cc4ca5SDavid du Colombier          } else {
455*59cc4ca5SDavid du Colombier 
456*59cc4ca5SDavid du Colombier             if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
457*59cc4ca5SDavid du Colombier 
458*59cc4ca5SDavid du Colombier             /*-- uc = MTF ( nextSym-1 ) --*/
459*59cc4ca5SDavid du Colombier             {
460*59cc4ca5SDavid du Colombier                Int32 ii, jj, kk, pp, lno, off;
461*59cc4ca5SDavid du Colombier                UInt32 nn;
462*59cc4ca5SDavid du Colombier                nn = (UInt32)(nextSym - 1);
463*59cc4ca5SDavid du Colombier 
464*59cc4ca5SDavid du Colombier                if (nn < MTFL_SIZE) {
465*59cc4ca5SDavid du Colombier                   /* avoid general-case expense */
466*59cc4ca5SDavid du Colombier                   pp = s->mtfbase[0];
467*59cc4ca5SDavid du Colombier                   uc = s->mtfa[pp+nn];
468*59cc4ca5SDavid du Colombier                   while (nn > 3) {
469*59cc4ca5SDavid du Colombier                      Int32 z = pp+nn;
470*59cc4ca5SDavid du Colombier                      s->mtfa[(z)  ] = s->mtfa[(z)-1];
471*59cc4ca5SDavid du Colombier                      s->mtfa[(z)-1] = s->mtfa[(z)-2];
472*59cc4ca5SDavid du Colombier                      s->mtfa[(z)-2] = s->mtfa[(z)-3];
473*59cc4ca5SDavid du Colombier                      s->mtfa[(z)-3] = s->mtfa[(z)-4];
474*59cc4ca5SDavid du Colombier                      nn -= 4;
475*59cc4ca5SDavid du Colombier                   }
476*59cc4ca5SDavid du Colombier                   while (nn > 0) {
477*59cc4ca5SDavid du Colombier                      s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
478*59cc4ca5SDavid du Colombier                   };
479*59cc4ca5SDavid du Colombier                   s->mtfa[pp] = uc;
480*59cc4ca5SDavid du Colombier                } else {
481*59cc4ca5SDavid du Colombier                   /* general case */
482*59cc4ca5SDavid du Colombier                   lno = nn / MTFL_SIZE;
483*59cc4ca5SDavid du Colombier                   off = nn % MTFL_SIZE;
484*59cc4ca5SDavid du Colombier                   pp = s->mtfbase[lno] + off;
485*59cc4ca5SDavid du Colombier                   uc = s->mtfa[pp];
486*59cc4ca5SDavid du Colombier                   while (pp > s->mtfbase[lno]) {
487*59cc4ca5SDavid du Colombier                      s->mtfa[pp] = s->mtfa[pp-1]; pp--;
488*59cc4ca5SDavid du Colombier                   };
489*59cc4ca5SDavid du Colombier                   s->mtfbase[lno]++;
490*59cc4ca5SDavid du Colombier                   while (lno > 0) {
491*59cc4ca5SDavid du Colombier                      s->mtfbase[lno]--;
492*59cc4ca5SDavid du Colombier                      s->mtfa[s->mtfbase[lno]]
493*59cc4ca5SDavid du Colombier                         = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
494*59cc4ca5SDavid du Colombier                      lno--;
495*59cc4ca5SDavid du Colombier                   }
496*59cc4ca5SDavid du Colombier                   s->mtfbase[0]--;
497*59cc4ca5SDavid du Colombier                   s->mtfa[s->mtfbase[0]] = uc;
498*59cc4ca5SDavid du Colombier                   if (s->mtfbase[0] == 0) {
499*59cc4ca5SDavid du Colombier                      kk = MTFA_SIZE-1;
500*59cc4ca5SDavid du Colombier                      for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
501*59cc4ca5SDavid du Colombier                         for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
502*59cc4ca5SDavid du Colombier                            s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
503*59cc4ca5SDavid du Colombier                            kk--;
504*59cc4ca5SDavid du Colombier                         }
505*59cc4ca5SDavid du Colombier                         s->mtfbase[ii] = kk + 1;
506*59cc4ca5SDavid du Colombier                      }
507*59cc4ca5SDavid du Colombier                   }
508*59cc4ca5SDavid du Colombier                }
509*59cc4ca5SDavid du Colombier             }
510*59cc4ca5SDavid du Colombier             /*-- end uc = MTF ( nextSym-1 ) --*/
511*59cc4ca5SDavid du Colombier 
512*59cc4ca5SDavid du Colombier             s->unzftab[s->seqToUnseq[uc]]++;
513*59cc4ca5SDavid du Colombier             if (s->smallDecompress)
514*59cc4ca5SDavid du Colombier                s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
515*59cc4ca5SDavid du Colombier                s->tt[nblock]   = (UInt32)(s->seqToUnseq[uc]);
516*59cc4ca5SDavid du Colombier             nblock++;
517*59cc4ca5SDavid du Colombier 
518*59cc4ca5SDavid du Colombier             GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
519*59cc4ca5SDavid du Colombier             continue;
520*59cc4ca5SDavid du Colombier          }
521*59cc4ca5SDavid du Colombier       }
522*59cc4ca5SDavid du Colombier 
523*59cc4ca5SDavid du Colombier       /* Now we know what nblock is, we can do a better sanity
524*59cc4ca5SDavid du Colombier          check on s->origPtr.
525*59cc4ca5SDavid du Colombier       */
526*59cc4ca5SDavid du Colombier       if (s->origPtr < 0 || s->origPtr >= nblock)
527*59cc4ca5SDavid du Colombier          RETURN(BZ_DATA_ERROR);
528*59cc4ca5SDavid du Colombier 
529*59cc4ca5SDavid du Colombier       s->state_out_len = 0;
530*59cc4ca5SDavid du Colombier       s->state_out_ch  = 0;
531*59cc4ca5SDavid du Colombier       BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
532*59cc4ca5SDavid du Colombier       s->state = BZ_X_OUTPUT;
533*59cc4ca5SDavid du Colombier       if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
534*59cc4ca5SDavid du Colombier 
535*59cc4ca5SDavid du Colombier       /*-- Set up cftab to facilitate generation of T^(-1) --*/
536*59cc4ca5SDavid du Colombier       s->cftab[0] = 0;
537*59cc4ca5SDavid du Colombier       for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
538*59cc4ca5SDavid du Colombier       for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
539*59cc4ca5SDavid du Colombier 
540*59cc4ca5SDavid du Colombier       if (s->smallDecompress) {
541*59cc4ca5SDavid du Colombier 
542*59cc4ca5SDavid du Colombier          /*-- Make a copy of cftab, used in generation of T --*/
543*59cc4ca5SDavid du Colombier          for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
544*59cc4ca5SDavid du Colombier 
545*59cc4ca5SDavid du Colombier          /*-- compute the T vector --*/
546*59cc4ca5SDavid du Colombier          for (i = 0; i < nblock; i++) {
547*59cc4ca5SDavid du Colombier             uc = (UChar)(s->ll16[i]);
548*59cc4ca5SDavid du Colombier             SET_LL(i, s->cftabCopy[uc]);
549*59cc4ca5SDavid du Colombier             s->cftabCopy[uc]++;
550*59cc4ca5SDavid du Colombier          }
551*59cc4ca5SDavid du Colombier 
552*59cc4ca5SDavid du Colombier          /*-- Compute T^(-1) by pointer reversal on T --*/
553*59cc4ca5SDavid du Colombier          i = s->origPtr;
554*59cc4ca5SDavid du Colombier          j = GET_LL(i);
555*59cc4ca5SDavid du Colombier          do {
556*59cc4ca5SDavid du Colombier             Int32 tmp = GET_LL(j);
557*59cc4ca5SDavid du Colombier             SET_LL(j, i);
558*59cc4ca5SDavid du Colombier             i = j;
559*59cc4ca5SDavid du Colombier             j = tmp;
560*59cc4ca5SDavid du Colombier          }
561*59cc4ca5SDavid du Colombier             while (i != s->origPtr);
562*59cc4ca5SDavid du Colombier 
563*59cc4ca5SDavid du Colombier          s->tPos = s->origPtr;
564*59cc4ca5SDavid du Colombier          s->nblock_used = 0;
565*59cc4ca5SDavid du Colombier          if (s->blockRandomised) {
566*59cc4ca5SDavid du Colombier             BZ_RAND_INIT_MASK;
567*59cc4ca5SDavid du Colombier             BZ_GET_SMALL(s->k0); s->nblock_used++;
568*59cc4ca5SDavid du Colombier             BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
569*59cc4ca5SDavid du Colombier          } else {
570*59cc4ca5SDavid du Colombier             BZ_GET_SMALL(s->k0); s->nblock_used++;
571*59cc4ca5SDavid du Colombier          }
572*59cc4ca5SDavid du Colombier 
573*59cc4ca5SDavid du Colombier       } else {
574*59cc4ca5SDavid du Colombier 
575*59cc4ca5SDavid du Colombier          /*-- compute the T^(-1) vector --*/
576*59cc4ca5SDavid du Colombier          for (i = 0; i < nblock; i++) {
577*59cc4ca5SDavid du Colombier             uc = (UChar)(s->tt[i] & 0xff);
578*59cc4ca5SDavid du Colombier             s->tt[s->cftab[uc]] |= (i << 8);
579*59cc4ca5SDavid du Colombier             s->cftab[uc]++;
580*59cc4ca5SDavid du Colombier          }
581*59cc4ca5SDavid du Colombier 
582*59cc4ca5SDavid du Colombier          s->tPos = s->tt[s->origPtr] >> 8;
583*59cc4ca5SDavid du Colombier          s->nblock_used = 0;
584*59cc4ca5SDavid du Colombier          if (s->blockRandomised) {
585*59cc4ca5SDavid du Colombier             BZ_RAND_INIT_MASK;
586*59cc4ca5SDavid du Colombier             BZ_GET_FAST(s->k0); s->nblock_used++;
587*59cc4ca5SDavid du Colombier             BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
588*59cc4ca5SDavid du Colombier          } else {
589*59cc4ca5SDavid du Colombier             BZ_GET_FAST(s->k0); s->nblock_used++;
590*59cc4ca5SDavid du Colombier          }
591*59cc4ca5SDavid du Colombier 
592*59cc4ca5SDavid du Colombier       }
593*59cc4ca5SDavid du Colombier 
594*59cc4ca5SDavid du Colombier       RETURN(BZ_OK);
595*59cc4ca5SDavid du Colombier 
596*59cc4ca5SDavid du Colombier 
597*59cc4ca5SDavid du Colombier 
598*59cc4ca5SDavid du Colombier     endhdr_2:
599*59cc4ca5SDavid du Colombier 
600*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_ENDHDR_2, uc);
601*59cc4ca5SDavid du Colombier       if (uc != 0x72) RETURN(BZ_DATA_ERROR);
602*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_ENDHDR_3, uc);
603*59cc4ca5SDavid du Colombier       if (uc != 0x45) RETURN(BZ_DATA_ERROR);
604*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_ENDHDR_4, uc);
605*59cc4ca5SDavid du Colombier       if (uc != 0x38) RETURN(BZ_DATA_ERROR);
606*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_ENDHDR_5, uc);
607*59cc4ca5SDavid du Colombier       if (uc != 0x50) RETURN(BZ_DATA_ERROR);
608*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_ENDHDR_6, uc);
609*59cc4ca5SDavid du Colombier       if (uc != 0x90) RETURN(BZ_DATA_ERROR);
610*59cc4ca5SDavid du Colombier 
611*59cc4ca5SDavid du Colombier       s->storedCombinedCRC = 0;
612*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_CCRC_1, uc);
613*59cc4ca5SDavid du Colombier       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
614*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_CCRC_2, uc);
615*59cc4ca5SDavid du Colombier       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
616*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_CCRC_3, uc);
617*59cc4ca5SDavid du Colombier       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
618*59cc4ca5SDavid du Colombier       GET_UCHAR(BZ_X_CCRC_4, uc);
619*59cc4ca5SDavid du Colombier       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
620*59cc4ca5SDavid du Colombier 
621*59cc4ca5SDavid du Colombier       s->state = BZ_X_IDLE;
622*59cc4ca5SDavid du Colombier       RETURN(BZ_STREAM_END);
623*59cc4ca5SDavid du Colombier 
624*59cc4ca5SDavid du Colombier       default: AssertH ( False, 4001 );
625*59cc4ca5SDavid du Colombier    }
626*59cc4ca5SDavid du Colombier 
627*59cc4ca5SDavid du Colombier    AssertH ( False, 4002 );
628*59cc4ca5SDavid du Colombier 
629*59cc4ca5SDavid du Colombier    save_state_and_return:
630*59cc4ca5SDavid du Colombier 
631*59cc4ca5SDavid du Colombier    s->save_i           = i;
632*59cc4ca5SDavid du Colombier    s->save_j           = j;
633*59cc4ca5SDavid du Colombier    s->save_t           = t;
634*59cc4ca5SDavid du Colombier    s->save_alphaSize   = alphaSize;
635*59cc4ca5SDavid du Colombier    s->save_nGroups     = nGroups;
636*59cc4ca5SDavid du Colombier    s->save_nSelectors  = nSelectors;
637*59cc4ca5SDavid du Colombier    s->save_EOB         = EOB;
638*59cc4ca5SDavid du Colombier    s->save_groupNo     = groupNo;
639*59cc4ca5SDavid du Colombier    s->save_groupPos    = groupPos;
640*59cc4ca5SDavid du Colombier    s->save_nextSym     = nextSym;
641*59cc4ca5SDavid du Colombier    s->save_nblockMAX   = nblockMAX;
642*59cc4ca5SDavid du Colombier    s->save_nblock      = nblock;
643*59cc4ca5SDavid du Colombier    s->save_es          = es;
644*59cc4ca5SDavid du Colombier    s->save_N           = N;
645*59cc4ca5SDavid du Colombier    s->save_curr        = curr;
646*59cc4ca5SDavid du Colombier    s->save_zt          = zt;
647*59cc4ca5SDavid du Colombier    s->save_zn          = zn;
648*59cc4ca5SDavid du Colombier    s->save_zvec        = zvec;
649*59cc4ca5SDavid du Colombier    s->save_zj          = zj;
650*59cc4ca5SDavid du Colombier    s->save_gSel        = gSel;
651*59cc4ca5SDavid du Colombier    s->save_gMinlen     = gMinlen;
652*59cc4ca5SDavid du Colombier    s->save_gLimit      = gLimit;
653*59cc4ca5SDavid du Colombier    s->save_gBase       = gBase;
654*59cc4ca5SDavid du Colombier    s->save_gPerm       = gPerm;
655*59cc4ca5SDavid du Colombier 
656*59cc4ca5SDavid du Colombier    return retVal;
657*59cc4ca5SDavid du Colombier }
658*59cc4ca5SDavid du Colombier 
659*59cc4ca5SDavid du Colombier 
660*59cc4ca5SDavid du Colombier /*-------------------------------------------------------------*/
661*59cc4ca5SDavid du Colombier /*--- end                                      decompress.c ---*/
662*59cc4ca5SDavid du Colombier /*-------------------------------------------------------------*/
663