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