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