xref: /plan9/sys/lib/dist/cmd/bzfs/unbzip.c (revision 9b7bf7df4595c26f1e9b67beb0c6e44c9876fb05)
1*9a747e4fSDavid du Colombier #include <u.h>
2*9a747e4fSDavid du Colombier #include <libc.h>
3*9a747e4fSDavid du Colombier #include <bio.h>
4*9a747e4fSDavid du Colombier #include "bzfs.h"
5*9a747e4fSDavid du Colombier 
6*9a747e4fSDavid du Colombier /*
7*9a747e4fSDavid du Colombier  * THIS FILE IS NOT IDENTICAL TO THE ORIGINAL
8*9a747e4fSDavid du Colombier  * FROM THE BZIP2 DISTRIBUTION.
9*9a747e4fSDavid du Colombier  *
10*9a747e4fSDavid du Colombier  * It has been modified, mainly to break the library
11*9a747e4fSDavid du Colombier  * into smaller pieces.
12*9a747e4fSDavid du Colombier  *
13*9a747e4fSDavid du Colombier  * Russ Cox
14*9a747e4fSDavid du Colombier  * rsc@plan9.bell-labs.com
15*9a747e4fSDavid du Colombier  * July 2000
16*9a747e4fSDavid du Colombier  */
17*9a747e4fSDavid du Colombier 
18*9a747e4fSDavid du Colombier /*---------------------------------------------*/
19*9a747e4fSDavid du Colombier /*--
20*9a747e4fSDavid du Colombier   Place a 1 beside your platform, and 0 elsewhere.
21*9a747e4fSDavid du Colombier   Attempts to autosniff this even if you don't.
22*9a747e4fSDavid du Colombier --*/
23*9a747e4fSDavid du Colombier 
24*9a747e4fSDavid du Colombier 
25*9a747e4fSDavid du Colombier /*--
26*9a747e4fSDavid du Colombier   Plan 9 from Bell Labs
27*9a747e4fSDavid du Colombier --*/
28*9a747e4fSDavid du Colombier #define BZ_PLAN9     1
29*9a747e4fSDavid du Colombier #define BZ_UNIX 0
30*9a747e4fSDavid du Colombier 
31*9a747e4fSDavid du Colombier #define exit(x) exits((x) ? "whoops" : nil)
32*9a747e4fSDavid du Colombier #define size_t ulong
33*9a747e4fSDavid du Colombier 
34*9a747e4fSDavid du Colombier #ifdef __GNUC__
35*9a747e4fSDavid du Colombier #   define NORETURN __attribute__ ((noreturn))
36*9a747e4fSDavid du Colombier #else
37*9a747e4fSDavid du Colombier #   define NORETURN /**/
38*9a747e4fSDavid du Colombier #endif
39*9a747e4fSDavid du Colombier 
40*9a747e4fSDavid du Colombier /*--
41*9a747e4fSDavid du Colombier   Some more stuff for all platforms :-)
42*9a747e4fSDavid du Colombier   This might have to get moved into the platform-specific
43*9a747e4fSDavid du Colombier   header files if we encounter a machine with different sizes.
44*9a747e4fSDavid du Colombier --*/
45*9a747e4fSDavid du Colombier 
46*9a747e4fSDavid du Colombier typedef char            Char;
47*9a747e4fSDavid du Colombier typedef unsigned char   Bool;
48*9a747e4fSDavid du Colombier typedef unsigned char   UChar;
49*9a747e4fSDavid du Colombier typedef int             Int32;
50*9a747e4fSDavid du Colombier typedef unsigned int    UInt32;
51*9a747e4fSDavid du Colombier typedef short           Int16;
52*9a747e4fSDavid du Colombier typedef unsigned short  UInt16;
53*9a747e4fSDavid du Colombier 
54*9a747e4fSDavid du Colombier #define True  ((Bool)1)
55*9a747e4fSDavid du Colombier #define False ((Bool)0)
56*9a747e4fSDavid du Colombier 
57*9a747e4fSDavid du Colombier /*--
58*9a747e4fSDavid du Colombier   IntNative is your platform's `native' int size.
59*9a747e4fSDavid du Colombier   Only here to avoid probs with 64-bit platforms.
60*9a747e4fSDavid du Colombier --*/
61*9a747e4fSDavid du Colombier typedef int IntNative;
62*9a747e4fSDavid du Colombier 
63*9a747e4fSDavid du Colombier #include "bzfs.h"
64*9a747e4fSDavid du Colombier #include "bzlib.h"
65*9a747e4fSDavid du Colombier #include "bzlib_private.h"
66*9a747e4fSDavid du Colombier 
67*9a747e4fSDavid du Colombier static int
bunzip(int ofd,char * ofile,Biobuf * bin)68*9a747e4fSDavid du Colombier bunzip(int ofd, char *ofile, Biobuf *bin)
69*9a747e4fSDavid du Colombier {
70*9a747e4fSDavid du Colombier 	int e, n, done, onemore;
71*9a747e4fSDavid du Colombier 	char buf[8192];
72*9a747e4fSDavid du Colombier 	char obuf[8192];
73*9a747e4fSDavid du Colombier 	Biobuf bout;
74*9a747e4fSDavid du Colombier 	bz_stream strm;
75*9a747e4fSDavid du Colombier 
76*9a747e4fSDavid du Colombier 	USED(ofile);
77*9a747e4fSDavid du Colombier 
78*9a747e4fSDavid du Colombier 	memset(&strm, 0, sizeof strm);
79*9a747e4fSDavid du Colombier 	BZ2_bzDecompressInit(&strm, 0, 0);
80*9a747e4fSDavid du Colombier 
81*9a747e4fSDavid du Colombier 	strm.next_in = buf;
82*9a747e4fSDavid du Colombier 	strm.avail_in = 0;
83*9a747e4fSDavid du Colombier 	strm.next_out = obuf;
84*9a747e4fSDavid du Colombier 	strm.avail_out = sizeof obuf;
85*9a747e4fSDavid du Colombier 
86*9a747e4fSDavid du Colombier 	done = 0;
87*9a747e4fSDavid du Colombier 	Binit(&bout, ofd, OWRITE);
88*9a747e4fSDavid du Colombier 
89*9a747e4fSDavid du Colombier 	/*
90*9a747e4fSDavid du Colombier 	 * onemore is a crummy hack to go 'round the loop
91*9a747e4fSDavid du Colombier 	 * once after we finish, to flush the output buffer.
92*9a747e4fSDavid du Colombier 	 */
93*9a747e4fSDavid du Colombier 	onemore = 1;
94*9a747e4fSDavid du Colombier 	SET(e);
95*9a747e4fSDavid du Colombier 	do {
96*9a747e4fSDavid du Colombier 		if(!done && strm.avail_in < sizeof buf) {
97*9a747e4fSDavid du Colombier 			if(strm.avail_in)
98*9a747e4fSDavid du Colombier 				memmove(buf, strm.next_in, strm.avail_in);
99*9a747e4fSDavid du Colombier 
100*9a747e4fSDavid du Colombier 			n = Bread(bin, buf+strm.avail_in, sizeof(buf)-strm.avail_in);
101*9a747e4fSDavid du Colombier 			if(n <= 0)
102*9a747e4fSDavid du Colombier 				done = 1;
103*9a747e4fSDavid du Colombier 			else
104*9a747e4fSDavid du Colombier 				strm.avail_in += n;
105*9a747e4fSDavid du Colombier 			strm.next_in = buf;
106*9a747e4fSDavid du Colombier 		}
107*9a747e4fSDavid du Colombier 		if(strm.avail_out < sizeof obuf) {
108*9a747e4fSDavid du Colombier 			Bwrite(&bout, obuf, sizeof(obuf)-strm.avail_out);
109*9a747e4fSDavid du Colombier 			strm.next_out = obuf;
110*9a747e4fSDavid du Colombier 			strm.avail_out = sizeof obuf;
111*9a747e4fSDavid du Colombier 		}
112*9a747e4fSDavid du Colombier 
113*9a747e4fSDavid du Colombier 		if(onemore == 0)
114*9a747e4fSDavid du Colombier 			break;
115*9a747e4fSDavid du Colombier 	} while((e=BZ2_bzDecompress(&strm)) == BZ_OK || onemore--);
116*9a747e4fSDavid du Colombier 
117*9a747e4fSDavid du Colombier 	if(e != BZ_STREAM_END) {
118*9a747e4fSDavid du Colombier 		fprint(2, "bunzip2: decompress failed\n");
119*9a747e4fSDavid du Colombier 		return 0;
120*9a747e4fSDavid du Colombier 	}
121*9a747e4fSDavid du Colombier 
122*9a747e4fSDavid du Colombier 	if(BZ2_bzDecompressEnd(&strm) != BZ_OK) {
123*9a747e4fSDavid du Colombier 		fprint(2, "bunzip2: decompress end failed (can't happen)\n");
124*9a747e4fSDavid du Colombier 		return 0;
125*9a747e4fSDavid du Colombier 	}
126*9a747e4fSDavid du Colombier 
127*9a747e4fSDavid du Colombier 	Bterm(&bout);
128*9a747e4fSDavid du Colombier 
129*9a747e4fSDavid du Colombier 	return 1;
130*9a747e4fSDavid du Colombier }
131*9a747e4fSDavid du Colombier 
132*9a747e4fSDavid du Colombier void
_unbzip(int in,int out)133*9a747e4fSDavid du Colombier _unbzip(int in, int out)
134*9a747e4fSDavid du Colombier {
135*9a747e4fSDavid du Colombier 	Biobuf bin;
136*9a747e4fSDavid du Colombier 
137*9a747e4fSDavid du Colombier 	Binit(&bin, in, OREAD);
138*9a747e4fSDavid du Colombier 	if(bunzip(out, nil, &bin) != 1) {
139*9a747e4fSDavid du Colombier 		fprint(2, "bunzip2 failed\n");
140*9a747e4fSDavid du Colombier 		_exits("bunzip2");
141*9a747e4fSDavid du Colombier 	}
142*9a747e4fSDavid du Colombier }
143*9a747e4fSDavid du Colombier 
144*9a747e4fSDavid du Colombier int
unbzip(int in)145*9a747e4fSDavid du Colombier unbzip(int in)
146*9a747e4fSDavid du Colombier {
147*9a747e4fSDavid du Colombier 	int rv, out, p[2];
148*9a747e4fSDavid du Colombier 
149*9a747e4fSDavid du Colombier 	if(pipe(p) < 0)
150*9a747e4fSDavid du Colombier 		sysfatal("pipe: %r");
151*9a747e4fSDavid du Colombier 
152*9a747e4fSDavid du Colombier 	rv = p[0];
153*9a747e4fSDavid du Colombier 	out = p[1];
154*9a747e4fSDavid du Colombier 	switch(rfork(RFPROC|RFFDG|RFNOTEG|RFMEM)){
155*9a747e4fSDavid du Colombier 	case -1:
156*9a747e4fSDavid du Colombier 		sysfatal("fork: %r");
157*9a747e4fSDavid du Colombier 	case 0:
158*9a747e4fSDavid du Colombier 		close(rv);
159*9a747e4fSDavid du Colombier 		break;
160*9a747e4fSDavid du Colombier 	default:
161*9a747e4fSDavid du Colombier 		close(in);
162*9a747e4fSDavid du Colombier 		close(out);
163*9a747e4fSDavid du Colombier 		return rv;
164*9a747e4fSDavid du Colombier 	}
165*9a747e4fSDavid du Colombier 
166*9a747e4fSDavid du Colombier 	_unbzip(in, out);
167*9a747e4fSDavid du Colombier 	_exits(0);
168*9a747e4fSDavid du Colombier 	return -1;	/* not reached */
169*9a747e4fSDavid du Colombier }
170*9a747e4fSDavid du Colombier 
bz_config_ok(void)171*9a747e4fSDavid du Colombier int bz_config_ok ( void )
172*9a747e4fSDavid du Colombier {
173*9a747e4fSDavid du Colombier    if (sizeof(int)   != 4) return 0;
174*9a747e4fSDavid du Colombier    if (sizeof(short) != 2) return 0;
175*9a747e4fSDavid du Colombier    if (sizeof(char)  != 1) return 0;
176*9a747e4fSDavid du Colombier    return 1;
177*9a747e4fSDavid du Colombier }
178*9a747e4fSDavid du Colombier 
default_bzalloc(void * o,int items,int size)179*9a747e4fSDavid du Colombier void* default_bzalloc(void *o, int items, int size)
180*9a747e4fSDavid du Colombier {
181*9a747e4fSDavid du Colombier 	USED(o);
182*9a747e4fSDavid du Colombier 	return sbrk(items*size);
183*9a747e4fSDavid du Colombier }
184*9a747e4fSDavid du Colombier 
default_bzfree(void *,void *)185*9a747e4fSDavid du Colombier void default_bzfree(void*, void*)
186*9a747e4fSDavid du Colombier {
187*9a747e4fSDavid du Colombier }
188*9a747e4fSDavid du Colombier 
189*9a747e4fSDavid du Colombier void
bz_internal_error(int)190*9a747e4fSDavid du Colombier bz_internal_error(int)
191*9a747e4fSDavid du Colombier {
192*9a747e4fSDavid du Colombier 	abort();
193*9a747e4fSDavid du Colombier }
194*9a747e4fSDavid du Colombier 
195*9a747e4fSDavid du Colombier /*-------------------------------------------------------------*/
196*9a747e4fSDavid du Colombier /*--- Decompression machinery                               ---*/
197*9a747e4fSDavid du Colombier /*---                                          decompress.c ---*/
198*9a747e4fSDavid du Colombier /*-------------------------------------------------------------*/
199*9a747e4fSDavid du Colombier 
200*9a747e4fSDavid du Colombier /*--
201*9a747e4fSDavid du Colombier   This file is a part of bzip2 and/or libbzip2, a program and
202*9a747e4fSDavid du Colombier   library for lossless, block-sorting data compression.
203*9a747e4fSDavid du Colombier 
204*9a747e4fSDavid du Colombier   Copyright (C) 1996-2000 Julian R Seward.  All rights reserved.
205*9a747e4fSDavid du Colombier 
206*9a747e4fSDavid du Colombier   Redistribution and use in source and binary forms, with or without
207*9a747e4fSDavid du Colombier   modification, are permitted provided that the following conditions
208*9a747e4fSDavid du Colombier   are met:
209*9a747e4fSDavid du Colombier 
210*9a747e4fSDavid du Colombier   1. Redistributions of source code must retain the above copyright
211*9a747e4fSDavid du Colombier      notice, this list of conditions and the following disclaimer.
212*9a747e4fSDavid du Colombier 
213*9a747e4fSDavid du Colombier   2. The origin of this software must not be misrepresented; you must
214*9a747e4fSDavid du Colombier      not claim that you wrote the original software.  If you use this
215*9a747e4fSDavid du Colombier      software in a product, an acknowledgment in the product
216*9a747e4fSDavid du Colombier      documentation would be appreciated but is not required.
217*9a747e4fSDavid du Colombier 
218*9a747e4fSDavid du Colombier   3. Altered source versions must be plainly marked as such, and must
219*9a747e4fSDavid du Colombier      not be misrepresented as being the original software.
220*9a747e4fSDavid du Colombier 
221*9a747e4fSDavid du Colombier   4. The name of the author may not be used to endorse or promote
222*9a747e4fSDavid du Colombier      products derived from this software without specific prior written
223*9a747e4fSDavid du Colombier      permission.
224*9a747e4fSDavid du Colombier 
225*9a747e4fSDavid du Colombier   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
226*9a747e4fSDavid du Colombier   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
227*9a747e4fSDavid du Colombier   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
228*9a747e4fSDavid du Colombier   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
229*9a747e4fSDavid du Colombier   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
230*9a747e4fSDavid du Colombier   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
231*9a747e4fSDavid du Colombier   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
232*9a747e4fSDavid du Colombier   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
233*9a747e4fSDavid du Colombier   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
234*9a747e4fSDavid du Colombier   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
235*9a747e4fSDavid du Colombier   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
236*9a747e4fSDavid du Colombier 
237*9a747e4fSDavid du Colombier   Julian Seward, Cambridge, UK.
238*9a747e4fSDavid du Colombier   jseward@acm.org
239*9a747e4fSDavid du Colombier   bzip2/libbzip2 version 1.0 of 21 March 2000
240*9a747e4fSDavid du Colombier 
241*9a747e4fSDavid du Colombier   This program is based on (at least) the work of:
242*9a747e4fSDavid du Colombier      Mike Burrows
243*9a747e4fSDavid du Colombier      David Wheeler
244*9a747e4fSDavid du Colombier      Peter Fenwick
245*9a747e4fSDavid du Colombier      Alistair Moffat
246*9a747e4fSDavid du Colombier      Radford Neal
247*9a747e4fSDavid du Colombier      Ian H. Witten
248*9a747e4fSDavid du Colombier      Robert Sedgewick
249*9a747e4fSDavid du Colombier      Jon L. Bentley
250*9a747e4fSDavid du Colombier 
251*9a747e4fSDavid du Colombier   For more information on these sources, see the manual.
252*9a747e4fSDavid du Colombier --*/
253*9a747e4fSDavid du Colombier 
254*9a747e4fSDavid du Colombier 
255*9a747e4fSDavid du Colombier 
256*9a747e4fSDavid du Colombier /*---------------------------------------------------*/
257*9a747e4fSDavid du Colombier static
makeMaps_d(DState * s)258*9a747e4fSDavid du Colombier void makeMaps_d ( DState* s )
259*9a747e4fSDavid du Colombier {
260*9a747e4fSDavid du Colombier    Int32 i;
261*9a747e4fSDavid du Colombier    s->nInUse = 0;
262*9a747e4fSDavid du Colombier    for (i = 0; i < 256; i++)
263*9a747e4fSDavid du Colombier       if (s->inUse[i]) {
264*9a747e4fSDavid du Colombier          s->seqToUnseq[s->nInUse] = i;
265*9a747e4fSDavid du Colombier          s->nInUse++;
266*9a747e4fSDavid du Colombier       }
267*9a747e4fSDavid du Colombier }
268*9a747e4fSDavid du Colombier 
269*9a747e4fSDavid du Colombier 
270*9a747e4fSDavid du Colombier /*---------------------------------------------------*/
271*9a747e4fSDavid du Colombier #define RETURN(rrr)                               \
272*9a747e4fSDavid du Colombier    { retVal = rrr; goto save_state_and_return; };
273*9a747e4fSDavid du Colombier 
274*9a747e4fSDavid du Colombier #define GET_BITS(lll,vvv,nnn)                     \
275*9a747e4fSDavid du Colombier 	case lll: \
276*9a747e4fSDavid du Colombier 		{ int x; if((retVal = getbits(s, lll, &x, nnn)) != 99) \
277*9a747e4fSDavid du Colombier 			goto save_state_and_return; vvv=x; }\
278*9a747e4fSDavid du Colombier 
279*9a747e4fSDavid du Colombier int
getbits(DState * s,int lll,int * vvv,int nnn)280*9a747e4fSDavid du Colombier getbits(DState *s, int lll, int *vvv, int nnn)
281*9a747e4fSDavid du Colombier {
282*9a747e4fSDavid du Colombier 	s->state = lll;
283*9a747e4fSDavid du Colombier 
284*9a747e4fSDavid du Colombier 	for(;;) {
285*9a747e4fSDavid du Colombier 		if (s->bsLive >= nnn) {
286*9a747e4fSDavid du Colombier 			UInt32 v;
287*9a747e4fSDavid du Colombier 			v = (s->bsBuff >>
288*9a747e4fSDavid du Colombier 				 (s->bsLive-nnn)) & ((1 << nnn)-1);
289*9a747e4fSDavid du Colombier 			s->bsLive -= nnn;
290*9a747e4fSDavid du Colombier 			*vvv = v;
291*9a747e4fSDavid du Colombier 			return 99;
292*9a747e4fSDavid du Colombier 		}
293*9a747e4fSDavid du Colombier 		if (s->strm->avail_in == 0) return BZ_OK;
294*9a747e4fSDavid du Colombier 		s->bsBuff
295*9a747e4fSDavid du Colombier 			= (s->bsBuff << 8) |
296*9a747e4fSDavid du Colombier 			  ((UInt32)
297*9a747e4fSDavid du Colombier 				  (*((UChar*)(s->strm->next_in))));
298*9a747e4fSDavid du Colombier 		s->bsLive += 8;
299*9a747e4fSDavid du Colombier 		s->strm->next_in++;
300*9a747e4fSDavid du Colombier 		s->strm->avail_in--;
301*9a747e4fSDavid du Colombier 		s->strm->total_in_lo32++;
302*9a747e4fSDavid du Colombier 		if (s->strm->total_in_lo32 == 0)
303*9a747e4fSDavid du Colombier 			s->strm->total_in_hi32++;
304*9a747e4fSDavid du Colombier 	}
305*9a747e4fSDavid du Colombier }
306*9a747e4fSDavid du Colombier 
307*9a747e4fSDavid du Colombier #define GET_UCHAR(lll,uuu)                        \
308*9a747e4fSDavid du Colombier    GET_BITS(lll,uuu,8)
309*9a747e4fSDavid du Colombier 
310*9a747e4fSDavid du Colombier #define GET_BIT(lll,uuu)                          \
311*9a747e4fSDavid du Colombier    GET_BITS(lll,uuu,1)
312*9a747e4fSDavid du Colombier 
313*9a747e4fSDavid du Colombier /*---------------------------------------------------*/
314*9a747e4fSDavid du Colombier #define GET_MTF_VAL(label1,label2,lval)           \
315*9a747e4fSDavid du Colombier {                                                 \
316*9a747e4fSDavid du Colombier    if (groupPos == 0) {                           \
317*9a747e4fSDavid du Colombier       groupNo++;                                  \
318*9a747e4fSDavid du Colombier       if (groupNo >= nSelectors)                  \
319*9a747e4fSDavid du Colombier          RETURN(BZ_DATA_ERROR);                   \
320*9a747e4fSDavid du Colombier       groupPos = BZ_G_SIZE;                       \
321*9a747e4fSDavid du Colombier       gSel = s->selector[groupNo];                \
322*9a747e4fSDavid du Colombier       gMinlen = s->minLens[gSel];                 \
323*9a747e4fSDavid du Colombier       gLimit = &(s->limit[gSel][0]);              \
324*9a747e4fSDavid du Colombier       gPerm = &(s->perm[gSel][0]);                \
325*9a747e4fSDavid du Colombier       gBase = &(s->base[gSel][0]);                \
326*9a747e4fSDavid du Colombier    }                                              \
327*9a747e4fSDavid du Colombier    groupPos--;                                    \
328*9a747e4fSDavid du Colombier    zn = gMinlen;                                  \
329*9a747e4fSDavid du Colombier    GET_BITS(label1, zvec, zn);                    \
330*9a747e4fSDavid du Colombier    while (1) {                                    \
331*9a747e4fSDavid du Colombier       if (zn > 20 /* the longest code */)         \
332*9a747e4fSDavid du Colombier          RETURN(BZ_DATA_ERROR);                   \
333*9a747e4fSDavid du Colombier       if (zvec <= gLimit[zn]) break;              \
334*9a747e4fSDavid du Colombier       zn++;                                       \
335*9a747e4fSDavid du Colombier       GET_BIT(label2, zj);                        \
336*9a747e4fSDavid du Colombier       zvec = (zvec << 1) | zj;                    \
337*9a747e4fSDavid du Colombier    };                                             \
338*9a747e4fSDavid du Colombier    if (zvec - gBase[zn] < 0                       \
339*9a747e4fSDavid du Colombier        || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE)  \
340*9a747e4fSDavid du Colombier       RETURN(BZ_DATA_ERROR);                      \
341*9a747e4fSDavid du Colombier    lval = gPerm[zvec - gBase[zn]];                \
342*9a747e4fSDavid du Colombier }
343*9a747e4fSDavid du Colombier 
344*9a747e4fSDavid du Colombier 
345*9a747e4fSDavid du Colombier /*---------------------------------------------------*/
BZ2_decompress(DState * s)346*9a747e4fSDavid du Colombier Int32 BZ2_decompress ( DState* s )
347*9a747e4fSDavid du Colombier {
348*9a747e4fSDavid du Colombier    UChar      uc;
349*9a747e4fSDavid du Colombier    Int32      retVal;
350*9a747e4fSDavid du Colombier    Int32      minLen, maxLen;
351*9a747e4fSDavid du Colombier    bz_stream* strm = s->strm;
352*9a747e4fSDavid du Colombier 
353*9a747e4fSDavid du Colombier    /* stuff that needs to be saved/restored */
354*9a747e4fSDavid du Colombier    Int32  i;
355*9a747e4fSDavid du Colombier    Int32  j;
356*9a747e4fSDavid du Colombier    Int32  t;
357*9a747e4fSDavid du Colombier    Int32  alphaSize;
358*9a747e4fSDavid du Colombier    Int32  nGroups;
359*9a747e4fSDavid du Colombier    Int32  nSelectors;
360*9a747e4fSDavid du Colombier    Int32  EOB;
361*9a747e4fSDavid du Colombier    Int32  groupNo;
362*9a747e4fSDavid du Colombier    Int32  groupPos;
363*9a747e4fSDavid du Colombier    Int32  nextSym;
364*9a747e4fSDavid du Colombier    Int32  nblockMAX;
365*9a747e4fSDavid du Colombier    Int32  nblock;
366*9a747e4fSDavid du Colombier    Int32  es;
367*9a747e4fSDavid du Colombier    Int32  N;
368*9a747e4fSDavid du Colombier    Int32  curr;
369*9a747e4fSDavid du Colombier    Int32  zt;
370*9a747e4fSDavid du Colombier    Int32  zn;
371*9a747e4fSDavid du Colombier    Int32  zvec;
372*9a747e4fSDavid du Colombier    Int32  zj;
373*9a747e4fSDavid du Colombier    Int32  gSel;
374*9a747e4fSDavid du Colombier    Int32  gMinlen;
375*9a747e4fSDavid du Colombier    Int32* gLimit;
376*9a747e4fSDavid du Colombier    Int32* gBase;
377*9a747e4fSDavid du Colombier    Int32* gPerm;
378*9a747e4fSDavid du Colombier 
379*9a747e4fSDavid du Colombier    if (s->state == BZ_X_MAGIC_1) {
380*9a747e4fSDavid du Colombier       /*initialise the save area*/
381*9a747e4fSDavid du Colombier       s->save_i           = 0;
382*9a747e4fSDavid du Colombier       s->save_j           = 0;
383*9a747e4fSDavid du Colombier       s->save_t           = 0;
384*9a747e4fSDavid du Colombier       s->save_alphaSize   = 0;
385*9a747e4fSDavid du Colombier       s->save_nGroups     = 0;
386*9a747e4fSDavid du Colombier       s->save_nSelectors  = 0;
387*9a747e4fSDavid du Colombier       s->save_EOB         = 0;
388*9a747e4fSDavid du Colombier       s->save_groupNo     = 0;
389*9a747e4fSDavid du Colombier       s->save_groupPos    = 0;
390*9a747e4fSDavid du Colombier       s->save_nextSym     = 0;
391*9a747e4fSDavid du Colombier       s->save_nblockMAX   = 0;
392*9a747e4fSDavid du Colombier       s->save_nblock      = 0;
393*9a747e4fSDavid du Colombier       s->save_es          = 0;
394*9a747e4fSDavid du Colombier       s->save_N           = 0;
395*9a747e4fSDavid du Colombier       s->save_curr        = 0;
396*9a747e4fSDavid du Colombier       s->save_zt          = 0;
397*9a747e4fSDavid du Colombier       s->save_zn          = 0;
398*9a747e4fSDavid du Colombier       s->save_zvec        = 0;
399*9a747e4fSDavid du Colombier       s->save_zj          = 0;
400*9a747e4fSDavid du Colombier       s->save_gSel        = 0;
401*9a747e4fSDavid du Colombier       s->save_gMinlen     = 0;
402*9a747e4fSDavid du Colombier       s->save_gLimit      = NULL;
403*9a747e4fSDavid du Colombier       s->save_gBase       = NULL;
404*9a747e4fSDavid du Colombier       s->save_gPerm       = NULL;
405*9a747e4fSDavid du Colombier    }
406*9a747e4fSDavid du Colombier 
407*9a747e4fSDavid du Colombier    /*restore from the save area*/
408*9a747e4fSDavid du Colombier    i           = s->save_i;
409*9a747e4fSDavid du Colombier    j           = s->save_j;
410*9a747e4fSDavid du Colombier    t           = s->save_t;
411*9a747e4fSDavid du Colombier    alphaSize   = s->save_alphaSize;
412*9a747e4fSDavid du Colombier    nGroups     = s->save_nGroups;
413*9a747e4fSDavid du Colombier    nSelectors  = s->save_nSelectors;
414*9a747e4fSDavid du Colombier    EOB         = s->save_EOB;
415*9a747e4fSDavid du Colombier    groupNo     = s->save_groupNo;
416*9a747e4fSDavid du Colombier    groupPos    = s->save_groupPos;
417*9a747e4fSDavid du Colombier    nextSym     = s->save_nextSym;
418*9a747e4fSDavid du Colombier    nblockMAX   = s->save_nblockMAX;
419*9a747e4fSDavid du Colombier    nblock      = s->save_nblock;
420*9a747e4fSDavid du Colombier    es          = s->save_es;
421*9a747e4fSDavid du Colombier    N           = s->save_N;
422*9a747e4fSDavid du Colombier    curr        = s->save_curr;
423*9a747e4fSDavid du Colombier    zt          = s->save_zt;
424*9a747e4fSDavid du Colombier    zn          = s->save_zn;
425*9a747e4fSDavid du Colombier    zvec        = s->save_zvec;
426*9a747e4fSDavid du Colombier    zj          = s->save_zj;
427*9a747e4fSDavid du Colombier    gSel        = s->save_gSel;
428*9a747e4fSDavid du Colombier    gMinlen     = s->save_gMinlen;
429*9a747e4fSDavid du Colombier    gLimit      = s->save_gLimit;
430*9a747e4fSDavid du Colombier    gBase       = s->save_gBase;
431*9a747e4fSDavid du Colombier    gPerm       = s->save_gPerm;
432*9a747e4fSDavid du Colombier 
433*9a747e4fSDavid du Colombier    retVal = BZ_OK;
434*9a747e4fSDavid du Colombier 
435*9a747e4fSDavid du Colombier    switch (s->state) {
436*9a747e4fSDavid du Colombier 
437*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_MAGIC_1, uc);
438*9a747e4fSDavid du Colombier       if (uc != 'B') RETURN(BZ_DATA_ERROR_MAGIC);
439*9a747e4fSDavid du Colombier 
440*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_MAGIC_2, uc);
441*9a747e4fSDavid du Colombier       if (uc != 'Z') RETURN(BZ_DATA_ERROR_MAGIC);
442*9a747e4fSDavid du Colombier 
443*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_MAGIC_3, uc)
444*9a747e4fSDavid du Colombier       if (uc != 'h') RETURN(BZ_DATA_ERROR_MAGIC);
445*9a747e4fSDavid du Colombier 
446*9a747e4fSDavid du Colombier       GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
447*9a747e4fSDavid du Colombier       if (s->blockSize100k < '1' ||
448*9a747e4fSDavid du Colombier           s->blockSize100k > '9') RETURN(BZ_DATA_ERROR_MAGIC);
449*9a747e4fSDavid du Colombier       s->blockSize100k -= '0';
450*9a747e4fSDavid du Colombier 
451*9a747e4fSDavid du Colombier       if (0 && s->smallDecompress) {
452*9a747e4fSDavid du Colombier          s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
453*9a747e4fSDavid du Colombier          s->ll4  = BZALLOC(
454*9a747e4fSDavid du Colombier                       ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar)
455*9a747e4fSDavid du Colombier                    );
456*9a747e4fSDavid du Colombier          if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
457*9a747e4fSDavid du Colombier       } else {
458*9a747e4fSDavid du Colombier          s->tt  = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
459*9a747e4fSDavid du Colombier          if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
460*9a747e4fSDavid du Colombier       }
461*9a747e4fSDavid du Colombier 
462*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_1, uc);
463*9a747e4fSDavid du Colombier 
464*9a747e4fSDavid du Colombier       if (uc == 0x17) goto endhdr_2;
465*9a747e4fSDavid du Colombier       if (uc != 0x31) RETURN(BZ_DATA_ERROR);
466*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_2, uc);
467*9a747e4fSDavid du Colombier       if (uc != 0x41) RETURN(BZ_DATA_ERROR);
468*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_3, uc);
469*9a747e4fSDavid du Colombier       if (uc != 0x59) RETURN(BZ_DATA_ERROR);
470*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_4, uc);
471*9a747e4fSDavid du Colombier       if (uc != 0x26) RETURN(BZ_DATA_ERROR);
472*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_5, uc);
473*9a747e4fSDavid du Colombier       if (uc != 0x53) RETURN(BZ_DATA_ERROR);
474*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_BLKHDR_6, uc);
475*9a747e4fSDavid du Colombier       if (uc != 0x59) RETURN(BZ_DATA_ERROR);
476*9a747e4fSDavid du Colombier 
477*9a747e4fSDavid du Colombier       s->currBlockNo++;
478*9a747e4fSDavid du Colombier     //  if (s->verbosity >= 2)
479*9a747e4fSDavid du Colombier     //     VPrintf1 ( "\n    [%d: huff+mtf ", s->currBlockNo );
480*9a747e4fSDavid du Colombier 
481*9a747e4fSDavid du Colombier       s->storedBlockCRC = 0;
482*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_BCRC_1, uc);
483*9a747e4fSDavid du Colombier       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
484*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_BCRC_2, uc);
485*9a747e4fSDavid du Colombier       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
486*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_BCRC_3, uc);
487*9a747e4fSDavid du Colombier       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
488*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_BCRC_4, uc);
489*9a747e4fSDavid du Colombier       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
490*9a747e4fSDavid du Colombier 
491*9a747e4fSDavid du Colombier       GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
492*9a747e4fSDavid du Colombier 
493*9a747e4fSDavid du Colombier       s->origPtr = 0;
494*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_ORIGPTR_1, uc);
495*9a747e4fSDavid du Colombier       s->origPtr = (s->origPtr << 8) | ((Int32)uc);
496*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_ORIGPTR_2, uc);
497*9a747e4fSDavid du Colombier       s->origPtr = (s->origPtr << 8) | ((Int32)uc);
498*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_ORIGPTR_3, uc);
499*9a747e4fSDavid du Colombier       s->origPtr = (s->origPtr << 8) | ((Int32)uc);
500*9a747e4fSDavid du Colombier 
501*9a747e4fSDavid du Colombier       if (s->origPtr < 0)
502*9a747e4fSDavid du Colombier          RETURN(BZ_DATA_ERROR);
503*9a747e4fSDavid du Colombier       if (s->origPtr > 10 + 100000*s->blockSize100k)
504*9a747e4fSDavid du Colombier          RETURN(BZ_DATA_ERROR);
505*9a747e4fSDavid du Colombier 
506*9a747e4fSDavid du Colombier       /*--- Receive the mapping table ---*/
507*9a747e4fSDavid du Colombier       for (i = 0; i < 16; i++) {
508*9a747e4fSDavid du Colombier          GET_BIT(BZ_X_MAPPING_1, uc);
509*9a747e4fSDavid du Colombier          if (uc == 1)
510*9a747e4fSDavid du Colombier             s->inUse16[i] = True; else
511*9a747e4fSDavid du Colombier             s->inUse16[i] = False;
512*9a747e4fSDavid du Colombier       }
513*9a747e4fSDavid du Colombier 
514*9a747e4fSDavid du Colombier       for (i = 0; i < 256; i++) s->inUse[i] = False;
515*9a747e4fSDavid du Colombier 
516*9a747e4fSDavid du Colombier       for (i = 0; i < 16; i++)
517*9a747e4fSDavid du Colombier          if (s->inUse16[i])
518*9a747e4fSDavid du Colombier             for (j = 0; j < 16; j++) {
519*9a747e4fSDavid du Colombier                GET_BIT(BZ_X_MAPPING_2, uc);
520*9a747e4fSDavid du Colombier                if (uc == 1) s->inUse[i * 16 + j] = True;
521*9a747e4fSDavid du Colombier             }
522*9a747e4fSDavid du Colombier       makeMaps_d ( s );
523*9a747e4fSDavid du Colombier       if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
524*9a747e4fSDavid du Colombier       alphaSize = s->nInUse+2;
525*9a747e4fSDavid du Colombier 
526*9a747e4fSDavid du Colombier       /*--- Now the selectors ---*/
527*9a747e4fSDavid du Colombier       GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
528*9a747e4fSDavid du Colombier       if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
529*9a747e4fSDavid du Colombier       GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
530*9a747e4fSDavid du Colombier       if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
531*9a747e4fSDavid du Colombier       for (i = 0; i < nSelectors; i++) {
532*9a747e4fSDavid du Colombier          j = 0;
533*9a747e4fSDavid du Colombier          while (True) {
534*9a747e4fSDavid du Colombier             GET_BIT(BZ_X_SELECTOR_3, uc);
535*9a747e4fSDavid du Colombier             if (uc == 0) break;
536*9a747e4fSDavid du Colombier             j++;
537*9a747e4fSDavid du Colombier             if (j >= nGroups) RETURN(BZ_DATA_ERROR);
538*9a747e4fSDavid du Colombier          }
539*9a747e4fSDavid du Colombier          s->selectorMtf[i] = j;
540*9a747e4fSDavid du Colombier       }
541*9a747e4fSDavid du Colombier 
542*9a747e4fSDavid du Colombier       /*--- Undo the MTF values for the selectors. ---*/
543*9a747e4fSDavid du Colombier       {
544*9a747e4fSDavid du Colombier          UChar pos[BZ_N_GROUPS], tmp, v;
545*9a747e4fSDavid du Colombier          for (v = 0; v < nGroups; v++) pos[v] = v;
546*9a747e4fSDavid du Colombier 
547*9a747e4fSDavid du Colombier          for (i = 0; i < nSelectors; i++) {
548*9a747e4fSDavid du Colombier             v = s->selectorMtf[i];
549*9a747e4fSDavid du Colombier             tmp = pos[v];
550*9a747e4fSDavid du Colombier             while (v > 0) { pos[v] = pos[v-1]; v--; }
551*9a747e4fSDavid du Colombier             pos[0] = tmp;
552*9a747e4fSDavid du Colombier             s->selector[i] = tmp;
553*9a747e4fSDavid du Colombier          }
554*9a747e4fSDavid du Colombier       }
555*9a747e4fSDavid du Colombier 
556*9a747e4fSDavid du Colombier       /*--- Now the coding tables ---*/
557*9a747e4fSDavid du Colombier       for (t = 0; t < nGroups; t++) {
558*9a747e4fSDavid du Colombier          GET_BITS(BZ_X_CODING_1, curr, 5);
559*9a747e4fSDavid du Colombier          for (i = 0; i < alphaSize; i++) {
560*9a747e4fSDavid du Colombier             while (True) {
561*9a747e4fSDavid du Colombier                if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
562*9a747e4fSDavid du Colombier                GET_BIT(BZ_X_CODING_2, uc);
563*9a747e4fSDavid du Colombier                if (uc == 0) break;
564*9a747e4fSDavid du Colombier                GET_BIT(BZ_X_CODING_3, uc);
565*9a747e4fSDavid du Colombier                if (uc == 0) curr++; else curr--;
566*9a747e4fSDavid du Colombier             }
567*9a747e4fSDavid du Colombier             s->len[t][i] = curr;
568*9a747e4fSDavid du Colombier          }
569*9a747e4fSDavid du Colombier       }
570*9a747e4fSDavid du Colombier 
571*9a747e4fSDavid du Colombier       /*--- Create the Huffman decoding tables ---*/
572*9a747e4fSDavid du Colombier       for (t = 0; t < nGroups; t++) {
573*9a747e4fSDavid du Colombier          minLen = 32;
574*9a747e4fSDavid du Colombier          maxLen = 0;
575*9a747e4fSDavid du Colombier          for (i = 0; i < alphaSize; i++) {
576*9a747e4fSDavid du Colombier             if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
577*9a747e4fSDavid du Colombier             if (s->len[t][i] < minLen) minLen = s->len[t][i];
578*9a747e4fSDavid du Colombier          }
579*9a747e4fSDavid du Colombier          BZ2_hbCreateDecodeTables (
580*9a747e4fSDavid du Colombier             &(s->limit[t][0]),
581*9a747e4fSDavid du Colombier             &(s->base[t][0]),
582*9a747e4fSDavid du Colombier             &(s->perm[t][0]),
583*9a747e4fSDavid du Colombier             &(s->len[t][0]),
584*9a747e4fSDavid du Colombier             minLen, maxLen, alphaSize
585*9a747e4fSDavid du Colombier          );
586*9a747e4fSDavid du Colombier          s->minLens[t] = minLen;
587*9a747e4fSDavid du Colombier       }
588*9a747e4fSDavid du Colombier 
589*9a747e4fSDavid du Colombier       /*--- Now the MTF values ---*/
590*9a747e4fSDavid du Colombier 
591*9a747e4fSDavid du Colombier       EOB      = s->nInUse+1;
592*9a747e4fSDavid du Colombier       nblockMAX = 100000 * s->blockSize100k;
593*9a747e4fSDavid du Colombier       groupNo  = -1;
594*9a747e4fSDavid du Colombier       groupPos = 0;
595*9a747e4fSDavid du Colombier 
596*9a747e4fSDavid du Colombier       for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
597*9a747e4fSDavid du Colombier 
598*9a747e4fSDavid du Colombier       /*-- MTF init --*/
599*9a747e4fSDavid du Colombier       {
600*9a747e4fSDavid du Colombier          Int32 ii, jj, kk;
601*9a747e4fSDavid du Colombier          kk = MTFA_SIZE-1;
602*9a747e4fSDavid du Colombier          for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
603*9a747e4fSDavid du Colombier             for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
604*9a747e4fSDavid du Colombier                s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
605*9a747e4fSDavid du Colombier                kk--;
606*9a747e4fSDavid du Colombier             }
607*9a747e4fSDavid du Colombier             s->mtfbase[ii] = kk + 1;
608*9a747e4fSDavid du Colombier          }
609*9a747e4fSDavid du Colombier       }
610*9a747e4fSDavid du Colombier       /*-- end MTF init --*/
611*9a747e4fSDavid du Colombier 
612*9a747e4fSDavid du Colombier       nblock = 0;
613*9a747e4fSDavid du Colombier       GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
614*9a747e4fSDavid du Colombier 
615*9a747e4fSDavid du Colombier       while (True) {
616*9a747e4fSDavid du Colombier 
617*9a747e4fSDavid du Colombier          if (nextSym == EOB) break;
618*9a747e4fSDavid du Colombier 
619*9a747e4fSDavid du Colombier          if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
620*9a747e4fSDavid du Colombier 
621*9a747e4fSDavid du Colombier             es = -1;
622*9a747e4fSDavid du Colombier             N = 1;
623*9a747e4fSDavid du Colombier             do {
624*9a747e4fSDavid du Colombier                if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
625*9a747e4fSDavid du Colombier                if (nextSym == BZ_RUNB) es = es + (1+1) * N;
626*9a747e4fSDavid du Colombier                N = N * 2;
627*9a747e4fSDavid du Colombier                GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
628*9a747e4fSDavid du Colombier             }
629*9a747e4fSDavid du Colombier                while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
630*9a747e4fSDavid du Colombier 
631*9a747e4fSDavid du Colombier             es++;
632*9a747e4fSDavid du Colombier             uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
633*9a747e4fSDavid du Colombier             s->unzftab[uc] += es;
634*9a747e4fSDavid du Colombier 
635*9a747e4fSDavid du Colombier             if (0 && s->smallDecompress)
636*9a747e4fSDavid du Colombier                while (es > 0) {
637*9a747e4fSDavid du Colombier                   if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
638*9a747e4fSDavid du Colombier                   s->ll16[nblock] = (UInt16)uc;
639*9a747e4fSDavid du Colombier                   nblock++;
640*9a747e4fSDavid du Colombier                   es--;
641*9a747e4fSDavid du Colombier                }
642*9a747e4fSDavid du Colombier             else
643*9a747e4fSDavid du Colombier                while (es > 0) {
644*9a747e4fSDavid du Colombier                   if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
645*9a747e4fSDavid du Colombier                   s->tt[nblock] = (UInt32)uc;
646*9a747e4fSDavid du Colombier                   nblock++;
647*9a747e4fSDavid du Colombier                   es--;
648*9a747e4fSDavid du Colombier                };
649*9a747e4fSDavid du Colombier 
650*9a747e4fSDavid du Colombier             continue;
651*9a747e4fSDavid du Colombier 
652*9a747e4fSDavid du Colombier          } else {
653*9a747e4fSDavid du Colombier 
654*9a747e4fSDavid du Colombier             if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
655*9a747e4fSDavid du Colombier 
656*9a747e4fSDavid du Colombier             /*-- uc = MTF ( nextSym-1 ) --*/
657*9a747e4fSDavid du Colombier             {
658*9a747e4fSDavid du Colombier                Int32 ii, jj, kk, pp, lno, off;
659*9a747e4fSDavid du Colombier                UInt32 nn;
660*9a747e4fSDavid du Colombier                nn = (UInt32)(nextSym - 1);
661*9a747e4fSDavid du Colombier 
662*9a747e4fSDavid du Colombier                if (nn < MTFL_SIZE) {
663*9a747e4fSDavid du Colombier                   /* avoid general-case expense */
664*9a747e4fSDavid du Colombier                   pp = s->mtfbase[0];
665*9a747e4fSDavid du Colombier                   uc = s->mtfa[pp+nn];
666*9a747e4fSDavid du Colombier                   while (nn > 3) {
667*9a747e4fSDavid du Colombier                      Int32 z = pp+nn;
668*9a747e4fSDavid du Colombier                      s->mtfa[(z)  ] = s->mtfa[(z)-1];
669*9a747e4fSDavid du Colombier                      s->mtfa[(z)-1] = s->mtfa[(z)-2];
670*9a747e4fSDavid du Colombier                      s->mtfa[(z)-2] = s->mtfa[(z)-3];
671*9a747e4fSDavid du Colombier                      s->mtfa[(z)-3] = s->mtfa[(z)-4];
672*9a747e4fSDavid du Colombier                      nn -= 4;
673*9a747e4fSDavid du Colombier                   }
674*9a747e4fSDavid du Colombier                   while (nn > 0) {
675*9a747e4fSDavid du Colombier                      s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
676*9a747e4fSDavid du Colombier                   };
677*9a747e4fSDavid du Colombier                   s->mtfa[pp] = uc;
678*9a747e4fSDavid du Colombier                } else {
679*9a747e4fSDavid du Colombier                   /* general case */
680*9a747e4fSDavid du Colombier                   lno = nn / MTFL_SIZE;
681*9a747e4fSDavid du Colombier                   off = nn % MTFL_SIZE;
682*9a747e4fSDavid du Colombier                   pp = s->mtfbase[lno] + off;
683*9a747e4fSDavid du Colombier                   uc = s->mtfa[pp];
684*9a747e4fSDavid du Colombier                   while (pp > s->mtfbase[lno]) {
685*9a747e4fSDavid du Colombier                      s->mtfa[pp] = s->mtfa[pp-1]; pp--;
686*9a747e4fSDavid du Colombier                   };
687*9a747e4fSDavid du Colombier                   s->mtfbase[lno]++;
688*9a747e4fSDavid du Colombier                   while (lno > 0) {
689*9a747e4fSDavid du Colombier                      s->mtfbase[lno]--;
690*9a747e4fSDavid du Colombier                      s->mtfa[s->mtfbase[lno]]
691*9a747e4fSDavid du Colombier                         = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
692*9a747e4fSDavid du Colombier                      lno--;
693*9a747e4fSDavid du Colombier                   }
694*9a747e4fSDavid du Colombier                   s->mtfbase[0]--;
695*9a747e4fSDavid du Colombier                   s->mtfa[s->mtfbase[0]] = uc;
696*9a747e4fSDavid du Colombier                   if (s->mtfbase[0] == 0) {
697*9a747e4fSDavid du Colombier                      kk = MTFA_SIZE-1;
698*9a747e4fSDavid du Colombier                      for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
699*9a747e4fSDavid du Colombier                         for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
700*9a747e4fSDavid du Colombier                            s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
701*9a747e4fSDavid du Colombier                            kk--;
702*9a747e4fSDavid du Colombier                         }
703*9a747e4fSDavid du Colombier                         s->mtfbase[ii] = kk + 1;
704*9a747e4fSDavid du Colombier                      }
705*9a747e4fSDavid du Colombier                   }
706*9a747e4fSDavid du Colombier                }
707*9a747e4fSDavid du Colombier             }
708*9a747e4fSDavid du Colombier             /*-- end uc = MTF ( nextSym-1 ) --*/
709*9a747e4fSDavid du Colombier 
710*9a747e4fSDavid du Colombier             s->unzftab[s->seqToUnseq[uc]]++;
711*9a747e4fSDavid du Colombier             if (0 && s->smallDecompress)
712*9a747e4fSDavid du Colombier                s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
713*9a747e4fSDavid du Colombier                s->tt[nblock]   = (UInt32)(s->seqToUnseq[uc]);
714*9a747e4fSDavid du Colombier             nblock++;
715*9a747e4fSDavid du Colombier 
716*9a747e4fSDavid du Colombier             GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
717*9a747e4fSDavid du Colombier             continue;
718*9a747e4fSDavid du Colombier          }
719*9a747e4fSDavid du Colombier       }
720*9a747e4fSDavid du Colombier 
721*9a747e4fSDavid du Colombier       /* Now we know what nblock is, we can do a better sanity
722*9a747e4fSDavid du Colombier          check on s->origPtr.
723*9a747e4fSDavid du Colombier       */
724*9a747e4fSDavid du Colombier       if (s->origPtr < 0 || s->origPtr >= nblock)
725*9a747e4fSDavid du Colombier          RETURN(BZ_DATA_ERROR);
726*9a747e4fSDavid du Colombier 
727*9a747e4fSDavid du Colombier       s->state_out_len = 0;
728*9a747e4fSDavid du Colombier       s->state_out_ch  = 0;
729*9a747e4fSDavid du Colombier       BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
730*9a747e4fSDavid du Colombier       s->state = BZ_X_OUTPUT;
731*9a747e4fSDavid du Colombier     //  if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
732*9a747e4fSDavid du Colombier 
733*9a747e4fSDavid du Colombier       /*-- Set up cftab to facilitate generation of T^(-1) --*/
734*9a747e4fSDavid du Colombier       s->cftab[0] = 0;
735*9a747e4fSDavid du Colombier       for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
736*9a747e4fSDavid du Colombier       for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
737*9a747e4fSDavid du Colombier 
738*9a747e4fSDavid du Colombier       if (0 && s->smallDecompress) {
739*9a747e4fSDavid du Colombier 
740*9a747e4fSDavid du Colombier          /*-- Make a copy of cftab, used in generation of T --*/
741*9a747e4fSDavid du Colombier          for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
742*9a747e4fSDavid du Colombier 
743*9a747e4fSDavid du Colombier          /*-- compute the T vector --*/
744*9a747e4fSDavid du Colombier          for (i = 0; i < nblock; i++) {
745*9a747e4fSDavid du Colombier             uc = (UChar)(s->ll16[i]);
746*9a747e4fSDavid du Colombier             SET_LL(i, s->cftabCopy[uc]);
747*9a747e4fSDavid du Colombier             s->cftabCopy[uc]++;
748*9a747e4fSDavid du Colombier          }
749*9a747e4fSDavid du Colombier 
750*9a747e4fSDavid du Colombier          /*-- Compute T^(-1) by pointer reversal on T --*/
751*9a747e4fSDavid du Colombier          i = s->origPtr;
752*9a747e4fSDavid du Colombier          j = GET_LL(i);
753*9a747e4fSDavid du Colombier          do {
754*9a747e4fSDavid du Colombier             Int32 tmp = GET_LL(j);
755*9a747e4fSDavid du Colombier             SET_LL(j, i);
756*9a747e4fSDavid du Colombier             i = j;
757*9a747e4fSDavid du Colombier             j = tmp;
758*9a747e4fSDavid du Colombier          }
759*9a747e4fSDavid du Colombier             while (i != s->origPtr);
760*9a747e4fSDavid du Colombier 
761*9a747e4fSDavid du Colombier          s->tPos = s->origPtr;
762*9a747e4fSDavid du Colombier          s->nblock_used = 0;
763*9a747e4fSDavid du Colombier          if (s->blockRandomised) {
764*9a747e4fSDavid du Colombier             BZ_RAND_INIT_MASK;
765*9a747e4fSDavid du Colombier             BZ_GET_SMALL(s->k0); s->nblock_used++;
766*9a747e4fSDavid du Colombier             BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
767*9a747e4fSDavid du Colombier          } else {
768*9a747e4fSDavid du Colombier             BZ_GET_SMALL(s->k0); s->nblock_used++;
769*9a747e4fSDavid du Colombier          }
770*9a747e4fSDavid du Colombier 
771*9a747e4fSDavid du Colombier       } else {
772*9a747e4fSDavid du Colombier 
773*9a747e4fSDavid du Colombier          /*-- compute the T^(-1) vector --*/
774*9a747e4fSDavid du Colombier          for (i = 0; i < nblock; i++) {
775*9a747e4fSDavid du Colombier             uc = (UChar)(s->tt[i] & 0xff);
776*9a747e4fSDavid du Colombier             s->tt[s->cftab[uc]] |= (i << 8);
777*9a747e4fSDavid du Colombier             s->cftab[uc]++;
778*9a747e4fSDavid du Colombier          }
779*9a747e4fSDavid du Colombier 
780*9a747e4fSDavid du Colombier          s->tPos = s->tt[s->origPtr] >> 8;
781*9a747e4fSDavid du Colombier          s->nblock_used = 0;
782*9a747e4fSDavid du Colombier          if (s->blockRandomised) {
783*9a747e4fSDavid du Colombier             BZ_RAND_INIT_MASK;
784*9a747e4fSDavid du Colombier             BZ_GET_FAST(s->k0); s->nblock_used++;
785*9a747e4fSDavid du Colombier             BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
786*9a747e4fSDavid du Colombier          } else {
787*9a747e4fSDavid du Colombier             BZ_GET_FAST(s->k0); s->nblock_used++;
788*9a747e4fSDavid du Colombier          }
789*9a747e4fSDavid du Colombier 
790*9a747e4fSDavid du Colombier       }
791*9a747e4fSDavid du Colombier 
792*9a747e4fSDavid du Colombier       RETURN(BZ_OK);
793*9a747e4fSDavid du Colombier 
794*9a747e4fSDavid du Colombier 
795*9a747e4fSDavid du Colombier 
796*9a747e4fSDavid du Colombier     endhdr_2:
797*9a747e4fSDavid du Colombier 
798*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_ENDHDR_2, uc);
799*9a747e4fSDavid du Colombier       if (uc != 0x72) RETURN(BZ_DATA_ERROR);
800*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_ENDHDR_3, uc);
801*9a747e4fSDavid du Colombier       if (uc != 0x45) RETURN(BZ_DATA_ERROR);
802*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_ENDHDR_4, uc);
803*9a747e4fSDavid du Colombier       if (uc != 0x38) RETURN(BZ_DATA_ERROR);
804*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_ENDHDR_5, uc);
805*9a747e4fSDavid du Colombier       if (uc != 0x50) RETURN(BZ_DATA_ERROR);
806*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_ENDHDR_6, uc);
807*9a747e4fSDavid du Colombier       if (uc != 0x90) RETURN(BZ_DATA_ERROR);
808*9a747e4fSDavid du Colombier 
809*9a747e4fSDavid du Colombier       s->storedCombinedCRC = 0;
810*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_CCRC_1, uc);
811*9a747e4fSDavid du Colombier       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
812*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_CCRC_2, uc);
813*9a747e4fSDavid du Colombier       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
814*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_CCRC_3, uc);
815*9a747e4fSDavid du Colombier       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
816*9a747e4fSDavid du Colombier       GET_UCHAR(BZ_X_CCRC_4, uc);
817*9a747e4fSDavid du Colombier       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
818*9a747e4fSDavid du Colombier 
819*9a747e4fSDavid du Colombier       s->state = BZ_X_IDLE;
820*9a747e4fSDavid du Colombier       RETURN(BZ_STREAM_END);
821*9a747e4fSDavid du Colombier 
822*9a747e4fSDavid du Colombier       default: AssertH ( False, 4001 );
823*9a747e4fSDavid du Colombier    }
824*9a747e4fSDavid du Colombier 
825*9a747e4fSDavid du Colombier    AssertH ( False, 4002 );
826*9a747e4fSDavid du Colombier 
827*9a747e4fSDavid du Colombier    save_state_and_return:
828*9a747e4fSDavid du Colombier 
829*9a747e4fSDavid du Colombier    s->save_i           = i;
830*9a747e4fSDavid du Colombier    s->save_j           = j;
831*9a747e4fSDavid du Colombier    s->save_t           = t;
832*9a747e4fSDavid du Colombier    s->save_alphaSize   = alphaSize;
833*9a747e4fSDavid du Colombier    s->save_nGroups     = nGroups;
834*9a747e4fSDavid du Colombier    s->save_nSelectors  = nSelectors;
835*9a747e4fSDavid du Colombier    s->save_EOB         = EOB;
836*9a747e4fSDavid du Colombier    s->save_groupNo     = groupNo;
837*9a747e4fSDavid du Colombier    s->save_groupPos    = groupPos;
838*9a747e4fSDavid du Colombier    s->save_nextSym     = nextSym;
839*9a747e4fSDavid du Colombier    s->save_nblockMAX   = nblockMAX;
840*9a747e4fSDavid du Colombier    s->save_nblock      = nblock;
841*9a747e4fSDavid du Colombier    s->save_es          = es;
842*9a747e4fSDavid du Colombier    s->save_N           = N;
843*9a747e4fSDavid du Colombier    s->save_curr        = curr;
844*9a747e4fSDavid du Colombier    s->save_zt          = zt;
845*9a747e4fSDavid du Colombier    s->save_zn          = zn;
846*9a747e4fSDavid du Colombier    s->save_zvec        = zvec;
847*9a747e4fSDavid du Colombier    s->save_zj          = zj;
848*9a747e4fSDavid du Colombier    s->save_gSel        = gSel;
849*9a747e4fSDavid du Colombier    s->save_gMinlen     = gMinlen;
850*9a747e4fSDavid du Colombier    s->save_gLimit      = gLimit;
851*9a747e4fSDavid du Colombier    s->save_gBase       = gBase;
852*9a747e4fSDavid du Colombier    s->save_gPerm       = gPerm;
853*9a747e4fSDavid du Colombier 
854*9a747e4fSDavid du Colombier    return retVal;
855*9a747e4fSDavid du Colombier }
856*9a747e4fSDavid du Colombier 
857*9a747e4fSDavid du Colombier 
858*9a747e4fSDavid du Colombier /*-------------------------------------------------------------*/
859*9a747e4fSDavid du Colombier /*--- end                                      decompress.c ---*/
860*9a747e4fSDavid du Colombier /*-------------------------------------------------------------*/
861