* Patch by Pantelis Antoniou, 14 Sep 2004:
[oweals/u-boot.git] / lib_generic / bzlib.c
1 #include <config.h>
2 #include <common.h>
3 #include <watchdog.h>
4 #ifdef CONFIG_BZIP2
5
6 /*
7  * This file is a modified version of bzlib.c from the bzip2-1.0.2
8  * distribution which can be found at http://sources.redhat.com/bzip2/
9  */
10
11 /*-------------------------------------------------------------*/
12 /*--- Library top-level functions.                          ---*/
13 /*---                                               bzlib.c ---*/
14 /*-------------------------------------------------------------*/
15
16 /*--
17   This file is a part of bzip2 and/or libbzip2, a program and
18   library for lossless, block-sorting data compression.
19
20   Copyright (C) 1996-2002 Julian R Seward.  All rights reserved.
21
22   Redistribution and use in source and binary forms, with or without
23   modification, are permitted provided that the following conditions
24   are met:
25
26   1. Redistributions of source code must retain the above copyright
27      notice, this list of conditions and the following disclaimer.
28
29   2. The origin of this software must not be misrepresented; you must
30      not claim that you wrote the original software.  If you use this
31      software in a product, an acknowledgment in the product
32      documentation would be appreciated but is not required.
33
34   3. Altered source versions must be plainly marked as such, and must
35      not be misrepresented as being the original software.
36
37   4. The name of the author may not be used to endorse or promote
38      products derived from this software without specific prior written
39      permission.
40
41   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
42   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
45   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
47   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
48   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
50   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
51   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52
53   Julian Seward, Cambridge, UK.
54   jseward@acm.org
55   bzip2/libbzip2 version 1.0 of 21 March 2000
56
57   This program is based on (at least) the work of:
58      Mike Burrows
59      David Wheeler
60      Peter Fenwick
61      Alistair Moffat
62      Radford Neal
63      Ian H. Witten
64      Robert Sedgewick
65      Jon L. Bentley
66
67   For more information on these sources, see the manual.
68 --*/
69
70 /*--
71    CHANGES
72    ~~~~~~~
73    0.9.0 -- original version.
74
75    0.9.0a/b -- no changes in this file.
76
77    0.9.0c
78       * made zero-length BZ_FLUSH work correctly in bzCompress().
79       * fixed bzWrite/bzRead to ignore zero-length requests.
80       * fixed bzread to correctly handle read requests after EOF.
81       * wrong parameter order in call to bzDecompressInit in
82         bzBuffToBuffDecompress.  Fixed.
83 --*/
84
85 #include "bzlib_private.h"
86
87 /*---------------------------------------------------*/
88 /*--- Compression stuff                           ---*/
89 /*---------------------------------------------------*/
90
91
92 /*---------------------------------------------------*/
93 #ifndef BZ_NO_STDIO
94 void BZ2_bz__AssertH__fail ( int errcode )
95 {
96    fprintf(stderr,
97       "\n\nbzip2/libbzip2: internal error number %d.\n"
98       "This is a bug in bzip2/libbzip2, %s.\n"
99       "Please report it to me at: jseward@acm.org.  If this happened\n"
100       "when you were using some program which uses libbzip2 as a\n"
101       "component, you should also report this bug to the author(s)\n"
102       "of that program.  Please make an effort to report this bug;\n"
103       "timely and accurate bug reports eventually lead to higher\n"
104       "quality software.  Thanks.  Julian Seward, 30 December 2001.\n\n",
105       errcode,
106       BZ2_bzlibVersion()
107    );
108
109    if (errcode == 1007) {
110    fprintf(stderr,
111       "\n*** A special note about internal error number 1007 ***\n"
112       "\n"
113       "Experience suggests that a common cause of i.e. 1007\n"
114       "is unreliable memory or other hardware.  The 1007 assertion\n"
115       "just happens to cross-check the results of huge numbers of\n"
116       "memory reads/writes, and so acts (unintendedly) as a stress\n"
117       "test of your memory system.\n"
118       "\n"
119       "I suggest the following: try compressing the file again,\n"
120       "possibly monitoring progress in detail with the -vv flag.\n"
121       "\n"
122       "* If the error cannot be reproduced, and/or happens at different\n"
123       "  points in compression, you may have a flaky memory system.\n"
124       "  Try a memory-test program.  I have used Memtest86\n"
125       "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n"
126       "  Memtest86 tests memory much more thorougly than your BIOSs\n"
127       "  power-on test, and may find failures that the BIOS doesn't.\n"
128       "\n"
129       "* If the error can be repeatably reproduced, this is a bug in\n"
130       "  bzip2, and I would very much like to hear about it.  Please\n"
131       "  let me know, and, ideally, save a copy of the file causing the\n"
132       "  problem -- without which I will be unable to investigate it.\n"
133       "\n"
134    );
135    }
136
137    exit(3);
138 }
139 #endif
140
141
142 /*---------------------------------------------------*/
143 static
144 int bz_config_ok ( void )
145 {
146    if (sizeof(int)   != 4) return 0;
147    if (sizeof(short) != 2) return 0;
148    if (sizeof(char)  != 1) return 0;
149    return 1;
150 }
151
152
153 /*---------------------------------------------------*/
154 static
155 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
156 {
157    void* v = malloc ( items * size );
158    return v;
159 }
160
161 static
162 void default_bzfree ( void* opaque, void* addr )
163 {
164    if (addr != NULL) free ( addr );
165 }
166
167 #ifndef BZ_NO_COMPRESS
168 /*---------------------------------------------------*/
169 static
170 void prepare_new_block ( EState* s )
171 {
172    Int32 i;
173    s->nblock = 0;
174    s->numZ = 0;
175    s->state_out_pos = 0;
176    BZ_INITIALISE_CRC ( s->blockCRC );
177    for (i = 0; i < 256; i++) s->inUse[i] = False;
178    s->blockNo++;
179 }
180
181
182 /*---------------------------------------------------*/
183 static
184 void init_RL ( EState* s )
185 {
186    s->state_in_ch  = 256;
187    s->state_in_len = 0;
188 }
189
190
191 static
192 Bool isempty_RL ( EState* s )
193 {
194    if (s->state_in_ch < 256 && s->state_in_len > 0)
195       return False; else
196       return True;
197 }
198
199 /*---------------------------------------------------*/
200 int BZ_API(BZ2_bzCompressInit)
201                     ( bz_stream* strm,
202                      int        blockSize100k,
203                      int        verbosity,
204                      int        workFactor )
205 {
206    Int32   n;
207    EState* s;
208
209    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
210
211    if (strm == NULL ||
212        blockSize100k < 1 || blockSize100k > 9 ||
213        workFactor < 0 || workFactor > 250)
214      return BZ_PARAM_ERROR;
215
216    if (workFactor == 0) workFactor = 30;
217    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
218    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
219
220    s = BZALLOC( sizeof(EState) );
221    if (s == NULL) return BZ_MEM_ERROR;
222    s->strm = strm;
223
224    s->arr1 = NULL;
225    s->arr2 = NULL;
226    s->ftab = NULL;
227
228    n       = 100000 * blockSize100k;
229    s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
230    s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
231    s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
232
233    if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
234       if (s->arr1 != NULL) BZFREE(s->arr1);
235       if (s->arr2 != NULL) BZFREE(s->arr2);
236       if (s->ftab != NULL) BZFREE(s->ftab);
237       if (s       != NULL) BZFREE(s);
238       return BZ_MEM_ERROR;
239    }
240
241    s->blockNo           = 0;
242    s->state             = BZ_S_INPUT;
243    s->mode              = BZ_M_RUNNING;
244    s->combinedCRC       = 0;
245    s->blockSize100k     = blockSize100k;
246    s->nblockMAX         = 100000 * blockSize100k - 19;
247    s->verbosity         = verbosity;
248    s->workFactor        = workFactor;
249
250    s->block             = (UChar*)s->arr2;
251    s->mtfv              = (UInt16*)s->arr1;
252    s->zbits             = NULL;
253    s->ptr               = (UInt32*)s->arr1;
254
255    strm->state          = s;
256    strm->total_in_lo32  = 0;
257    strm->total_in_hi32  = 0;
258    strm->total_out_lo32 = 0;
259    strm->total_out_hi32 = 0;
260    init_RL ( s );
261    prepare_new_block ( s );
262    return BZ_OK;
263 }
264
265
266 /*---------------------------------------------------*/
267 static
268 void add_pair_to_block ( EState* s )
269 {
270    Int32 i;
271    UChar ch = (UChar)(s->state_in_ch);
272    for (i = 0; i < s->state_in_len; i++) {
273       BZ_UPDATE_CRC( s->blockCRC, ch );
274    }
275    s->inUse[s->state_in_ch] = True;
276    switch (s->state_in_len) {
277       case 1:
278          s->block[s->nblock] = (UChar)ch; s->nblock++;
279          break;
280       case 2:
281          s->block[s->nblock] = (UChar)ch; s->nblock++;
282          s->block[s->nblock] = (UChar)ch; s->nblock++;
283          break;
284       case 3:
285          s->block[s->nblock] = (UChar)ch; s->nblock++;
286          s->block[s->nblock] = (UChar)ch; s->nblock++;
287          s->block[s->nblock] = (UChar)ch; s->nblock++;
288          break;
289       default:
290          s->inUse[s->state_in_len-4] = True;
291          s->block[s->nblock] = (UChar)ch; s->nblock++;
292          s->block[s->nblock] = (UChar)ch; s->nblock++;
293          s->block[s->nblock] = (UChar)ch; s->nblock++;
294          s->block[s->nblock] = (UChar)ch; s->nblock++;
295          s->block[s->nblock] = ((UChar)(s->state_in_len-4));
296          s->nblock++;
297          break;
298    }
299 }
300
301
302 /*---------------------------------------------------*/
303 static
304 void flush_RL ( EState* s )
305 {
306    if (s->state_in_ch < 256) add_pair_to_block ( s );
307    init_RL ( s );
308 }
309
310
311 /*---------------------------------------------------*/
312 #define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
313 {                                                 \
314    UInt32 zchh = (UInt32)(zchh0);                 \
315    /*-- fast track the common case --*/           \
316    if (zchh != zs->state_in_ch &&                 \
317        zs->state_in_len == 1) {                   \
318       UChar ch = (UChar)(zs->state_in_ch);        \
319       BZ_UPDATE_CRC( zs->blockCRC, ch );          \
320       zs->inUse[zs->state_in_ch] = True;          \
321       zs->block[zs->nblock] = (UChar)ch;          \
322       zs->nblock++;                               \
323       zs->state_in_ch = zchh;                     \
324    }                                              \
325    else                                           \
326    /*-- general, uncommon cases --*/              \
327    if (zchh != zs->state_in_ch ||                 \
328       zs->state_in_len == 255) {                  \
329       if (zs->state_in_ch < 256)                  \
330          add_pair_to_block ( zs );                \
331       zs->state_in_ch = zchh;                     \
332       zs->state_in_len = 1;                       \
333    } else {                                       \
334       zs->state_in_len++;                         \
335    }                                              \
336 }
337
338
339 /*---------------------------------------------------*/
340 static
341 Bool copy_input_until_stop ( EState* s )
342 {
343    Bool progress_in = False;
344
345    if (s->mode == BZ_M_RUNNING) {
346
347       /*-- fast track the common case --*/
348       while (True) {
349          /*-- block full? --*/
350          if (s->nblock >= s->nblockMAX) break;
351          /*-- no input? --*/
352          if (s->strm->avail_in == 0) break;
353          progress_in = True;
354          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
355          s->strm->next_in++;
356          s->strm->avail_in--;
357          s->strm->total_in_lo32++;
358          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
359       }
360
361    } else {
362
363       /*-- general, uncommon case --*/
364       while (True) {
365          /*-- block full? --*/
366          if (s->nblock >= s->nblockMAX) break;
367          /*-- no input? --*/
368          if (s->strm->avail_in == 0) break;
369          /*-- flush/finish end? --*/
370          if (s->avail_in_expect == 0) break;
371          progress_in = True;
372          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
373          s->strm->next_in++;
374          s->strm->avail_in--;
375          s->strm->total_in_lo32++;
376          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
377          s->avail_in_expect--;
378       }
379    }
380    return progress_in;
381 }
382
383
384 /*---------------------------------------------------*/
385 static
386 Bool copy_output_until_stop ( EState* s )
387 {
388    Bool progress_out = False;
389
390    while (True) {
391
392       /*-- no output space? --*/
393       if (s->strm->avail_out == 0) break;
394
395       /*-- block done? --*/
396       if (s->state_out_pos >= s->numZ) break;
397
398       progress_out = True;
399       *(s->strm->next_out) = s->zbits[s->state_out_pos];
400       s->state_out_pos++;
401       s->strm->avail_out--;
402       s->strm->next_out++;
403       s->strm->total_out_lo32++;
404       if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
405    }
406
407    return progress_out;
408 }
409
410
411 /*---------------------------------------------------*/
412 static
413 Bool handle_compress ( bz_stream* strm )
414 {
415    Bool progress_in  = False;
416    Bool progress_out = False;
417    EState* s = strm->state;
418
419    while (True) {
420
421       if (s->state == BZ_S_OUTPUT) {
422          progress_out |= copy_output_until_stop ( s );
423          if (s->state_out_pos < s->numZ) break;
424          if (s->mode == BZ_M_FINISHING &&
425              s->avail_in_expect == 0 &&
426              isempty_RL(s)) break;
427          prepare_new_block ( s );
428          s->state = BZ_S_INPUT;
429          if (s->mode == BZ_M_FLUSHING &&
430              s->avail_in_expect == 0 &&
431              isempty_RL(s)) break;
432       }
433
434       if (s->state == BZ_S_INPUT) {
435          progress_in |= copy_input_until_stop ( s );
436          if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
437             flush_RL ( s );
438             BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
439             s->state = BZ_S_OUTPUT;
440          }
441          else
442          if (s->nblock >= s->nblockMAX) {
443             BZ2_compressBlock ( s, False );
444             s->state = BZ_S_OUTPUT;
445          }
446          else
447          if (s->strm->avail_in == 0) {
448             break;
449          }
450       }
451
452    }
453
454    return progress_in || progress_out;
455 }
456
457
458 /*---------------------------------------------------*/
459 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
460 {
461    Bool progress;
462    EState* s;
463    if (strm == NULL) return BZ_PARAM_ERROR;
464    s = strm->state;
465    if (s == NULL) return BZ_PARAM_ERROR;
466    if (s->strm != strm) return BZ_PARAM_ERROR;
467
468    preswitch:
469    switch (s->mode) {
470
471       case BZ_M_IDLE:
472          return BZ_SEQUENCE_ERROR;
473
474       case BZ_M_RUNNING:
475          if (action == BZ_RUN) {
476             progress = handle_compress ( strm );
477             return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
478          }
479          else
480          if (action == BZ_FLUSH) {
481             s->avail_in_expect = strm->avail_in;
482             s->mode = BZ_M_FLUSHING;
483             goto preswitch;
484          }
485          else
486          if (action == BZ_FINISH) {
487             s->avail_in_expect = strm->avail_in;
488             s->mode = BZ_M_FINISHING;
489             goto preswitch;
490          }
491          else
492             return BZ_PARAM_ERROR;
493
494       case BZ_M_FLUSHING:
495          if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
496          if (s->avail_in_expect != s->strm->avail_in)
497             return BZ_SEQUENCE_ERROR;
498          progress = handle_compress ( strm );
499          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
500              s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
501          s->mode = BZ_M_RUNNING;
502          return BZ_RUN_OK;
503
504       case BZ_M_FINISHING:
505          if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
506          if (s->avail_in_expect != s->strm->avail_in)
507             return BZ_SEQUENCE_ERROR;
508          progress = handle_compress ( strm );
509          if (!progress) return BZ_SEQUENCE_ERROR;
510          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
511              s->state_out_pos < s->numZ) return BZ_FINISH_OK;
512          s->mode = BZ_M_IDLE;
513          return BZ_STREAM_END;
514    }
515    return BZ_OK; /*--not reached--*/
516 }
517
518
519 /*---------------------------------------------------*/
520 int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
521 {
522    EState* s;
523    if (strm == NULL) return BZ_PARAM_ERROR;
524    s = strm->state;
525    if (s == NULL) return BZ_PARAM_ERROR;
526    if (s->strm != strm) return BZ_PARAM_ERROR;
527
528    if (s->arr1 != NULL) BZFREE(s->arr1);
529    if (s->arr2 != NULL) BZFREE(s->arr2);
530    if (s->ftab != NULL) BZFREE(s->ftab);
531    BZFREE(strm->state);
532
533    strm->state = NULL;
534
535    return BZ_OK;
536 }
537 #endif /* BZ_NO_COMPRESS */
538
539 /*---------------------------------------------------*/
540 /*--- Decompression stuff                         ---*/
541 /*---------------------------------------------------*/
542
543 /*---------------------------------------------------*/
544 int BZ_API(BZ2_bzDecompressInit)
545                      ( bz_stream* strm,
546                        int        verbosity,
547                        int        small )
548 {
549    DState* s;
550
551    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
552
553    if (strm == NULL) return BZ_PARAM_ERROR;
554    if (small != 0 && small != 1) return BZ_PARAM_ERROR;
555    if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
556
557    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
558    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
559
560    s = BZALLOC( sizeof(DState) );
561    if (s == NULL) return BZ_MEM_ERROR;
562    s->strm                  = strm;
563    strm->state              = s;
564    s->state                 = BZ_X_MAGIC_1;
565    s->bsLive                = 0;
566    s->bsBuff                = 0;
567    s->calculatedCombinedCRC = 0;
568    strm->total_in_lo32      = 0;
569    strm->total_in_hi32      = 0;
570    strm->total_out_lo32     = 0;
571    strm->total_out_hi32     = 0;
572    s->smallDecompress       = (Bool)small;
573    s->ll4                   = NULL;
574    s->ll16                  = NULL;
575    s->tt                    = NULL;
576    s->currBlockNo           = 0;
577    s->verbosity             = verbosity;
578
579    return BZ_OK;
580 }
581
582
583 /*---------------------------------------------------*/
584 static
585 void unRLE_obuf_to_output_FAST ( DState* s )
586 {
587    UChar k1;
588
589    if (s->blockRandomised) {
590
591       while (True) {
592          /* try to finish existing run */
593          while (True) {
594             if (s->strm->avail_out == 0) return;
595             if (s->state_out_len == 0) break;
596             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
597             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
598             s->state_out_len--;
599             s->strm->next_out++;
600             s->strm->avail_out--;
601             s->strm->total_out_lo32++;
602             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
603          }
604
605          /* can a new run be started? */
606          if (s->nblock_used == s->save_nblock+1) return;
607
608
609          s->state_out_len = 1;
610          s->state_out_ch = s->k0;
611          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
612          k1 ^= BZ_RAND_MASK; s->nblock_used++;
613          if (s->nblock_used == s->save_nblock+1) continue;
614          if (k1 != s->k0) { s->k0 = k1; continue; };
615
616          s->state_out_len = 2;
617          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
618          k1 ^= BZ_RAND_MASK; s->nblock_used++;
619          if (s->nblock_used == s->save_nblock+1) continue;
620          if (k1 != s->k0) { s->k0 = k1; continue; };
621
622          s->state_out_len = 3;
623          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
624          k1 ^= BZ_RAND_MASK; s->nblock_used++;
625          if (s->nblock_used == s->save_nblock+1) continue;
626          if (k1 != s->k0) { s->k0 = k1; continue; };
627
628          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
629          k1 ^= BZ_RAND_MASK; s->nblock_used++;
630          s->state_out_len = ((Int32)k1) + 4;
631          BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
632          s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
633       }
634
635    } else {
636
637       /* restore */
638       UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
639       UChar         c_state_out_ch       = s->state_out_ch;
640       Int32         c_state_out_len      = s->state_out_len;
641       Int32         c_nblock_used        = s->nblock_used;
642       Int32         c_k0                 = s->k0;
643       UInt32*       c_tt                 = s->tt;
644       UInt32        c_tPos               = s->tPos;
645       char*         cs_next_out          = s->strm->next_out;
646       unsigned int  cs_avail_out         = s->strm->avail_out;
647       /* end restore */
648
649       UInt32       avail_out_INIT = cs_avail_out;
650       Int32        s_save_nblockPP = s->save_nblock+1;
651       unsigned int total_out_lo32_old;
652
653       while (True) {
654
655          /* try to finish existing run */
656          if (c_state_out_len > 0) {
657             while (True) {
658                if (cs_avail_out == 0) goto return_notr;
659                if (c_state_out_len == 1) break;
660                *( (UChar*)(cs_next_out) ) = c_state_out_ch;
661                BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
662                c_state_out_len--;
663                cs_next_out++;
664                cs_avail_out--;
665             }
666             s_state_out_len_eq_one:
667             {
668                if (cs_avail_out == 0) {
669                   c_state_out_len = 1; goto return_notr;
670                };
671                *( (UChar*)(cs_next_out) ) = c_state_out_ch;
672                BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
673                cs_next_out++;
674                cs_avail_out--;
675             }
676          }
677          /* can a new run be started? */
678          if (c_nblock_used == s_save_nblockPP) {
679             c_state_out_len = 0; goto return_notr;
680          };
681          c_state_out_ch = c_k0;
682          BZ_GET_FAST_C(k1); c_nblock_used++;
683          if (k1 != c_k0) {
684             c_k0 = k1; goto s_state_out_len_eq_one;
685          };
686          if (c_nblock_used == s_save_nblockPP)
687             goto s_state_out_len_eq_one;
688
689          c_state_out_len = 2;
690          BZ_GET_FAST_C(k1); c_nblock_used++;
691          if (c_nblock_used == s_save_nblockPP) continue;
692          if (k1 != c_k0) { c_k0 = k1; continue; };
693
694          c_state_out_len = 3;
695          BZ_GET_FAST_C(k1); c_nblock_used++;
696          if (c_nblock_used == s_save_nblockPP) continue;
697          if (k1 != c_k0) { c_k0 = k1; continue; };
698
699          BZ_GET_FAST_C(k1); c_nblock_used++;
700          c_state_out_len = ((Int32)k1) + 4;
701          BZ_GET_FAST_C(c_k0); c_nblock_used++;
702       }
703
704       return_notr:
705       total_out_lo32_old = s->strm->total_out_lo32;
706       s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
707       if (s->strm->total_out_lo32 < total_out_lo32_old)
708          s->strm->total_out_hi32++;
709
710       /* save */
711       s->calculatedBlockCRC = c_calculatedBlockCRC;
712       s->state_out_ch       = c_state_out_ch;
713       s->state_out_len      = c_state_out_len;
714       s->nblock_used        = c_nblock_used;
715       s->k0                 = c_k0;
716       s->tt                 = c_tt;
717       s->tPos               = c_tPos;
718       s->strm->next_out     = cs_next_out;
719       s->strm->avail_out    = cs_avail_out;
720       /* end save */
721    }
722 }
723
724
725 /*---------------------------------------------------*/
726 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
727 {
728    Int32 nb, na, mid;
729    nb = 0;
730    na = 256;
731    do {
732       mid = (nb + na) >> 1;
733       if (indx >= cftab[mid]) nb = mid; else na = mid;
734    }
735    while (na - nb != 1);
736    return nb;
737 }
738
739
740 /*---------------------------------------------------*/
741 static
742 void unRLE_obuf_to_output_SMALL ( DState* s )
743 {
744    UChar k1;
745
746    if (s->blockRandomised) {
747
748       while (True) {
749          /* try to finish existing run */
750          while (True) {
751             if (s->strm->avail_out == 0) return;
752             if (s->state_out_len == 0) break;
753             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
754             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
755             s->state_out_len--;
756             s->strm->next_out++;
757             s->strm->avail_out--;
758             s->strm->total_out_lo32++;
759             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
760          }
761
762          /* can a new run be started? */
763          if (s->nblock_used == s->save_nblock+1) return;
764
765
766          s->state_out_len = 1;
767          s->state_out_ch = s->k0;
768          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
769          k1 ^= BZ_RAND_MASK; s->nblock_used++;
770          if (s->nblock_used == s->save_nblock+1) continue;
771          if (k1 != s->k0) { s->k0 = k1; continue; };
772
773          s->state_out_len = 2;
774          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
775          k1 ^= BZ_RAND_MASK; s->nblock_used++;
776          if (s->nblock_used == s->save_nblock+1) continue;
777          if (k1 != s->k0) { s->k0 = k1; continue; };
778
779          s->state_out_len = 3;
780          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
781          k1 ^= BZ_RAND_MASK; s->nblock_used++;
782          if (s->nblock_used == s->save_nblock+1) continue;
783          if (k1 != s->k0) { s->k0 = k1; continue; };
784
785          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
786          k1 ^= BZ_RAND_MASK; s->nblock_used++;
787          s->state_out_len = ((Int32)k1) + 4;
788          BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
789          s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
790       }
791
792    } else {
793
794       while (True) {
795          /* try to finish existing run */
796          while (True) {
797             if (s->strm->avail_out == 0) return;
798             if (s->state_out_len == 0) break;
799             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
800             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
801             s->state_out_len--;
802             s->strm->next_out++;
803             s->strm->avail_out--;
804             s->strm->total_out_lo32++;
805             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
806          }
807
808          /* can a new run be started? */
809          if (s->nblock_used == s->save_nblock+1) return;
810
811          s->state_out_len = 1;
812          s->state_out_ch = s->k0;
813          BZ_GET_SMALL(k1); s->nblock_used++;
814          if (s->nblock_used == s->save_nblock+1) continue;
815          if (k1 != s->k0) { s->k0 = k1; continue; };
816
817          s->state_out_len = 2;
818          BZ_GET_SMALL(k1); s->nblock_used++;
819          if (s->nblock_used == s->save_nblock+1) continue;
820          if (k1 != s->k0) { s->k0 = k1; continue; };
821
822          s->state_out_len = 3;
823          BZ_GET_SMALL(k1); s->nblock_used++;
824          if (s->nblock_used == s->save_nblock+1) continue;
825          if (k1 != s->k0) { s->k0 = k1; continue; };
826
827          BZ_GET_SMALL(k1); s->nblock_used++;
828          s->state_out_len = ((Int32)k1) + 4;
829          BZ_GET_SMALL(s->k0); s->nblock_used++;
830       }
831
832    }
833 }
834
835
836 /*---------------------------------------------------*/
837 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
838 {
839    DState* s;
840    if (strm == NULL) return BZ_PARAM_ERROR;
841    s = strm->state;
842    if (s == NULL) return BZ_PARAM_ERROR;
843    if (s->strm != strm) return BZ_PARAM_ERROR;
844
845    while (True) {
846 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
847         WATCHDOG_RESET();
848 #endif
849       if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
850       if (s->state == BZ_X_OUTPUT) {
851          if (s->smallDecompress)
852             unRLE_obuf_to_output_SMALL ( s ); else
853             unRLE_obuf_to_output_FAST  ( s );
854          if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
855             BZ_FINALISE_CRC ( s->calculatedBlockCRC );
856             if (s->verbosity >= 3)
857                VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC,
858                           s->calculatedBlockCRC );
859             if (s->verbosity >= 2) VPrintf0 ( "]" );
860             if (s->calculatedBlockCRC != s->storedBlockCRC)
861                return BZ_DATA_ERROR;
862             s->calculatedCombinedCRC
863                = (s->calculatedCombinedCRC << 1) |
864                     (s->calculatedCombinedCRC >> 31);
865             s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
866             s->state = BZ_X_BLKHDR_1;
867          } else {
868             return BZ_OK;
869          }
870       }
871       if (s->state >= BZ_X_MAGIC_1) {
872          Int32 r = BZ2_decompress ( s );
873          if (r == BZ_STREAM_END) {
874             if (s->verbosity >= 3)
875                VPrintf2 ( "\n    combined CRCs: stored = 0x%x, computed = 0x%x",
876                           s->storedCombinedCRC, s->calculatedCombinedCRC );
877             if (s->calculatedCombinedCRC != s->storedCombinedCRC)
878                return BZ_DATA_ERROR;
879             return r;
880          }
881          if (s->state != BZ_X_OUTPUT) return r;
882       }
883    }
884
885    AssertH ( 0, 6001 );
886
887    return 0;  /*NOTREACHED*/
888 }
889
890
891 /*---------------------------------------------------*/
892 int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
893 {
894    DState* s;
895    if (strm == NULL) return BZ_PARAM_ERROR;
896    s = strm->state;
897    if (s == NULL) return BZ_PARAM_ERROR;
898    if (s->strm != strm) return BZ_PARAM_ERROR;
899
900    if (s->tt   != NULL) BZFREE(s->tt);
901    if (s->ll16 != NULL) BZFREE(s->ll16);
902    if (s->ll4  != NULL) BZFREE(s->ll4);
903
904    BZFREE(strm->state);
905    strm->state = NULL;
906
907    return BZ_OK;
908 }
909
910
911 #ifndef BZ_NO_STDIO
912 /*---------------------------------------------------*/
913 /*--- File I/O stuff                              ---*/
914 /*---------------------------------------------------*/
915
916 #define BZ_SETERR(eee)                    \
917 {                                         \
918    if (bzerror != NULL) *bzerror = eee;   \
919    if (bzf != NULL) bzf->lastErr = eee;   \
920 }
921
922 typedef
923    struct {
924       FILE*     handle;
925       Char      buf[BZ_MAX_UNUSED];
926       Int32     bufN;
927       Bool      writing;
928       bz_stream strm;
929       Int32     lastErr;
930       Bool      initialisedOk;
931    }
932    bzFile;
933
934
935 /*---------------------------------------------*/
936 static Bool myfeof ( FILE* f )
937 {
938    Int32 c = fgetc ( f );
939    if (c == EOF) return True;
940    ungetc ( c, f );
941    return False;
942 }
943
944
945 /*---------------------------------------------------*/
946 BZFILE* BZ_API(BZ2_bzWriteOpen)
947                     ( int*  bzerror,
948                       FILE* f,
949                       int   blockSize100k,
950                       int   verbosity,
951                       int   workFactor )
952 {
953    Int32   ret;
954    bzFile* bzf = NULL;
955
956    BZ_SETERR(BZ_OK);
957
958    if (f == NULL ||
959        (blockSize100k < 1 || blockSize100k > 9) ||
960        (workFactor < 0 || workFactor > 250) ||
961        (verbosity < 0 || verbosity > 4))
962       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
963
964    if (ferror(f))
965       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
966
967    bzf = malloc ( sizeof(bzFile) );
968    if (bzf == NULL)
969       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
970
971    BZ_SETERR(BZ_OK);
972    bzf->initialisedOk = False;
973    bzf->bufN          = 0;
974    bzf->handle        = f;
975    bzf->writing       = True;
976    bzf->strm.bzalloc  = NULL;
977    bzf->strm.bzfree   = NULL;
978    bzf->strm.opaque   = NULL;
979
980    if (workFactor == 0) workFactor = 30;
981    ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
982                               verbosity, workFactor );
983    if (ret != BZ_OK)
984       { BZ_SETERR(ret); free(bzf); return NULL; };
985
986    bzf->strm.avail_in = 0;
987    bzf->initialisedOk = True;
988    return bzf;
989 }
990
991
992 /*---------------------------------------------------*/
993 void BZ_API(BZ2_bzWrite)
994              ( int*    bzerror,
995                BZFILE* b,
996                void*   buf,
997                int     len )
998 {
999    Int32 n, n2, ret;
1000    bzFile* bzf = (bzFile*)b;
1001
1002    BZ_SETERR(BZ_OK);
1003    if (bzf == NULL || buf == NULL || len < 0)
1004       { BZ_SETERR(BZ_PARAM_ERROR); return; };
1005    if (!(bzf->writing))
1006       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1007    if (ferror(bzf->handle))
1008       { BZ_SETERR(BZ_IO_ERROR); return; };
1009
1010    if (len == 0)
1011       { BZ_SETERR(BZ_OK); return; };
1012
1013    bzf->strm.avail_in = len;
1014    bzf->strm.next_in  = buf;
1015
1016    while (True) {
1017       bzf->strm.avail_out = BZ_MAX_UNUSED;
1018       bzf->strm.next_out = bzf->buf;
1019       ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1020       if (ret != BZ_RUN_OK)
1021          { BZ_SETERR(ret); return; };
1022
1023       if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1024          n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1025          n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1026                        n, bzf->handle );
1027          if (n != n2 || ferror(bzf->handle))
1028             { BZ_SETERR(BZ_IO_ERROR); return; };
1029       }
1030
1031       if (bzf->strm.avail_in == 0)
1032          { BZ_SETERR(BZ_OK); return; };
1033    }
1034 }
1035
1036
1037 /*---------------------------------------------------*/
1038 void BZ_API(BZ2_bzWriteClose)
1039                   ( int*          bzerror,
1040                     BZFILE*       b,
1041                     int           abandon,
1042                     unsigned int* nbytes_in,
1043                     unsigned int* nbytes_out )
1044 {
1045    BZ2_bzWriteClose64 ( bzerror, b, abandon,
1046                         nbytes_in, NULL, nbytes_out, NULL );
1047 }
1048
1049
1050 void BZ_API(BZ2_bzWriteClose64)
1051                   ( int*          bzerror,
1052                     BZFILE*       b,
1053                     int           abandon,
1054                     unsigned int* nbytes_in_lo32,
1055                     unsigned int* nbytes_in_hi32,
1056                     unsigned int* nbytes_out_lo32,
1057                     unsigned int* nbytes_out_hi32 )
1058 {
1059    Int32   n, n2, ret;
1060    bzFile* bzf = (bzFile*)b;
1061
1062    if (bzf == NULL)
1063       { BZ_SETERR(BZ_OK); return; };
1064    if (!(bzf->writing))
1065       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1066    if (ferror(bzf->handle))
1067       { BZ_SETERR(BZ_IO_ERROR); return; };
1068
1069    if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1070    if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1071    if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1072    if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1073
1074    if ((!abandon) && bzf->lastErr == BZ_OK) {
1075       while (True) {
1076          bzf->strm.avail_out = BZ_MAX_UNUSED;
1077          bzf->strm.next_out = bzf->buf;
1078          ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1079          if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1080             { BZ_SETERR(ret); return; };
1081
1082          if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1083             n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1084             n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1085                           n, bzf->handle );
1086             if (n != n2 || ferror(bzf->handle))
1087                { BZ_SETERR(BZ_IO_ERROR); return; };
1088          }
1089
1090          if (ret == BZ_STREAM_END) break;
1091       }
1092    }
1093
1094    if ( !abandon && !ferror ( bzf->handle ) ) {
1095       fflush ( bzf->handle );
1096       if (ferror(bzf->handle))
1097          { BZ_SETERR(BZ_IO_ERROR); return; };
1098    }
1099
1100    if (nbytes_in_lo32 != NULL)
1101       *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1102    if (nbytes_in_hi32 != NULL)
1103       *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1104    if (nbytes_out_lo32 != NULL)
1105       *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1106    if (nbytes_out_hi32 != NULL)
1107       *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1108
1109    BZ_SETERR(BZ_OK);
1110    BZ2_bzCompressEnd ( &(bzf->strm) );
1111    free ( bzf );
1112 }
1113
1114
1115 /*---------------------------------------------------*/
1116 BZFILE* BZ_API(BZ2_bzReadOpen)
1117                    ( int*  bzerror,
1118                      FILE* f,
1119                      int   verbosity,
1120                      int   small,
1121                      void* unused,
1122                      int   nUnused )
1123 {
1124    bzFile* bzf = NULL;
1125    int     ret;
1126
1127    BZ_SETERR(BZ_OK);
1128
1129    if (f == NULL ||
1130        (small != 0 && small != 1) ||
1131        (verbosity < 0 || verbosity > 4) ||
1132        (unused == NULL && nUnused != 0) ||
1133        (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1134       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1135
1136    if (ferror(f))
1137       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1138
1139    bzf = malloc ( sizeof(bzFile) );
1140    if (bzf == NULL)
1141       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1142
1143    BZ_SETERR(BZ_OK);
1144
1145    bzf->initialisedOk = False;
1146    bzf->handle        = f;
1147    bzf->bufN          = 0;
1148    bzf->writing       = False;
1149    bzf->strm.bzalloc  = NULL;
1150    bzf->strm.bzfree   = NULL;
1151    bzf->strm.opaque   = NULL;
1152
1153    while (nUnused > 0) {
1154       bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1155       unused = ((void*)( 1 + ((UChar*)(unused))  ));
1156       nUnused--;
1157    }
1158
1159    ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1160    if (ret != BZ_OK)
1161       { BZ_SETERR(ret); free(bzf); return NULL; };
1162
1163    bzf->strm.avail_in = bzf->bufN;
1164    bzf->strm.next_in  = bzf->buf;
1165
1166    bzf->initialisedOk = True;
1167    return bzf;
1168 }
1169
1170
1171 /*---------------------------------------------------*/
1172 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1173 {
1174    bzFile* bzf = (bzFile*)b;
1175
1176    BZ_SETERR(BZ_OK);
1177    if (bzf == NULL)
1178       { BZ_SETERR(BZ_OK); return; };
1179
1180    if (bzf->writing)
1181       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1182
1183    if (bzf->initialisedOk)
1184       (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1185    free ( bzf );
1186 }
1187
1188
1189 /*---------------------------------------------------*/
1190 int BZ_API(BZ2_bzRead)
1191            ( int*    bzerror,
1192              BZFILE* b,
1193              void*   buf,
1194              int     len )
1195 {
1196    Int32   n, ret;
1197    bzFile* bzf = (bzFile*)b;
1198
1199    BZ_SETERR(BZ_OK);
1200
1201    if (bzf == NULL || buf == NULL || len < 0)
1202       { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1203
1204    if (bzf->writing)
1205       { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1206
1207    if (len == 0)
1208       { BZ_SETERR(BZ_OK); return 0; };
1209
1210    bzf->strm.avail_out = len;
1211    bzf->strm.next_out = buf;
1212
1213    while (True) {
1214
1215       if (ferror(bzf->handle))
1216          { BZ_SETERR(BZ_IO_ERROR); return 0; };
1217
1218       if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1219          n = fread ( bzf->buf, sizeof(UChar),
1220                      BZ_MAX_UNUSED, bzf->handle );
1221          if (ferror(bzf->handle))
1222             { BZ_SETERR(BZ_IO_ERROR); return 0; };
1223          bzf->bufN = n;
1224          bzf->strm.avail_in = bzf->bufN;
1225          bzf->strm.next_in = bzf->buf;
1226       }
1227
1228       ret = BZ2_bzDecompress ( &(bzf->strm) );
1229
1230       if (ret != BZ_OK && ret != BZ_STREAM_END)
1231          { BZ_SETERR(ret); return 0; };
1232
1233       if (ret == BZ_OK && myfeof(bzf->handle) &&
1234           bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1235          { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1236
1237       if (ret == BZ_STREAM_END)
1238          { BZ_SETERR(BZ_STREAM_END);
1239            return len - bzf->strm.avail_out; };
1240       if (bzf->strm.avail_out == 0)
1241          { BZ_SETERR(BZ_OK); return len; };
1242
1243    }
1244
1245    return 0; /*not reached*/
1246 }
1247
1248
1249 /*---------------------------------------------------*/
1250 void BZ_API(BZ2_bzReadGetUnused)
1251                      ( int*    bzerror,
1252                        BZFILE* b,
1253                        void**  unused,
1254                        int*    nUnused )
1255 {
1256    bzFile* bzf = (bzFile*)b;
1257    if (bzf == NULL)
1258       { BZ_SETERR(BZ_PARAM_ERROR); return; };
1259    if (bzf->lastErr != BZ_STREAM_END)
1260       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1261    if (unused == NULL || nUnused == NULL)
1262       { BZ_SETERR(BZ_PARAM_ERROR); return; };
1263
1264    BZ_SETERR(BZ_OK);
1265    *nUnused = bzf->strm.avail_in;
1266    *unused = bzf->strm.next_in;
1267 }
1268 #endif
1269
1270
1271 /*---------------------------------------------------*/
1272 /*--- Misc convenience stuff                      ---*/
1273 /*---------------------------------------------------*/
1274 #ifndef BZ_NO_COMPRESS
1275 /*---------------------------------------------------*/
1276 int BZ_API(BZ2_bzBuffToBuffCompress)
1277                          ( char*         dest,
1278                            unsigned int* destLen,
1279                            char*         source,
1280                            unsigned int  sourceLen,
1281                            int           blockSize100k,
1282                            int           verbosity,
1283                            int           workFactor )
1284 {
1285    bz_stream strm;
1286    int ret;
1287
1288    if (dest == NULL || destLen == NULL ||
1289        source == NULL ||
1290        blockSize100k < 1 || blockSize100k > 9 ||
1291        verbosity < 0 || verbosity > 4 ||
1292        workFactor < 0 || workFactor > 250)
1293       return BZ_PARAM_ERROR;
1294
1295    if (workFactor == 0) workFactor = 30;
1296    strm.bzalloc = NULL;
1297    strm.bzfree = NULL;
1298    strm.opaque = NULL;
1299    ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1300                               verbosity, workFactor );
1301    if (ret != BZ_OK) return ret;
1302
1303    strm.next_in = source;
1304    strm.next_out = dest;
1305    strm.avail_in = sourceLen;
1306    strm.avail_out = *destLen;
1307
1308    ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1309    if (ret == BZ_FINISH_OK) goto output_overflow;
1310    if (ret != BZ_STREAM_END) goto errhandler;
1311
1312    /* normal termination */
1313    *destLen -= strm.avail_out;
1314    BZ2_bzCompressEnd ( &strm );
1315    return BZ_OK;
1316
1317    output_overflow:
1318    BZ2_bzCompressEnd ( &strm );
1319    return BZ_OUTBUFF_FULL;
1320
1321    errhandler:
1322    BZ2_bzCompressEnd ( &strm );
1323    return ret;
1324 }
1325 #endif /* BZ_NO_COMPRESS */
1326
1327 /*---------------------------------------------------*/
1328 int BZ_API(BZ2_bzBuffToBuffDecompress)
1329                            ( char*         dest,
1330                              unsigned int* destLen,
1331                              char*         source,
1332                              unsigned int  sourceLen,
1333                              int           small,
1334                              int           verbosity )
1335 {
1336    bz_stream strm;
1337    int ret;
1338
1339    if (destLen == NULL || source == NULL)
1340           return BZ_PARAM_ERROR;
1341
1342    strm.bzalloc = NULL;
1343    strm.bzfree = NULL;
1344    strm.opaque = NULL;
1345    ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1346    if (ret != BZ_OK) return ret;
1347
1348    strm.next_in = source;
1349    strm.next_out = dest;
1350    strm.avail_in = sourceLen;
1351    strm.avail_out = *destLen;
1352
1353    ret = BZ2_bzDecompress ( &strm );
1354    if (ret == BZ_OK) goto output_overflow_or_eof;
1355    if (ret != BZ_STREAM_END) goto errhandler;
1356
1357    /* normal termination */
1358    *destLen -= strm.avail_out;
1359    BZ2_bzDecompressEnd ( &strm );
1360    return BZ_OK;
1361
1362    output_overflow_or_eof:
1363    if (strm.avail_out > 0) {
1364       BZ2_bzDecompressEnd ( &strm );
1365       return BZ_UNEXPECTED_EOF;
1366    } else {
1367       BZ2_bzDecompressEnd ( &strm );
1368       return BZ_OUTBUFF_FULL;
1369    };
1370
1371    errhandler:
1372    BZ2_bzDecompressEnd ( &strm );
1373    return ret;
1374 }
1375
1376
1377 /*---------------------------------------------------*/
1378 /*--
1379    Code contributed by Yoshioka Tsuneo
1380    (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
1381    to support better zlib compatibility.
1382    This code is not _officially_ part of libbzip2 (yet);
1383    I haven't tested it, documented it, or considered the
1384    threading-safeness of it.
1385    If this code breaks, please contact both Yoshioka and me.
1386 --*/
1387 /*---------------------------------------------------*/
1388
1389 /*---------------------------------------------------*/
1390 /*--
1391    return version like "0.9.0c".
1392 --*/
1393 const char * BZ_API(BZ2_bzlibVersion)(void)
1394 {
1395    return BZ_VERSION;
1396 }
1397
1398
1399 #ifndef BZ_NO_STDIO
1400 /*---------------------------------------------------*/
1401
1402 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1403 #   include <fcntl.h>
1404 #   include <io.h>
1405 #   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1406 #else
1407 #   define SET_BINARY_MODE(file)
1408 #endif
1409 static
1410 BZFILE * bzopen_or_bzdopen
1411                ( const char *path,   /* no use when bzdopen */
1412                  int fd,             /* no use when bzdopen */
1413                  const char *mode,
1414                  int open_mode)      /* bzopen: 0, bzdopen:1 */
1415 {
1416    int    bzerr;
1417    char   unused[BZ_MAX_UNUSED];
1418    int    blockSize100k = 9;
1419    int    writing       = 0;
1420    char   mode2[10]     = "";
1421    FILE   *fp           = NULL;
1422    BZFILE *bzfp         = NULL;
1423    int    verbosity     = 0;
1424    int    workFactor    = 30;
1425    int    smallMode     = 0;
1426    int    nUnused       = 0;
1427
1428    if (mode == NULL) return NULL;
1429    while (*mode) {
1430       switch (*mode) {
1431       case 'r':
1432          writing = 0; break;
1433       case 'w':
1434          writing = 1; break;
1435       case 's':
1436          smallMode = 1; break;
1437       default:
1438          if (isdigit((int)(*mode))) {
1439             blockSize100k = *mode-BZ_HDR_0;
1440          }
1441       }
1442       mode++;
1443    }
1444    strcat(mode2, writing ? "w" : "r" );
1445    strcat(mode2,"b");   /* binary mode */
1446
1447    if (open_mode==0) {
1448       if (path==NULL || strcmp(path,"")==0) {
1449         fp = (writing ? stdout : stdin);
1450         SET_BINARY_MODE(fp);
1451       } else {
1452         fp = fopen(path,mode2);
1453       }
1454    } else {
1455 #ifdef BZ_STRICT_ANSI
1456       fp = NULL;
1457 #else
1458       fp = fdopen(fd,mode2);
1459 #endif
1460    }
1461    if (fp == NULL) return NULL;
1462
1463    if (writing) {
1464       /* Guard against total chaos and anarchy -- JRS */
1465       if (blockSize100k < 1) blockSize100k = 1;
1466       if (blockSize100k > 9) blockSize100k = 9;
1467       bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1468                              verbosity,workFactor);
1469    } else {
1470       bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1471                             unused,nUnused);
1472    }
1473    if (bzfp == NULL) {
1474       if (fp != stdin && fp != stdout) fclose(fp);
1475       return NULL;
1476    }
1477    return bzfp;
1478 }
1479
1480
1481 /*---------------------------------------------------*/
1482 /*--
1483    open file for read or write.
1484       ex) bzopen("file","w9")
1485       case path="" or NULL => use stdin or stdout.
1486 --*/
1487 BZFILE * BZ_API(BZ2_bzopen)
1488                ( const char *path,
1489                  const char *mode )
1490 {
1491    return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1492 }
1493
1494
1495 /*---------------------------------------------------*/
1496 BZFILE * BZ_API(BZ2_bzdopen)
1497                ( int fd,
1498                  const char *mode )
1499 {
1500    return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1501 }
1502
1503
1504 /*---------------------------------------------------*/
1505 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1506 {
1507    int bzerr, nread;
1508    if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1509    nread = BZ2_bzRead(&bzerr,b,buf,len);
1510    if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1511       return nread;
1512    } else {
1513       return -1;
1514    }
1515 }
1516
1517
1518 /*---------------------------------------------------*/
1519 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1520 {
1521    int bzerr;
1522
1523    BZ2_bzWrite(&bzerr,b,buf,len);
1524    if(bzerr == BZ_OK){
1525       return len;
1526    }else{
1527       return -1;
1528    }
1529 }
1530
1531
1532 /*---------------------------------------------------*/
1533 int BZ_API(BZ2_bzflush) (BZFILE *b)
1534 {
1535    /* do nothing now... */
1536    return 0;
1537 }
1538
1539
1540 /*---------------------------------------------------*/
1541 void BZ_API(BZ2_bzclose) (BZFILE* b)
1542 {
1543    int bzerr;
1544    FILE *fp = ((bzFile *)b)->handle;
1545
1546    if (b==NULL) {return;}
1547    if(((bzFile*)b)->writing){
1548       BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1549       if(bzerr != BZ_OK){
1550          BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1551       }
1552    }else{
1553       BZ2_bzReadClose(&bzerr,b);
1554    }
1555    if(fp!=stdin && fp!=stdout){
1556       fclose(fp);
1557    }
1558 }
1559
1560
1561 /*---------------------------------------------------*/
1562 /*--
1563    return last error code
1564 --*/
1565 static char *bzerrorstrings[] = {
1566        "OK"
1567       ,"SEQUENCE_ERROR"
1568       ,"PARAM_ERROR"
1569       ,"MEM_ERROR"
1570       ,"DATA_ERROR"
1571       ,"DATA_ERROR_MAGIC"
1572       ,"IO_ERROR"
1573       ,"UNEXPECTED_EOF"
1574       ,"OUTBUFF_FULL"
1575       ,"CONFIG_ERROR"
1576       ,"???"   /* for future */
1577       ,"???"   /* for future */
1578       ,"???"   /* for future */
1579       ,"???"   /* for future */
1580       ,"???"   /* for future */
1581       ,"???"   /* for future */
1582 };
1583
1584
1585 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1586 {
1587    int err = ((bzFile *)b)->lastErr;
1588
1589    if(err>0) err = 0;
1590    *errnum = err;
1591    return bzerrorstrings[err*-1];
1592 }
1593 #endif
1594
1595
1596 /*-------------------------------------------------------------*/
1597 /*--- end                                           bzlib.c ---*/
1598 /*-------------------------------------------------------------*/
1599
1600 #endif /* CONFIG_BZIP2 */