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