Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

bzip2.c

Go to the documentation of this file.
00001 
00002 /*-----------------------------------------------------------*/
00003 /*--- A block-sorting, lossless compressor        bzip2.c ---*/
00004 /*-----------------------------------------------------------*/
00005 
00006 /*--
00007   This program is bzip2, a lossless, block-sorting data compressor,
00008   version 0.1pl2, dated 29-Aug-1997.
00009 
00010   Copyright (C) 1996, 1997 by Julian Seward.
00011      Guildford, Surrey, UK
00012      email: jseward@acm.org
00013 
00014   This program is free software; you can redistribute it and/or modify
00015   it under the terms of the GNU General Public License as published by
00016   the Free Software Foundation; either version 2 of the License, or
00017   (at your option) any later version.
00018 
00019   This program is distributed in the hope that it will be useful,
00020   but WITHOUT ANY WARRANTY; without even the implied warranty of
00021   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022   GNU General Public License for more details.
00023 
00024   You should have received a copy of the GNU General Public License
00025   along with this program; if not, write to the Free Software
00026   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00027 
00028   The GNU General Public License is contained in the file LICENSE.
00029 
00030   This program is based on (at least) the work of:
00031      Mike Burrows
00032      David Wheeler
00033      Peter Fenwick
00034      Alistair Moffat
00035      Radford Neal
00036      Ian H. Witten
00037      Robert Sedgewick
00038      Jon L. Bentley
00039 
00040   For more information on these sources, see the file ALGORITHMS.
00041 --*/
00042 
00043 /*----------------------------------------------------*/
00044 /*--- IMPORTANT                                    ---*/
00045 /*----------------------------------------------------*/
00046 
00047 /*--
00048    WARNING:
00049       This program (attempts to) compress data by performing several
00050       non-trivial transformations on it.  Unless you are 100% familiar
00051       with *all* the algorithms contained herein, and with the
00052       consequences of modifying them, you should NOT meddle with the
00053       compression or decompression machinery.  Incorrect changes can
00054       and very likely *will* lead to disasterous loss of data.
00055 
00056    DISCLAIMER:
00057       I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE
00058       USE OF THIS PROGRAM, HOWSOEVER CAUSED.
00059 
00060       Every compression of a file implies an assumption that the
00061       compressed file can be decompressed to reproduce the original.
00062       Great efforts in design, coding and testing have been made to
00063       ensure that this program works correctly.  However, the
00064       complexity of the algorithms, and, in particular, the presence
00065       of various special cases in the code which occur with very low
00066       but non-zero probability make it impossible to rule out the
00067       possibility of bugs remaining in the program.  DO NOT COMPRESS
00068       ANY DATA WITH THIS PROGRAM UNLESS YOU ARE PREPARED TO ACCEPT THE
00069       POSSIBILITY, HOWEVER SMALL, THAT THE DATA WILL NOT BE RECOVERABLE.
00070 
00071       That is not to say this program is inherently unreliable.
00072       Indeed, I very much hope the opposite is true.  bzip2 has been
00073       carefully constructed and extensively tested.
00074 
00075    PATENTS:
00076       To the best of my knowledge, bzip2 does not use any patented
00077       algorithms.  However, I do not have the resources available to
00078       carry out a full patent search.  Therefore I cannot give any
00079       guarantee of the above statement.
00080 --*/
00081 
00082 
00083 
00084 /*----------------------------------------------------*/
00085 /*--- and now for something much more pleasant :-) ---*/
00086 /*----------------------------------------------------*/
00087 
00088 /*---------------------------------------------*/
00089 /*--
00090   Place a 1 beside your platform, and 0 elsewhere.
00091 --*/
00092 
00093 /*--
00094   Generic 32-bit Unix.
00095   Also works on 64-bit Unix boxes.
00096 --*/
00097 #define BZ_UNIX      1
00098 
00099 /*--
00100   Win32, as seen by Jacob Navia's excellent
00101   port of (Chris Fraser & David Hanson)'s excellent
00102   lcc compiler.
00103 --*/
00104 #define BZ_LCCWIN32  0
00105 
00106 
00107 
00108 /*---------------------------------------------*/
00109 /*--
00110   Some stuff for all platforms.
00111 --*/
00112 
00113 #include <stdio.h>
00114 #include <stdlib.h>
00115 #if DEBUG
00116   #include <assert.h>
00117 #endif
00118 #include <string.h>
00119 #include <signal.h>
00120 #include <math.h>
00121 
00122 #define ERROR_IF_EOF(i)       { if ((i) == EOF)  ioError(); }
00123 #define ERROR_IF_NOT_ZERO(i)  { if ((i) != 0)    ioError(); }
00124 #define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); }
00125 
00126 
00127 /*---------------------------------------------*/
00128 /*--
00129    Platform-specific stuff.
00130 --*/
00131 
00132 #if BZ_UNIX
00133    #include <sys/types.h>
00134    #include <utime.h>
00135    #include <unistd.h>
00136 #ifndef DARWIN
00137    #include <malloc.h>
00138 #endif
00139    #include <sys/stat.h>
00140    #include <sys/times.h>
00141 
00142    #define Int32   int
00143    #define UInt32  unsigned int
00144    #define Char    char
00145    #define UChar   unsigned char
00146    #define Int16   short
00147    #define UInt16  unsigned short
00148 
00149    #define PATH_SEP    '/'
00150    #define MY_LSTAT    lstat
00151    #define MY_S_IFREG  S_ISREG
00152    #define MY_STAT     stat
00153 
00154    #define APPEND_FILESPEC(root, name) \
00155       root=snocString((root), (name))
00156 
00157    #define SET_BINARY_MODE(fd) /**/
00158 
00159    /*--
00160       You should try very hard to persuade your C compiler
00161       to inline the bits marked INLINE.  Otherwise bzip2 will
00162       run rather slowly.  gcc version 2.x is recommended.
00163    --*/
00164    #ifdef __GNUC__
00165       #define INLINE   inline
00166       #define NORETURN __attribute__ ((noreturn))
00167    #else
00168       #define INLINE   /**/
00169       #define NORETURN /**/
00170    #endif
00171 #endif
00172 
00173 
00174 
00175 #if BZ_LCCWIN32
00176    #include <io.h>
00177    #include <fcntl.h>
00178    #include <sys\stat.h>
00179 
00180    #define Int32   int
00181    #define UInt32  unsigned int
00182    #define Int16   short
00183    #define UInt16  unsigned short
00184    #define Char    char
00185    #define UChar   unsigned char
00186 
00187    #define INLINE         /**/
00188    #define NORETURN       /**/
00189    #define PATH_SEP       '\\'
00190    #define MY_LSTAT       _stat
00191    #define MY_STAT        _stat
00192    #define MY_S_IFREG(x)  ((x) & _S_IFREG)
00193 
00194    #if 0
00195    /*-- lcc-win32 seems to expand wildcards itself --*/
00196    #define APPEND_FILESPEC(root, spec)                \
00197       do {                                            \
00198          if ((spec)[0] == '-') {                      \
00199             root = snocString((root), (spec));        \
00200          } else {                                     \
00201             struct _finddata_t c_file;                \
00202             long hFile;                               \
00203             hFile = _findfirst((spec), &c_file);      \
00204             if ( hFile == -1L ) {                     \
00205                root = snocString ((root), (spec));    \
00206             } else {                                  \
00207                int anInt = 0;                         \
00208                while ( anInt == 0 ) {                 \
00209                   root = snocString((root),           \
00210                             &c_file.name[0]);         \
00211                   anInt = _findnext(hFile, &c_file);  \
00212                }                                      \
00213             }                                         \
00214          }                                            \
00215       } while ( 0 )
00216    #else
00217    #define APPEND_FILESPEC(root, name)                \
00218       root = snocString ((root), (name))
00219    #endif
00220 
00221    #define SET_BINARY_MODE(fd)                        \
00222       do {                                            \
00223          int retVal = setmode ( fileno ( fd ),        \
00224                                O_BINARY );            \
00225          ERROR_IF_MINUS_ONE ( retVal );               \
00226       } while ( 0 )
00227 
00228 #endif
00229 
00230 
00231 /*---------------------------------------------*/
00232 /*--
00233   Some more stuff for all platforms :-)
00234 --*/
00235 
00236 #define Bool   unsigned char
00237 #define True   1
00238 #define False  0
00239 
00240 /*--
00241   IntNative is your platform's `native' int size.
00242   Only here to avoid probs with 64-bit platforms.
00243 --*/
00244 #define IntNative int
00245 
00246 
00247 /*--
00248    change to 1, or compile with -DDEBUG=1 to debug
00249 --*/
00250 #ifndef DEBUG
00251 #define DEBUG 0
00252 #endif
00253 
00254 
00255 /*---------------------------------------------------*/
00256 /*---                                             ---*/
00257 /*---------------------------------------------------*/
00258 
00259 /*--
00260    Implementation notes, July 1997
00261    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00262 
00263    Memory allocation
00264    ~~~~~~~~~~~~~~~~~
00265    All large data structures are allocated on the C heap,
00266    for better or for worse.  That includes the various
00267    arrays of pointers, striped words, bytes, frequency
00268    tables and buffers for compression and decompression.
00269 
00270    bzip2 can operate at various block-sizes, ranging from
00271    100k to 900k in 100k steps, and it allocates only as
00272    much as it needs to.  When compressing, we know from the
00273    command-line options what the block-size is going to be,
00274    so all allocation can be done at start-up; if that
00275    succeeds, there can be no further allocation problems.
00276 
00277    Decompression is more complicated.  Each compressed file
00278    contains, in its header, a byte indicating the block
00279    size used for compression.  This means bzip2 potentially
00280    needs to reallocate memory for each file it deals with,
00281    which in turn opens the possibility for a memory allocation
00282    failure part way through a run of files, by encountering
00283    a file requiring a much larger block size than all the
00284    ones preceding it.
00285 
00286    The policy is to simply give up if a memory allocation
00287    failure occurs.  During decompression, it would be
00288    possible to move on to subsequent files in the hope that
00289    some might ask for a smaller block size, but the
00290    complications for doing this seem more trouble than they
00291    are worth.
00292 
00293 
00294    Compressed file formats
00295    ~~~~~~~~~~~~~~~~~~~~~~~
00296    [This is now entirely different from both 0.21, and from
00297     any previous Huffman-coded variant of bzip.
00298     See the associated file bzip2.txt for details.]
00299 
00300 
00301    Error conditions
00302    ~~~~~~~~~~~~~~~~
00303    Dealing with error conditions is the least satisfactory
00304    aspect of bzip2.  The policy is to try and leave the
00305    filesystem in a consistent state, then quit, even if it
00306    means not processing some of the files mentioned in the
00307    command line.  `A consistent state' means that a file
00308    exists either in its compressed or uncompressed form,
00309    but not both.  This boils down to the rule `delete the
00310    output file if an error condition occurs, leaving the
00311    input intact'.  Input files are only deleted when we can
00312    be pretty sure the output file has been written and
00313    closed successfully.
00314 
00315    Errors are a dog because there's so many things to
00316    deal with.  The following can happen mid-file, and
00317    require cleaning up.
00318 
00319      internal `panics' -- indicating a bug
00320      corrupted or inconsistent compressed file
00321      can't allocate enough memory to decompress this file
00322      I/O error reading/writing/opening/closing
00323      signal catches -- Control-C, SIGTERM, SIGHUP.
00324 
00325    Other conditions, primarily pertaining to file names,
00326    can be checked in-between files, which makes dealing
00327    with them easier.
00328 --*/
00329 
00330 
00331 
00332 /*---------------------------------------------------*/
00333 /*--- Misc (file handling) data decls             ---*/
00334 /*---------------------------------------------------*/
00335 
00336 UInt32  bytesIn, bytesOut;
00337 Int32   verbosity;
00338 Bool    keepInputFiles, smallMode, testFailsExist;
00339 UInt32  globalCrc;
00340 Int32   numFileNames, numFilesProcessed;
00341 
00342 
00343 /*-- source modes; F==file, I==stdin, O==stdout --*/
00344 #define SM_I2O           1
00345 #define SM_F2O           2
00346 #define SM_F2F           3
00347 
00348 /*-- operation modes --*/
00349 #define OM_Z             1
00350 #define OM_UNZ           2
00351 #define OM_TEST          3
00352 
00353 Int32   opMode;
00354 Int32   srcMode;
00355 
00356 
00357 Int32   longestFileName;
00358 Char    inName[1024];
00359 Char    outName[1024];
00360 Char    *progName;
00361 Char    progNameReally[1024];
00362 FILE    *outputHandleJustInCase;
00363 
00364 void    panic                 ( Char* )          NORETURN;
00365 void    ioError               ( void )           NORETURN;
00366 void    compressOutOfMemory   ( Int32, Int32 )   NORETURN;
00367 void    uncompressOutOfMemory ( Int32, Int32 )   NORETURN;
00368 void    blockOverrun          ( void )           NORETURN;
00369 void    badBlockHeader        ( void )           NORETURN;
00370 void    badBGLengths          ( void )           NORETURN;
00371 void    crcError              ( UInt32, UInt32 ) NORETURN;
00372 void    bitStreamEOF          ( void )           NORETURN;
00373 void    cleanUpAndFail        ( Int32 )          NORETURN;
00374 void    compressedStreamEOF   ( void )           NORETURN;
00375 
00376 void*   myMalloc ( Int32 );
00377 
00378 
00379 
00380 /*---------------------------------------------------*/
00381 /*--- Data decls for the front end                ---*/
00382 /*---------------------------------------------------*/
00383 
00384 /*--
00385    The overshoot bytes allow us to avoid most of
00386    the cost of pointer renormalisation during
00387    comparison of rotations in sorting.
00388    The figure of 20 is derived as follows:
00389       qSort3 allows an overshoot of up to 10.
00390       It then calls simpleSort, which calls
00391       fullGtU, also with max overshoot 10.
00392       fullGtU does up to 10 comparisons without
00393       renormalising, giving 10+10 == 20.
00394 --*/
00395 #define NUM_OVERSHOOT_BYTES 20
00396 
00397 /*--
00398   These are the main data structures for
00399   the Burrows-Wheeler transform.
00400 --*/
00401 
00402 /*--
00403   Pointers to compression and decompression
00404   structures.  Set by
00405      allocateCompressStructures   and
00406      setDecompressStructureSizes
00407 
00408   The structures are always set to be suitable
00409   for a block of size 100000 * blockSize100k.
00410 --*/
00411 UChar    *block;    /*-- compress   --*/
00412 UInt16   *quadrant; /*-- compress   --*/
00413 Int32    *zptr;     /*-- compress   --*/ 
00414 UInt16   *szptr;    /*-- overlays zptr ---*/
00415 Int32    *ftab;     /*-- compress   --*/
00416 
00417 UInt16   *ll16;     /*-- small decompress --*/
00418 UChar    *ll4;      /*-- small decompress --*/
00419 
00420 Int32    *tt;       /*-- fast decompress  --*/
00421 UChar    *ll8;      /*-- fast decompress  --*/
00422 
00423 
00424 /*--
00425   freq table collected to save a pass over the data
00426   during decompression.
00427 --*/
00428 Int32   unzftab[256];
00429 
00430 
00431 /*--
00432    index of the last char in the block, so
00433    the block size == last + 1.
00434 --*/
00435 Int32  last;
00436 
00437 
00438 /*--
00439   index in zptr[] of original string after sorting.
00440 --*/
00441 Int32  origPtr;
00442 
00443 
00444 /*--
00445   always: in the range 0 .. 9.
00446   The current block size is 100000 * this number.
00447 --*/
00448 Int32  blockSize100k;
00449 
00450 
00451 /*--
00452   Used when sorting.  If too many long comparisons
00453   happen, we stop sorting, randomise the block 
00454   slightly, and try again.
00455 --*/
00456 
00457 Int32  workFactor;
00458 Int32  workDone;
00459 Int32  workLimit;
00460 Bool   blockRandomised;
00461 Bool   firstAttempt;
00462 Int32  nBlocksRandomised;
00463 
00464 
00465 
00466 /*---------------------------------------------------*/
00467 /*--- Data decls for the back end                 ---*/
00468 /*---------------------------------------------------*/
00469 
00470 #define MAX_ALPHA_SIZE 258
00471 #define MAX_CODE_LEN    23
00472 
00473 #define RUNA 0
00474 #define RUNB 1
00475 
00476 #define N_GROUPS 6
00477 #define G_SIZE   50
00478 #define N_ITERS  4
00479 
00480 #define MAX_SELECTORS (2 + (900000 / G_SIZE))
00481 
00482 Bool  inUse[256];
00483 Int32 nInUse;
00484 
00485 UChar seqToUnseq[256];
00486 UChar unseqToSeq[256];
00487 
00488 UChar selector   [MAX_SELECTORS];
00489 UChar selectorMtf[MAX_SELECTORS];
00490 
00491 Int32 nMTF;
00492 
00493 Int32 mtfFreq[MAX_ALPHA_SIZE];
00494 
00495 UChar len  [N_GROUPS][MAX_ALPHA_SIZE];
00496 
00497 /*-- decompress only --*/
00498 Int32 limit  [N_GROUPS][MAX_ALPHA_SIZE];
00499 Int32 base   [N_GROUPS][MAX_ALPHA_SIZE];
00500 Int32 perm   [N_GROUPS][MAX_ALPHA_SIZE];
00501 Int32 minLens[N_GROUPS];
00502 
00503 /*-- compress only --*/
00504 Int32  code [N_GROUPS][MAX_ALPHA_SIZE];
00505 Int32  rfreq[N_GROUPS][MAX_ALPHA_SIZE];
00506 
00507 
00508 /*---------------------------------------------------*/
00509 /*--- 32-bit CRC grunge                           ---*/
00510 /*---------------------------------------------------*/
00511 
00512 /*--
00513   I think this is an implementation of the AUTODIN-II,
00514   Ethernet & FDDI 32-bit CRC standard.  Vaguely derived
00515   from code by Rob Warnock, in Section 51 of the
00516   comp.compression FAQ.
00517 --*/
00518 
00519 UInt32 crc32Table[256] = {
00520 
00521    /*-- Ugly, innit? --*/
00522 
00523    0x00000000UL, 0x04c11db7UL, 0x09823b6eUL, 0x0d4326d9UL,
00524    0x130476dcUL, 0x17c56b6bUL, 0x1a864db2UL, 0x1e475005UL,
00525    0x2608edb8UL, 0x22c9f00fUL, 0x2f8ad6d6UL, 0x2b4bcb61UL,
00526    0x350c9b64UL, 0x31cd86d3UL, 0x3c8ea00aUL, 0x384fbdbdUL,
00527    0x4c11db70UL, 0x48d0c6c7UL, 0x4593e01eUL, 0x4152fda9UL,
00528    0x5f15adacUL, 0x5bd4b01bUL, 0x569796c2UL, 0x52568b75UL,
00529    0x6a1936c8UL, 0x6ed82b7fUL, 0x639b0da6UL, 0x675a1011UL,
00530    0x791d4014UL, 0x7ddc5da3UL, 0x709f7b7aUL, 0x745e66cdUL,
00531    0x9823b6e0UL, 0x9ce2ab57UL, 0x91a18d8eUL, 0x95609039UL,
00532    0x8b27c03cUL, 0x8fe6dd8bUL, 0x82a5fb52UL, 0x8664e6e5UL,
00533    0xbe2b5b58UL, 0xbaea46efUL, 0xb7a96036UL, 0xb3687d81UL,
00534    0xad2f2d84UL, 0xa9ee3033UL, 0xa4ad16eaUL, 0xa06c0b5dUL,
00535    0xd4326d90UL, 0xd0f37027UL, 0xddb056feUL, 0xd9714b49UL,
00536    0xc7361b4cUL, 0xc3f706fbUL, 0xceb42022UL, 0xca753d95UL,
00537    0xf23a8028UL, 0xf6fb9d9fUL, 0xfbb8bb46UL, 0xff79a6f1UL,
00538    0xe13ef6f4UL, 0xe5ffeb43UL, 0xe8bccd9aUL, 0xec7dd02dUL,
00539    0x34867077UL, 0x30476dc0UL, 0x3d044b19UL, 0x39c556aeUL,
00540    0x278206abUL, 0x23431b1cUL, 0x2e003dc5UL, 0x2ac12072UL,
00541    0x128e9dcfUL, 0x164f8078UL, 0x1b0ca6a1UL, 0x1fcdbb16UL,
00542    0x018aeb13UL, 0x054bf6a4UL, 0x0808d07dUL, 0x0cc9cdcaUL,
00543    0x7897ab07UL, 0x7c56b6b0UL, 0x71159069UL, 0x75d48ddeUL,
00544    0x6b93dddbUL, 0x6f52c06cUL, 0x6211e6b5UL, 0x66d0fb02UL,
00545    0x5e9f46bfUL, 0x5a5e5b08UL, 0x571d7dd1UL, 0x53dc6066UL,
00546    0x4d9b3063UL, 0x495a2dd4UL, 0x44190b0dUL, 0x40d816baUL,
00547    0xaca5c697UL, 0xa864db20UL, 0xa527fdf9UL, 0xa1e6e04eUL,
00548    0xbfa1b04bUL, 0xbb60adfcUL, 0xb6238b25UL, 0xb2e29692UL,
00549    0x8aad2b2fUL, 0x8e6c3698UL, 0x832f1041UL, 0x87ee0df6UL,
00550    0x99a95df3UL, 0x9d684044UL, 0x902b669dUL, 0x94ea7b2aUL,
00551    0xe0b41de7UL, 0xe4750050UL, 0xe9362689UL, 0xedf73b3eUL,
00552    0xf3b06b3bUL, 0xf771768cUL, 0xfa325055UL, 0xfef34de2UL,
00553    0xc6bcf05fUL, 0xc27dede8UL, 0xcf3ecb31UL, 0xcbffd686UL,
00554    0xd5b88683UL, 0xd1799b34UL, 0xdc3abdedUL, 0xd8fba05aUL,
00555    0x690ce0eeUL, 0x6dcdfd59UL, 0x608edb80UL, 0x644fc637UL,
00556    0x7a089632UL, 0x7ec98b85UL, 0x738aad5cUL, 0x774bb0ebUL,
00557    0x4f040d56UL, 0x4bc510e1UL, 0x46863638UL, 0x42472b8fUL,
00558    0x5c007b8aUL, 0x58c1663dUL, 0x558240e4UL, 0x51435d53UL,
00559    0x251d3b9eUL, 0x21dc2629UL, 0x2c9f00f0UL, 0x285e1d47UL,
00560    0x36194d42UL, 0x32d850f5UL, 0x3f9b762cUL, 0x3b5a6b9bUL,
00561    0x0315d626UL, 0x07d4cb91UL, 0x0a97ed48UL, 0x0e56f0ffUL,
00562    0x1011a0faUL, 0x14d0bd4dUL, 0x19939b94UL, 0x1d528623UL,
00563    0xf12f560eUL, 0xf5ee4bb9UL, 0xf8ad6d60UL, 0xfc6c70d7UL,
00564    0xe22b20d2UL, 0xe6ea3d65UL, 0xeba91bbcUL, 0xef68060bUL,
00565    0xd727bbb6UL, 0xd3e6a601UL, 0xdea580d8UL, 0xda649d6fUL,
00566    0xc423cd6aUL, 0xc0e2d0ddUL, 0xcda1f604UL, 0xc960ebb3UL,
00567    0xbd3e8d7eUL, 0xb9ff90c9UL, 0xb4bcb610UL, 0xb07daba7UL,
00568    0xae3afba2UL, 0xaafbe615UL, 0xa7b8c0ccUL, 0xa379dd7bUL,
00569    0x9b3660c6UL, 0x9ff77d71UL, 0x92b45ba8UL, 0x9675461fUL,
00570    0x8832161aUL, 0x8cf30badUL, 0x81b02d74UL, 0x857130c3UL,
00571    0x5d8a9099UL, 0x594b8d2eUL, 0x5408abf7UL, 0x50c9b640UL,
00572    0x4e8ee645UL, 0x4a4ffbf2UL, 0x470cdd2bUL, 0x43cdc09cUL,
00573    0x7b827d21UL, 0x7f436096UL, 0x7200464fUL, 0x76c15bf8UL,
00574    0x68860bfdUL, 0x6c47164aUL, 0x61043093UL, 0x65c52d24UL,
00575    0x119b4be9UL, 0x155a565eUL, 0x18197087UL, 0x1cd86d30UL,
00576    0x029f3d35UL, 0x065e2082UL, 0x0b1d065bUL, 0x0fdc1becUL,
00577    0x3793a651UL, 0x3352bbe6UL, 0x3e119d3fUL, 0x3ad08088UL,
00578    0x2497d08dUL, 0x2056cd3aUL, 0x2d15ebe3UL, 0x29d4f654UL,
00579    0xc5a92679UL, 0xc1683bceUL, 0xcc2b1d17UL, 0xc8ea00a0UL,
00580    0xd6ad50a5UL, 0xd26c4d12UL, 0xdf2f6bcbUL, 0xdbee767cUL,
00581    0xe3a1cbc1UL, 0xe760d676UL, 0xea23f0afUL, 0xeee2ed18UL,
00582    0xf0a5bd1dUL, 0xf464a0aaUL, 0xf9278673UL, 0xfde69bc4UL,
00583    0x89b8fd09UL, 0x8d79e0beUL, 0x803ac667UL, 0x84fbdbd0UL,
00584    0x9abc8bd5UL, 0x9e7d9662UL, 0x933eb0bbUL, 0x97ffad0cUL,
00585    0xafb010b1UL, 0xab710d06UL, 0xa6322bdfUL, 0xa2f33668UL,
00586    0xbcb4666dUL, 0xb8757bdaUL, 0xb5365d03UL, 0xb1f740b4UL
00587 };
00588 
00589 
00590 /*---------------------------------------------*/
00591 void initialiseCRC ( void )
00592 {
00593    globalCrc = 0xffffffffUL;
00594 }
00595 
00596 
00597 /*---------------------------------------------*/
00598 UInt32 getFinalCRC ( void )
00599 {
00600    return ~globalCrc;
00601 }
00602 
00603 
00604 /*---------------------------------------------*/
00605 UInt32 getGlobalCRC ( void )
00606 {
00607    return globalCrc;
00608 }
00609 
00610 
00611 /*---------------------------------------------*/
00612 void setGlobalCRC ( UInt32 newCrc )
00613 {
00614    globalCrc = newCrc;
00615 }
00616 
00617 
00618 /*---------------------------------------------*/
00619 #define UPDATE_CRC(crcVar,cha)              \
00620 {                                           \
00621    crcVar = (crcVar << 8) ^                 \
00622             crc32Table[(crcVar >> 24) ^     \
00623                        ((UChar)cha)];       \
00624 }
00625 
00626 
00627 /*---------------------------------------------------*/
00628 /*--- Bit stream I/O                              ---*/
00629 /*---------------------------------------------------*/
00630 
00631 
00632 UInt32 bsBuff;
00633 Int32  bsLive;
00634 FILE*  bsStream;
00635 Bool   bsWriting;
00636 
00637 
00638 /*---------------------------------------------*/
00639 void bsSetStream ( FILE* f, Bool wr )
00640 {
00641    if (bsStream != NULL) panic ( "bsSetStream" );
00642    bsStream = f;
00643    bsLive = 0;
00644    bsBuff = 0;
00645    bytesOut = 0;
00646    bytesIn = 0;
00647    bsWriting = wr;
00648 }
00649 
00650 
00651 /*---------------------------------------------*/
00652 void bsFinishedWithStream ( void )
00653 {
00654    if (bsWriting)
00655       while (bsLive > 0) {
00656          fputc ( (UChar)(bsBuff >> 24), bsStream );
00657          bsBuff <<= 8;
00658          bsLive -= 8;
00659          bytesOut++;
00660       }
00661    bsStream = NULL;
00662 }
00663 
00664 
00665 /*---------------------------------------------*/
00666 #define bsNEEDR(nz)                           \
00667 {                                             \
00668    while (bsLive < nz) {                      \
00669       Int32 zzi = fgetc ( bsStream );         \
00670       if (zzi == EOF) compressedStreamEOF();  \
00671       bsBuff = (bsBuff << 8) | (zzi & 0xffL); \
00672       bsLive += 8;                            \
00673    }                                          \
00674 }
00675 
00676 
00677 /*---------------------------------------------*/
00678 #define bsNEEDW(nz)                           \
00679 {                                             \
00680    while (bsLive >= 8) {                      \
00681       fputc ( (UChar)(bsBuff >> 24),          \
00682                bsStream );                    \
00683       bsBuff <<= 8;                           \
00684       bsLive -= 8;                            \
00685       bytesOut++;                             \
00686    }                                          \
00687 }
00688 
00689 
00690 /*---------------------------------------------*/
00691 #define bsR1(vz)                              \
00692 {                                             \
00693    bsNEEDR(1);                                \
00694    vz = (bsBuff >> (bsLive-1)) & 1;           \
00695    bsLive--;                                  \
00696 }
00697 
00698 
00699 /*---------------------------------------------*/
00700 INLINE UInt32 bsR ( Int32 n )
00701 {
00702    UInt32 v;
00703    bsNEEDR ( n );
00704    v = (bsBuff >> (bsLive-n)) & ((1 << n)-1);
00705    bsLive -= n;
00706    return v;
00707 }
00708 
00709 
00710 /*---------------------------------------------*/
00711 INLINE void bsW ( Int32 n, UInt32 v )
00712 {
00713    bsNEEDW ( n );
00714    bsBuff |= (v << (32 - bsLive - n));
00715    bsLive += n;
00716 }
00717 
00718 
00719 /*---------------------------------------------*/
00720 UChar bsGetUChar ( void )
00721 {
00722    return (UChar)bsR(8);
00723 }
00724 
00725 
00726 /*---------------------------------------------*/
00727 void bsPutUChar ( UChar c )
00728 {
00729    bsW(8, (UInt32)c );
00730 }
00731 
00732 
00733 /*---------------------------------------------*/
00734 Int32 bsGetUInt32 ( void )
00735 {
00736    UInt32 u;
00737    u = 0;
00738    u = (u << 8) | bsR(8);
00739    u = (u << 8) | bsR(8);
00740    u = (u << 8) | bsR(8);
00741    u = (u << 8) | bsR(8);
00742    return u;
00743 }
00744 
00745 
00746 /*---------------------------------------------*/
00747 UInt32 bsGetIntVS ( UInt32 numBits )
00748 {
00749    return (UInt32)bsR(numBits);
00750 }
00751 
00752 
00753 /*---------------------------------------------*/
00754 UInt32 bsGetInt32 ( void )
00755 {
00756    return (Int32)bsGetUInt32();
00757 }
00758 
00759 
00760 /*---------------------------------------------*/
00761 void bsPutUInt32 ( UInt32 u )
00762 {
00763    bsW ( 8, (u >> 24) & 0xffL );
00764    bsW ( 8, (u >> 16) & 0xffL );
00765    bsW ( 8, (u >>  8) & 0xffL );
00766    bsW ( 8,  u        & 0xffL );
00767 }
00768 
00769 
00770 /*---------------------------------------------*/
00771 void bsPutInt32 ( Int32 c )
00772 {
00773    bsPutUInt32 ( (UInt32)c );
00774 }
00775 
00776 
00777 /*---------------------------------------------*/
00778 void bsPutIntVS ( Int32 numBits, UInt32 c )
00779 {
00780    bsW ( numBits, c );
00781 }
00782 
00783 
00784 /*---------------------------------------------------*/
00785 /*--- Huffman coding low-level stuff              ---*/
00786 /*---------------------------------------------------*/
00787 
00788 #define WEIGHTOF(zz0)  ((zz0) & 0xffffff00)
00789 #define DEPTHOF(zz1)   ((zz1) & 0x000000ff)
00790 #define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
00791 
00792 #define ADDWEIGHTS(zw1,zw2)                           \
00793    (WEIGHTOF(zw1)+WEIGHTOF(zw2)) |                    \
00794    (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
00795 
00796 #define UPHEAP(z)                                     \
00797 {                                                     \
00798    Int32 zz, tmp;                                     \
00799    zz = z; tmp = heap[zz];                            \
00800    while (weight[tmp] < weight[heap[zz >> 1]]) {      \
00801       heap[zz] = heap[zz >> 1];                       \
00802       zz >>= 1;                                       \
00803    }                                                  \
00804    heap[zz] = tmp;                                    \
00805 }
00806 
00807 #define DOWNHEAP(z)                                   \
00808 {                                                     \
00809    Int32 zz, yy, tmp;                                 \
00810    zz = z; tmp = heap[zz];                            \
00811    while (True) {                                     \
00812       yy = zz << 1;                                   \
00813       if (yy > nHeap) break;                          \
00814       if (yy < nHeap &&                               \
00815           weight[heap[yy+1]] < weight[heap[yy]])      \
00816          yy++;                                        \
00817       if (weight[tmp] < weight[heap[yy]]) break;      \
00818       heap[zz] = heap[yy];                            \
00819       zz = yy;                                        \
00820    }                                                  \
00821    heap[zz] = tmp;                                    \
00822 }
00823 
00824 
00825 /*---------------------------------------------*/
00826 void hbMakeCodeLengths ( UChar *len, 
00827                          Int32 *freq,
00828                          Int32 alphaSize,
00829                          Int32 maxLen )
00830 {
00831    /*--
00832       Nodes and heap entries run from 1.  Entry 0
00833       for both the heap and nodes is a sentinel.
00834    --*/
00835    Int32 nNodes, nHeap, n1, n2, i, j, k;
00836    Bool  tooLong;
00837 
00838    Int32 heap   [ MAX_ALPHA_SIZE + 2 ];
00839    Int32 weight [ MAX_ALPHA_SIZE * 2 ];
00840    Int32 parent [ MAX_ALPHA_SIZE * 2 ]; 
00841 
00842    for (i = 0; i < alphaSize; i++)
00843       weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
00844 
00845    while (True) {
00846 
00847       nNodes = alphaSize;
00848       nHeap = 0;
00849 
00850       heap[0] = 0;
00851       weight[0] = 0;
00852       parent[0] = -2;
00853 
00854       for (i = 1; i <= alphaSize; i++) {
00855          parent[i] = -1;
00856          nHeap++;
00857          heap[nHeap] = i;
00858          UPHEAP(nHeap);
00859       }
00860       if (!(nHeap < (MAX_ALPHA_SIZE+2))) 
00861          panic ( "hbMakeCodeLengths(1)" );
00862    
00863       while (nHeap > 1) {
00864          n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
00865          n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
00866          nNodes++;
00867          parent[n1] = parent[n2] = nNodes;
00868          weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
00869          parent[nNodes] = -1;
00870          nHeap++;
00871          heap[nHeap] = nNodes;
00872          UPHEAP(nHeap);
00873       }
00874       if (!(nNodes < (MAX_ALPHA_SIZE * 2)))
00875          panic ( "hbMakeCodeLengths(2)" );
00876 
00877       tooLong = False;
00878       for (i = 1; i <= alphaSize; i++) {
00879          j = 0;
00880          k = i;
00881          while (parent[k] >= 0) { k = parent[k]; j++; }
00882          len[i-1] = j;
00883          if (j > maxLen) tooLong = True;
00884       }
00885       
00886       if (! tooLong) break;
00887 
00888       for (i = 1; i < alphaSize; i++) {
00889          j = weight[i] >> 8;
00890          j = 1 + (j / 2);
00891          weight[i] = j << 8;
00892       }
00893    }
00894 }
00895 
00896 
00897 /*---------------------------------------------*/
00898 void hbAssignCodes ( Int32 *code,
00899                      UChar *length,
00900                      Int32 minLen,
00901                      Int32 maxLen,
00902                      Int32 alphaSize )
00903 {
00904    Int32 n, vec, i;
00905 
00906    vec = 0;
00907    for (n = minLen; n <= maxLen; n++) {
00908       for (i = 0; i < alphaSize; i++)
00909          if (length[i] == n) { code[i] = vec; vec++; };
00910       vec <<= 1;
00911    }
00912 }
00913 
00914 
00915 /*---------------------------------------------*/
00916 void hbCreateDecodeTables ( Int32 *limit,
00917                             Int32 *base,
00918                             Int32 *perm,
00919                             UChar *length,
00920                             Int32 minLen,
00921                             Int32 maxLen,
00922                             Int32 alphaSize )
00923 {
00924    Int32 pp, i, j, vec;
00925 
00926    pp = 0;
00927    for (i = minLen; i <= maxLen; i++)
00928       for (j = 0; j < alphaSize; j++)
00929          if (length[j] == i) { perm[pp] = j; pp++; };
00930 
00931    for (i = 0; i < MAX_CODE_LEN; i++) base[i] = 0;
00932    for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
00933 
00934    for (i = 1; i < MAX_CODE_LEN; i++) base[i] += base[i-1];
00935 
00936    for (i = 0; i < MAX_CODE_LEN; i++) limit[i] = 0;
00937    vec = 0;
00938 
00939    for (i = minLen; i <= maxLen; i++) {
00940       vec += (base[i+1] - base[i]);
00941       limit[i] = vec-1;
00942       vec <<= 1;
00943    }
00944    for (i = minLen + 1; i <= maxLen; i++)
00945       base[i] = ((limit[i-1] + 1) << 1) - base[i];
00946 }
00947 
00948 
00949 
00950 /*---------------------------------------------------*/
00951 /*--- Undoing the reversible transformation       ---*/
00952 /*---------------------------------------------------*/
00953 
00954 /*---------------------------------------------*/
00955 #define SET_LL4(i,n)                                          \
00956    { if (((i) & 0x1) == 0)                                    \
00957         ll4[(i) >> 1] = (ll4[(i) >> 1] & 0xf0) | (n); else    \
00958         ll4[(i) >> 1] = (ll4[(i) >> 1] & 0x0f) | ((n) << 4);  \
00959    }
00960 
00961 #define GET_LL4(i)                             \
00962     (((UInt32)(ll4[(i) >> 1])) >> (((i) << 2) & 0x4) & 0xF)
00963 
00964 #define SET_LL(i,n)                       \
00965    { ll16[i] = (UInt16)(n & 0x0000ffff);  \
00966      SET_LL4(i, n >> 16);                 \
00967    }
00968 
00969 #define GET_LL(i) \
00970    (((UInt32)ll16[i]) | (GET_LL4(i) << 16))
00971 
00972 
00973 /*---------------------------------------------*/
00974 /*--
00975   Manage memory for compression/decompression.
00976   When compressing, a single block size applies to
00977   all files processed, and that's set when the
00978   program starts.  But when decompressing, each file
00979   processed could have been compressed with a
00980   different block size, so we may have to free
00981   and reallocate on a per-file basis.
00982 
00983   A call with argument of zero means
00984   `free up everything.'  And a value of zero for
00985   blockSize100k means no memory is currently allocated.
00986 --*/
00987 
00988 
00989 /*---------------------------------------------*/
00990 void allocateCompressStructures ( void )
00991 {
00992    Int32 n  = 100000 * blockSize100k;
00993    block    = malloc ( (n + 1 + NUM_OVERSHOOT_BYTES) * sizeof(UChar) );
00994    quadrant = malloc ( (n     + NUM_OVERSHOOT_BYTES) * sizeof(Int16) );
00995    zptr     = malloc ( n                             * sizeof(Int32) );
00996    ftab     = malloc ( 65537                         * sizeof(Int32) );
00997 
00998    if (block == NULL || quadrant == NULL ||
00999        zptr == NULL  || ftab == NULL) {
01000       Int32 totalDraw
01001          = (n + 1 + NUM_OVERSHOOT_BYTES) * sizeof(UChar) +
01002            (n     + NUM_OVERSHOOT_BYTES) * sizeof(Int16) +
01003            n                             * sizeof(Int32) +
01004            65537                         * sizeof(Int32);
01005 
01006       compressOutOfMemory ( totalDraw, n );
01007    }
01008 
01009    /*--
01010       Since we want valid indexes for block of
01011       -1 to n + NUM_OVERSHOOT_BYTES - 1
01012       inclusive.
01013    --*/
01014    block++;
01015 
01016    /*--
01017       The back end needs a place to store the MTF values
01018       whilst it calculates the coding tables.  We could
01019       put them in the zptr array.  However, these values
01020       will fit in a short, so we overlay szptr at the 
01021       start of zptr, in the hope of reducing the number
01022       of cache misses induced by the multiple traversals
01023       of the MTF values when calculating coding tables.
01024       Seems to improve compression speed by about 1%.
01025    --*/
01026    szptr = (UInt16*)zptr;
01027 }
01028 
01029 
01030 /*---------------------------------------------*/
01031 void setDecompressStructureSizes ( Int32 newSize100k )
01032 {
01033    if (! (0 <= newSize100k   && newSize100k   <= 9 &&
01034           0 <= blockSize100k && blockSize100k <= 9))
01035       panic ( "setDecompressStructureSizes" );
01036 
01037    if (newSize100k == blockSize100k) return;
01038 
01039    blockSize100k = newSize100k;
01040 
01041    if (ll16  != NULL) free ( ll16  );
01042    if (ll4   != NULL) free ( ll4   );
01043    if (ll8   != NULL) free ( ll8   );
01044    if (tt    != NULL) free ( tt    );
01045 
01046    if (newSize100k == 0) return;
01047 
01048    if (smallMode) {
01049 
01050       Int32 n = 100000 * newSize100k;
01051       ll16    = malloc ( n * sizeof(UInt16) );
01052       ll4     = malloc ( ((n+1) >> 1) * sizeof(UChar) );
01053 
01054       if (ll4 == NULL || ll16 == NULL) {
01055          Int32 totalDraw
01056             = n * sizeof(Int16) + ((n+1) >> 1) * sizeof(UChar);
01057          uncompressOutOfMemory ( totalDraw, n );
01058       }
01059 
01060    } else {
01061 
01062       Int32 n = 100000 * newSize100k;
01063       ll8     = malloc ( n * sizeof(UChar) );
01064       tt      = malloc ( n * sizeof(Int32) );
01065 
01066       if (ll8 == NULL || tt == NULL) {
01067          Int32 totalDraw
01068             = n * sizeof(UChar) + n * sizeof(UInt32);
01069          uncompressOutOfMemory ( totalDraw, n );
01070       }
01071 
01072    }
01073 }
01074 
01075 
01076 
01077 /*---------------------------------------------------*/
01078 /*--- The new back end                            ---*/
01079 /*---------------------------------------------------*/
01080 
01081 /*---------------------------------------------*/
01082 void makeMaps ( void )
01083 {
01084    Int32 i;
01085    nInUse = 0;
01086    for (i = 0; i < 256; i++)
01087       if (inUse[i]) {
01088          seqToUnseq[nInUse] = i;
01089          unseqToSeq[i] = nInUse;
01090          nInUse++;
01091       }
01092 }
01093 
01094 
01095 /*---------------------------------------------*/
01096 void generateMTFValues ( void )
01097 {
01098    UChar  yy[256];
01099    Int32  i, j;
01100    UChar  tmp;
01101    UChar  tmp2;
01102    Int32  zPend;
01103    Int32  wr;
01104    Int32  EOB;
01105 
01106    makeMaps();
01107    EOB = nInUse+1;
01108 
01109    for (i = 0; i <= EOB; i++) mtfFreq[i] = 0;
01110 
01111    wr = 0;
01112    zPend = 0;
01113    for (i = 0; i < nInUse; i++) yy[i] = (UChar) i;
01114    
01115 
01116    for (i = 0; i <= last; i++) {
01117       UChar ll_i;
01118 
01119       #if DEBUG
01120          assert (wr <= i);
01121       #endif
01122 
01123       ll_i = unseqToSeq[block[zptr[i] - 1]];
01124       #if DEBUG
01125          assert (ll_i < nInUse);
01126       #endif
01127 
01128       j = 0;
01129       tmp = yy[j];
01130       while ( ll_i != tmp ) {
01131          j++;
01132          tmp2 = tmp;
01133          tmp = yy[j];
01134          yy[j] = tmp2;
01135       };
01136       yy[0] = tmp;
01137 
01138       if (j == 0) {
01139          zPend++;
01140       } else {
01141          if (zPend > 0) {
01142             zPend--;
01143             while (True) {
01144                switch (zPend % 2) {
01145                   case 0: szptr[wr] = RUNA; wr++; mtfFreq[RUNA]++; break;
01146                   case 1: szptr[wr] = RUNB; wr++; mtfFreq[RUNB]++; break;
01147                };
01148                if (zPend < 2) break;
01149                zPend = (zPend - 2) / 2;
01150             };
01151             zPend = 0;
01152          }
01153          szptr[wr] = j+1; wr++; mtfFreq[j+1]++;
01154       }
01155    }
01156 
01157    if (zPend > 0) {
01158       zPend--;
01159       while (True) {
01160          switch (zPend % 2) {
01161             case 0:  szptr[wr] = RUNA; wr++; mtfFreq[RUNA]++; break;
01162             case 1:  szptr[wr] = RUNB; wr++; mtfFreq[RUNB]++; break;
01163          };
01164          if (zPend < 2) break;
01165          zPend = (zPend - 2) / 2;
01166       };
01167    }
01168 
01169    szptr[wr] = EOB; wr++; mtfFreq[EOB]++;
01170 
01171    nMTF = wr;
01172 }
01173 
01174 
01175 /*---------------------------------------------*/
01176 #define LESSER_ICOST  0
01177 #define GREATER_ICOST 15
01178 
01179 void sendMTFValues ( void )
01180 {
01181    Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
01182    Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
01183    Int32 nGroups, nBytes;
01184 
01185    /*--
01186    UChar  len [N_GROUPS][MAX_ALPHA_SIZE];
01187    is a global since the decoder also needs it.
01188 
01189    Int32  code[N_GROUPS][MAX_ALPHA_SIZE];
01190    Int32  rfreq[N_GROUPS][MAX_ALPHA_SIZE];
01191    are also globals only used in this proc.
01192    Made global to keep stack frame size small.
01193    --*/
01194 
01195 
01196    UInt16 cost[N_GROUPS];
01197    Int32  fave[N_GROUPS];
01198 
01199    if (verbosity >= 3)
01200       fprintf ( stderr, 
01201                 "      %d in block, %d after MTF & 1-2 coding, %d+2 syms in use\n", 
01202                 last+1, nMTF, nInUse );
01203 
01204    alphaSize = nInUse+2;
01205    for (t = 0; t < N_GROUPS; t++)
01206       for (v = 0; v < alphaSize; v++)
01207          len[t][v] = GREATER_ICOST;
01208 
01209    /*--- Decide how many coding tables to use ---*/
01210    if (nMTF <= 0) panic ( "sendMTFValues(0)" );
01211    if (nMTF < 200) nGroups = 2; else
01212    if (nMTF < 800) nGroups = 4; else
01213                    nGroups = 6;
01214 
01215    /*--- Generate an initial set of coding tables ---*/
01216    { 
01217       Int32 nPart, remF, tFreq, aFreq;
01218 
01219       nPart = nGroups;
01220       remF  = nMTF;
01221       gs = 0;
01222       while (nPart > 0) {
01223          tFreq = remF / nPart;
01224          ge = gs-1;
01225          aFreq = 0;
01226          while (aFreq < tFreq && ge < alphaSize-1) {
01227             ge++;
01228             aFreq += mtfFreq[ge];
01229          }
01230 
01231          if (ge > gs 
01232              && nPart != nGroups && nPart != 1 
01233              && ((nGroups-nPart) % 2 == 1)) {
01234             aFreq -= mtfFreq[ge];
01235             ge--;
01236          }
01237 
01238          if (verbosity >= 3)
01239             fprintf ( stderr, 
01240                       "      initial group %d, [%d .. %d], has %d syms (%4.1f%%)\n",
01241                               nPart, gs, ge, aFreq, 
01242                               (100.0 * (float)aFreq) / (float)nMTF );
01243  
01244          for (v = 0; v < alphaSize; v++)
01245             if (v >= gs && v <= ge) 
01246                len[nPart-1][v] = LESSER_ICOST; else
01247                len[nPart-1][v] = GREATER_ICOST;
01248  
01249          nPart--;
01250          gs = ge+1;
01251          remF -= aFreq;
01252       }
01253    }
01254 
01255    /*--- 
01256       Iterate up to N_ITERS times to improve the tables.
01257    ---*/
01258    for (iter = 0; iter < N_ITERS; iter++) {
01259 
01260       for (t = 0; t < nGroups; t++) fave[t] = 0;
01261 
01262       for (t = 0; t < nGroups; t++)
01263          for (v = 0; v < alphaSize; v++)
01264             rfreq[t][v] = 0;
01265 
01266       nSelectors = 0;
01267       totc = 0;
01268       gs = 0;
01269       while (True) {
01270 
01271          /*--- Set group start & end marks. --*/
01272          if (gs >= nMTF) break;
01273          ge = gs + G_SIZE - 1; 
01274          if (ge >= nMTF) ge = nMTF-1;
01275 
01276          /*-- 
01277             Calculate the cost of this group as coded
01278             by each of the coding tables.
01279          --*/
01280          for (t = 0; t < nGroups; t++) cost[t] = 0;
01281 
01282          if (nGroups == 6) {
01283             register UInt16 cost0, cost1, cost2, cost3, cost4, cost5;
01284             cost0 = cost1 = cost2 = cost3 = cost4 = cost5 = 0;
01285             for (i = gs; i <= ge; i++) { 
01286                UInt16 icv = szptr[i];
01287                cost0 += len[0][icv];
01288                cost1 += len[1][icv];
01289                cost2 += len[2][icv];
01290                cost3 += len[3][icv];
01291                cost4 += len[4][icv];
01292                cost5 += len[5][icv];
01293             }
01294             cost[0] = cost0; cost[1] = cost1; cost[2] = cost2;
01295             cost[3] = cost3; cost[4] = cost4; cost[5] = cost5;
01296          } else {
01297             for (i = gs; i <= ge; i++) { 
01298                UInt16 icv = szptr[i];
01299                for (t = 0; t < nGroups; t++) cost[t] += len[t][icv];
01300             }
01301          }
01302  
01303          /*-- 
01304             Find the coding table which is best for this group,
01305             and record its identity in the selector table.
01306          --*/
01307          bc = 999999999; bt = -1;
01308          for (t = 0; t < nGroups; t++)
01309             if (cost[t] < bc) { bc = cost[t]; bt = t; };
01310          totc += bc;
01311          fave[bt]++;
01312          selector[nSelectors] = bt;
01313          nSelectors++;
01314 
01315          /*-- 
01316             Increment the symbol frequencies for the selected table.
01317           --*/
01318          for (i = gs; i <= ge; i++)
01319             rfreq[bt][ szptr[i] ]++;
01320 
01321          gs = ge+1;
01322       }
01323       if (verbosity >= 3) {
01324          fprintf ( stderr, 
01325                    "      pass %d: size is %d, grp uses are ", 
01326                    iter+1, totc/8 );
01327          for (t = 0; t < nGroups; t++)
01328             fprintf ( stderr, "%d ", fave[t] );
01329          fprintf ( stderr, "\n" );
01330       }
01331 
01332       /*--
01333         Recompute the tables based on the accumulated frequencies.
01334       --*/
01335       for (t = 0; t < nGroups; t++)
01336          hbMakeCodeLengths ( &len[t][0], &rfreq[t][0], alphaSize, 20 );
01337    }
01338 
01339 
01340    if (!(nGroups < 8)) panic ( "sendMTFValues(1)" );
01341    if (!(nSelectors < 32768 &&
01342          nSelectors <= (2 + (900000 / G_SIZE))))
01343                        panic ( "sendMTFValues(2)" );
01344 
01345 
01346    /*--- Compute MTF values for the selectors. ---*/
01347    {
01348       UChar pos[N_GROUPS], ll_i, tmp2, tmp;
01349       for (i = 0; i < nGroups; i++) pos[i] = i;
01350       for (i = 0; i < nSelectors; i++) {
01351          ll_i = selector[i];
01352          j = 0;
01353          tmp = pos[j];
01354          while ( ll_i != tmp ) {
01355             j++;
01356             tmp2 = tmp;
01357             tmp = pos[j];
01358             pos[j] = tmp2;
01359          };
01360          pos[0] = tmp;
01361          selectorMtf[i] = j;
01362       }
01363    };
01364 
01365    /*--- Assign actual codes for the tables. --*/
01366    for (t = 0; t < nGroups; t++) {
01367       minLen = 32;
01368       maxLen = 0;
01369       for (i = 0; i < alphaSize; i++) {
01370          if (len[t][i] > maxLen) maxLen = len[t][i];
01371          if (len[t][i] < minLen) minLen = len[t][i];
01372       }
01373       if (maxLen > 20) panic ( "sendMTFValues(3)" );
01374       if (minLen < 1)  panic ( "sendMTFValues(4)" );
01375       hbAssignCodes ( &code[t][0], &len[t][0], 
01376                       minLen, maxLen, alphaSize );
01377    }
01378 
01379    /*--- Transmit the mapping table. ---*/
01380    { 
01381       Bool inUse16[16];
01382       for (i = 0; i < 16; i++) {
01383           inUse16[i] = False;
01384           for (j = 0; j < 16; j++)
01385              if (inUse[i * 16 + j]) inUse16[i] = True;
01386       }
01387      
01388       nBytes = bytesOut;
01389       for (i = 0; i < 16; i++)
01390          if (inUse16[i]) bsW(1,1); else bsW(1,0);
01391 
01392       for (i = 0; i < 16; i++)
01393          if (inUse16[i])
01394             for (j = 0; j < 16; j++)
01395                if (inUse[i * 16 + j]) bsW(1,1); else bsW(1,0);
01396 
01397       if (verbosity >= 3) 
01398          fprintf ( stderr, "      bytes: mapping %d, ", bytesOut-nBytes );
01399    }
01400 
01401    /*--- Now the selectors. ---*/
01402    nBytes = bytesOut;
01403    bsW ( 3, nGroups );
01404    bsW ( 15, nSelectors );
01405    for (i = 0; i < nSelectors; i++) { 
01406       for (j = 0; j < selectorMtf[i]; j++) bsW(1,1);
01407       bsW(1,0);
01408    }
01409    if (verbosity >= 3)
01410       fprintf ( stderr, "selectors %d, ", bytesOut-nBytes );
01411 
01412    /*--- Now the coding tables. ---*/
01413    nBytes = bytesOut;
01414 
01415    for (t = 0; t < nGroups; t++) {
01416       Int32 curr = len[t][0];
01417       bsW ( 5, curr );
01418       for (i = 0; i < alphaSize; i++) {
01419          while (curr < len[t][i]) { bsW(2,2); curr++; /* 10 */ };
01420          while (curr > len[t][i]) { bsW(2,3); curr--; /* 11 */ };
01421          bsW ( 1, 0 );
01422       }
01423    }
01424 
01425    if (verbosity >= 3)
01426       fprintf ( stderr, "code lengths %d, ", bytesOut-nBytes );
01427 
01428    /*--- And finally, the block data proper ---*/
01429    nBytes = bytesOut;
01430    selCtr = 0;
01431    gs = 0;
01432    while (True) {
01433       if (gs >= nMTF) break;
01434       ge = gs + G_SIZE - 1; 
01435       if (ge >= nMTF) ge = nMTF-1;
01436       for (i = gs; i <= ge; i++) { 
01437          #if DEBUG
01438             assert (selector[selCtr] < nGroups);
01439          #endif
01440          bsW ( len  [selector[selCtr]] [szptr[i]],
01441                code [selector[selCtr]] [szptr[i]] );
01442       }
01443 
01444       gs = ge+1;
01445       selCtr++;
01446    }
01447    if (!(selCtr == nSelectors)) panic ( "sendMTFValues(5)" );
01448 
01449    if (verbosity >= 3)
01450       fprintf ( stderr, "codes %d\n", bytesOut-nBytes );
01451 }
01452 
01453 
01454 /*---------------------------------------------*/
01455 void moveToFrontCodeAndSend ( void )
01456 {
01457    bsPutIntVS ( 24, origPtr );
01458    generateMTFValues();
01459    sendMTFValues();
01460 }
01461 
01462 
01463 /*---------------------------------------------*/
01464 void recvDecodingTables ( void )
01465 {
01466    Int32 i, j, t, nGroups, nSelectors, alphaSize;
01467    Int32 minLen, maxLen;
01468    Bool inUse16[16];
01469 
01470    /*--- Receive the mapping table ---*/
01471    for (i = 0; i < 16; i++)
01472       if (bsR(1) == 1) 
01473          inUse16[i] = True; else 
01474          inUse16[i] = False;
01475 
01476    for (i = 0; i < 256; i++) inUse[i] = False;
01477 
01478    for (i = 0; i < 16; i++)
01479       if (inUse16[i])
01480          for (j = 0; j < 16; j++)
01481             if (bsR(1) == 1) inUse[i * 16 + j] = True;
01482 
01483    makeMaps();
01484    alphaSize = nInUse+2;
01485 
01486    /*--- Now the selectors ---*/
01487    nGroups = bsR ( 3 );
01488    nSelectors = bsR ( 15 );
01489    for (i = 0; i < nSelectors; i++) {
01490       j = 0;
01491       while (bsR(1) == 1) j++;
01492       selectorMtf[i] = j;
01493    }
01494 
01495    /*--- Undo the MTF values for the selectors. ---*/
01496    {
01497       UChar pos[N_GROUPS], tmp, v;
01498       for (v = 0; v < nGroups; v++) pos[v] = v;
01499    
01500       for (i = 0; i < nSelectors; i++) {
01501          v = selectorMtf[i];
01502          tmp = pos[v];
01503          while (v > 0) { pos[v] = pos[v-1]; v--; }
01504          pos[0] = tmp;
01505          selector[i] = tmp;
01506       }
01507    }
01508 
01509    /*--- Now the coding tables ---*/
01510    for (t = 0; t < nGroups; t++) {
01511       Int32 curr = bsR ( 5 );
01512       for (i = 0; i < alphaSize; i++) {
01513          while (bsR(1) == 1) {
01514             if (bsR(1) == 0) curr++; else curr--;
01515          }
01516          len[t][i] = curr;
01517       }
01518    }
01519 
01520    /*--- Create the Huffman decoding tables ---*/
01521    for (t = 0; t < nGroups; t++) {
01522       minLen = 32;
01523       maxLen = 0;
01524       for (i = 0; i < alphaSize; i++) {
01525          if (len[t][i] > maxLen) maxLen = len[t][i];
01526          if (len[t][i] < minLen) minLen = len[t][i];
01527       }
01528       hbCreateDecodeTables ( 
01529          &limit[t][0], &base[t][0], &perm[t][0], &len[t][0],
01530          minLen, maxLen, alphaSize
01531       );
01532       minLens[t] = minLen;
01533    }
01534 }
01535 
01536 
01537 /*---------------------------------------------*/
01538 #define GET_MTF_VAL(lval)                 \
01539 {                                         \
01540    Int32 zt, zn, zvec, zj;                \
01541    if (groupPos == 0) {                   \
01542       groupNo++;                          \
01543       groupPos = G_SIZE;                  \
01544    }                                      \
01545    groupPos--;                            \
01546    zt = selector[groupNo];                \
01547    zn = minLens[zt];                      \
01548    zvec = bsR ( zn );                     \
01549    while (zvec > limit[zt][zn]) {         \
01550       zn++; bsR1(zj);                     \
01551       zvec = (zvec << 1) | zj;            \
01552    };                                     \
01553    lval = perm[zt][zvec - base[zt][zn]];  \
01554 }
01555 
01556 
01557 /*---------------------------------------------*/
01558 void getAndMoveToFrontDecode ( void )
01559 {
01560    UChar  yy[256];
01561    Int32  i, j, nextSym, limitLast;
01562    Int32  EOB, groupNo, groupPos;
01563 
01564    limitLast = 100000 * blockSize100k;
01565    origPtr   = bsGetIntVS ( 24 );
01566 
01567    recvDecodingTables();
01568    EOB      = nInUse+1;
01569    groupNo  = -1;
01570    groupPos = 0;
01571 
01572    /*--
01573       Setting up the unzftab entries here is not strictly
01574       necessary, but it does save having to do it later
01575       in a separate pass, and so saves a block's worth of
01576       cache misses.
01577    --*/
01578    for (i = 0; i <= 255; i++) unzftab[i] = 0;
01579 
01580    for (i = 0; i <= 255; i++) yy[i] = (UChar) i;
01581 
01582    last = -1;
01583 
01584    GET_MTF_VAL(nextSym);
01585 
01586    while (True) {
01587 
01588       if (nextSym == EOB) break;
01589 
01590       if (nextSym == RUNA || nextSym == RUNB) {
01591          UChar ch;
01592          Int32 s = -1;
01593          Int32 N = 1;
01594          do {
01595             if (nextSym == RUNA) s = s + (0+1) * N; else
01596             if (nextSym == RUNB) s = s + (1+1) * N;
01597             N = N * 2;
01598             GET_MTF_VAL(nextSym);
01599          }
01600             while (nextSym == RUNA || nextSym == RUNB);
01601 
01602          s++;
01603          ch = seqToUnseq[yy[0]];
01604          unzftab[ch] += s;
01605 
01606          if (smallMode)
01607             while (s > 0) {
01608                last++; 
01609                ll16[last] = ch;
01610                s--;
01611             }
01612          else
01613             while (s > 0) {
01614                last++;
01615                ll8[last] = ch;
01616                s--;
01617             };
01618 
01619          if (last >= limitLast) blockOverrun();
01620          continue;
01621 
01622       } else {
01623 
01624          UChar tmp;
01625          last++; if (last >= limitLast) blockOverrun();
01626 
01627          tmp = yy[nextSym-1];
01628          unzftab[seqToUnseq[tmp]]++;
01629          if (smallMode)
01630             ll16[last] = seqToUnseq[tmp]; else
01631             ll8[last]  = seqToUnseq[tmp];
01632 
01633          /*--
01634             This loop is hammered during decompression,
01635             hence the unrolling.
01636 
01637             for (j = nextSym-1; j > 0; j--) yy[j] = yy[j-1];
01638          --*/
01639 
01640          j = nextSym-1;
01641          for (; j > 3; j -= 4) {
01642             yy[j]   = yy[j-1];
01643             yy[j-1] = yy[j-2];
01644             yy[j-2] = yy[j-3];
01645             yy[j-3] = yy[j-4];
01646          }
01647          for (; j > 0; j--) yy[j] = yy[j-1];
01648 
01649          yy[0] = tmp;
01650          GET_MTF_VAL(nextSym);
01651          continue;
01652       }
01653    }
01654 }
01655 
01656 
01657 /*---------------------------------------------------*/
01658 /*--- Block-sorting machinery                     ---*/
01659 /*---------------------------------------------------*/
01660 
01661 /*---------------------------------------------*/
01662 /*--
01663   Compare two strings in block.  We assume (see
01664   discussion above) that i1 and i2 have a max
01665   offset of 10 on entry, and that the first
01666   bytes of both block and quadrant have been
01667   copied into the "overshoot area", ie
01668   into the subscript range
01669   [last+1 .. last+NUM_OVERSHOOT_BYTES].
01670 --*/
01671 INLINE Bool fullGtU ( Int32 i1, Int32 i2 )
01672 {
01673    Int32 k;
01674    UChar c1, c2;
01675    UInt16 s1, s2;
01676 
01677    #if DEBUG
01678       /*--
01679         shellsort shouldn't ask to compare
01680         something with itself.
01681       --*/
01682       assert (i1 != i2);
01683    #endif
01684 
01685    c1 = block[i1];
01686    c2 = block[i2];
01687    if (c1 != c2) return (c1 > c2);
01688    i1++; i2++;
01689 
01690    c1 = block[i1];
01691    c2 = block[i2];
01692    if (c1 != c2) return (c1 > c2);
01693    i1++; i2++;
01694 
01695    c1 = block[i1];
01696    c2 = block[i2];
01697    if (c1 != c2) return (c1 > c2);
01698    i1++; i2++;
01699 
01700    c1 = block[i1];
01701    c2 = block[i2];
01702    if (c1 != c2) return (c1 > c2);
01703    i1++; i2++;
01704 
01705    c1 = block[i1];
01706    c2 = block[i2];
01707    if (c1 != c2) return (c1 > c2);
01708    i1++; i2++;
01709 
01710    c1 = block[i1];
01711    c2 = block[i2];
01712    if (c1 != c2) return (c1 > c2);
01713    i1++; i2++;
01714 
01715    k = last + 1;
01716 
01717    do {
01718 
01719       c1 = block[i1];
01720       c2 = block[i2];
01721       if (c1 != c2) return (c1 > c2);
01722       s1 = quadrant[i1];
01723       s2 = quadrant[i2];
01724       if (s1 != s2) return (s1 > s2);
01725       i1++; i2++;
01726 
01727       c1 = block[i1];
01728       c2 = block[i2];
01729       if (c1 != c2) return (c1 > c2);
01730       s1 = quadrant[i1];
01731       s2 = quadrant[i2];
01732       if (s1 != s2) return (s1 > s2);
01733       i1++; i2++;
01734 
01735       c1 = block[i1];
01736       c2 = block[i2];
01737       if (c1 != c2) return (c1 > c2);
01738       s1 = quadrant[i1];
01739       s2 = quadrant[i2];
01740       if (s1 != s2) return (s1 > s2);
01741       i1++; i2++;
01742 
01743       c1 = block[i1];
01744       c2 = block[i2];
01745       if (c1 != c2) return (c1 > c2);
01746       s1 = quadrant[i1];
01747       s2 = quadrant[i2];
01748       if (s1 != s2) return (s1 > s2);
01749       i1++; i2++;
01750 
01751       if (i1 > last) { i1 -= last; i1--; };
01752       if (i2 > last) { i2 -= last; i2--; };
01753 
01754       k -= 4;
01755       workDone++;
01756    }
01757       while (k >= 0);
01758 
01759    return False;
01760 }
01761 
01762 /*---------------------------------------------*/
01763 /*--
01764    Knuth's increments seem to work better
01765    than Incerpi-Sedgewick here.  Possibly
01766    because the number of elems to sort is
01767    usually small, typically <= 20.
01768 --*/
01769 Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
01770                    9841, 29524, 88573, 265720,
01771                    797161, 2391484 };
01772 
01773 void simpleSort ( Int32 lo, Int32 hi, Int32 d )
01774 {
01775    Int32 i, j, h, bigN, hp;
01776    Int32 v;
01777 
01778    bigN = hi - lo + 1;
01779    if (bigN < 2) return;
01780 
01781    hp = 0;
01782    while (incs[hp] < bigN) hp++;
01783    hp--;
01784 
01785    for (; hp >= 0; hp--) {
01786       h = incs[hp];
01787       if (verbosity >= 5) 
01788          fprintf ( stderr, "          shell increment %d\n", h );
01789 
01790       i = lo + h;
01791       while (True) {
01792 
01793          /*-- copy 1 --*/
01794          if (i > hi) break;
01795          v = zptr[i];
01796          j = i;
01797          while ( fullGtU ( zptr[j-h]+d, v+d ) ) {
01798             zptr[j] = zptr[j-h];
01799             j = j - h;
01800             if (j <= (lo + h - 1)) break;
01801          }
01802          zptr[j] = v;
01803          i++;
01804 
01805          /*-- copy 2 --*/
01806          if (i > hi) break;
01807          v = zptr[i];
01808          j = i;
01809          while ( fullGtU ( zptr[j-h]+d, v+d ) ) {
01810             zptr[j] = zptr[j-h];
01811             j = j - h;
01812             if (j <= (lo + h - 1)) break;
01813          }
01814          zptr[j] = v;
01815          i++;
01816 
01817          /*-- copy 3 --*/
01818          if (i > hi) break;
01819          v = zptr[i];
01820          j = i;
01821          while ( fullGtU ( zptr[j-h]+d, v+d ) ) {
01822             zptr[j] = zptr[j-h];
01823             j = j - h;
01824             if (j <= (lo + h - 1)) break;
01825          }
01826          zptr[j] = v;
01827          i++;
01828 
01829          if (workDone > workLimit && firstAttempt) return;
01830       }
01831    }
01832 }
01833 
01834 
01835 /*---------------------------------------------*/
01836 /*--
01837    The following is an implementation of
01838    an elegant 3-way quicksort for strings,
01839    described in a paper "Fast Algorithms for
01840    Sorting and Searching Strings", by Robert
01841    Sedgewick and Jon L. Bentley.
01842 --*/
01843 
01844 #define swap(lv1, lv2) \
01845    { Int32 tmp = lv1; lv1 = lv2; lv2 = tmp; }
01846 
01847 INLINE void vswap ( Int32 p1, Int32 p2, Int32 n )
01848 {
01849    while (n > 0) {
01850       swap(zptr[p1], zptr[p2]);
01851       p1++; p2++; n--;
01852    }
01853 }
01854 
01855 INLINE UChar med3 ( UChar a, UChar b, UChar c )
01856 {
01857    UChar t;
01858    if (a > b) { t = a; a = b; b = t; };
01859    if (b > c) { t = b; b = c; c = t; };
01860    if (a > b)          b = a;
01861    return b;
01862 }
01863 
01864 
01865 #define min(a,b) ((a) < (b)) ? (a) : (b)
01866 
01867 typedef
01868    struct { Int32 ll; Int32 hh; Int32 dd; }
01869    StackElem;
01870 
01871 #define push(lz,hz,dz) { stack[sp].ll = lz; \
01872                          stack[sp].hh = hz; \
01873                          stack[sp].dd = dz; \
01874                          sp++; }
01875 
01876 #define pop(lz,hz,dz) { sp--;               \
01877                         lz = stack[sp].ll;  \
01878                         hz = stack[sp].hh;  \
01879                         dz = stack[sp].dd; }
01880 
01881 #define SMALL_THRESH 20
01882 #define DEPTH_THRESH 10
01883 
01884 /*--
01885    If you are ever unlucky/improbable enough
01886    to get a stack overflow whilst sorting,
01887    increase the following constant and try
01888    again.  In practice I have never seen the
01889    stack go above 27 elems, so the following
01890    limit seems very generous.
01891 --*/
01892 #define QSORT_STACK_SIZE 1000
01893 
01894 
01895 void qSort3 ( Int32 loSt, Int32 hiSt, Int32 dSt )
01896 {
01897    Int32 unLo, unHi, ltLo, gtHi, med, n, m;
01898    Int32 sp, lo, hi, d;
01899    StackElem stack[QSORT_STACK_SIZE];
01900 
01901    sp = 0;
01902    push ( loSt, hiSt, dSt );
01903 
01904    while (sp > 0) {
01905 
01906       if (sp >= QSORT_STACK_SIZE) panic ( "stack overflow in qSort3" );
01907 
01908       pop ( lo, hi, d );
01909 
01910       if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) {
01911          simpleSort ( lo, hi, d );
01912          if (workDone > workLimit && firstAttempt) return;
01913          continue;
01914       }
01915 
01916       med = med3 ( block[zptr[ lo         ]+d],
01917                    block[zptr[ hi         ]+d],
01918                    block[zptr[ (lo+hi)>>1 ]+d] );
01919 
01920       unLo = ltLo = lo;
01921       unHi = gtHi = hi;
01922 
01923       while (True) {
01924          while (True) {
01925             if (unLo > unHi) break;
01926             n = ((Int32)block[zptr[unLo]+d]) - med;
01927             if (n == 0) { swap(zptr[unLo], zptr[ltLo]); ltLo++; unLo++; continue; };
01928             if (n >  0) break;
01929             unLo++;
01930          }
01931          while (True) {
01932             if (unLo > unHi) break;
01933             n = ((Int32)block[zptr[unHi]+d]) - med;
01934             if (n == 0) { swap(zptr[unHi], zptr[gtHi]); gtHi--; unHi--; continue; };
01935             if (n <  0) break;
01936             unHi--;
01937          }
01938          if (unLo > unHi) break;
01939          swap(zptr[unLo], zptr[unHi]); unLo++; unHi--;
01940       }
01941       #if DEBUG
01942          assert (unHi == unLo-1);
01943       #endif
01944 
01945       if (gtHi < ltLo) {
01946          push(lo, hi, d+1 );
01947          continue;
01948       }
01949 
01950       n = min(ltLo-lo, unLo-ltLo); vswap(lo, unLo-n, n);
01951       m = min(hi-gtHi, gtHi-unHi); vswap(unLo, hi-m+1, m);
01952 
01953       n = lo + unLo - ltLo - 1;
01954       m = hi - (gtHi - unHi) + 1;
01955 
01956       push ( lo, n, d );
01957       push ( n+1, m-1, d+1 );
01958       push ( m, hi, d );
01959    }
01960 }
01961 
01962 
01963 /*---------------------------------------------*/
01964 
01965 #define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
01966 
01967 #define SETMASK (1 << 21)
01968 #define CLEARMASK (~(SETMASK))
01969 
01970 void sortIt ( void )
01971 {
01972    Int32 i, j, ss, sb;
01973    Int32 runningOrder[256];
01974    Int32 copy[256];
01975    Bool bigDone[256];
01976    UChar c1, c2;
01977    Int32 numQSorted;
01978 
01979    /*--
01980       In the various block-sized structures, live data runs
01981       from 0 to last+NUM_OVERSHOOT_BYTES inclusive.  First,
01982       set up the overshoot area for block.
01983    --*/
01984 
01985    if (verbosity >= 4) fprintf ( stderr, "        sort initialise ...\n" );
01986    for (i = 0; i < NUM_OVERSHOOT_BYTES; i++)
01987        block[last+i+1] = block[i % (last+1)];
01988    for (i = 0; i <= last+NUM_OVERSHOOT_BYTES; i++)
01989        quadrant[i] = 0;
01990 
01991    block[-1] = block[last];
01992 
01993    if (last < 4000) {
01994 
01995       /*--
01996          Use simpleSort(), since the full sorting mechanism
01997          has quite a large constant overhead.
01998       --*/
01999       if (verbosity >= 4) fprintf ( stderr, "        simpleSort ...\n" );
02000       for (i = 0; i <= last; i++) zptr[i] = i;
02001       firstAttempt = False;
02002       workDone = workLimit = 0;
02003       simpleSort ( 0, last, 0 );
02004       if (verbosity >= 4) fprintf ( stderr, "        simpleSort done.\n" );
02005 
02006    } else {
02007 
02008       numQSorted = 0;
02009       for (i = 0; i <= 255; i++) bigDone[i] = False;
02010 
02011       if (verbosity >= 4) fprintf ( stderr, "        bucket sorting ...\n" );
02012 
02013       for (i = 0; i <= 65536; i++) ftab[i] = 0;
02014 
02015       c1 = block[-1];
02016       for (i = 0; i <= last; i++) {
02017          c2 = block[i];
02018          ftab[(c1 << 8) + c2]++;
02019          c1 = c2;
02020       }
02021 
02022       for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
02023 
02024       c1 = block[0];
02025       for (i = 0; i < last; i++) {
02026          c2 = block[i+1];
02027          j = (c1 << 8) + c2;
02028          c1 = c2;
02029          ftab[j]--;
02030          zptr[ftab[j]] = i;
02031       }
02032       j = (block[last] << 8) + block[0];
02033       ftab[j]--;
02034       zptr[ftab[j]] = last;
02035 
02036       /*--
02037          Now ftab contains the first loc of every small bucket.
02038          Calculate the running order, from smallest to largest
02039          big bucket.
02040       --*/
02041 
02042       for (i = 0; i <= 255; i++) runningOrder[i] = i;
02043 
02044       {
02045          Int32 vv;
02046          Int32 h = 1;
02047          do h = 3 * h + 1; while (h <= 256);
02048          do {
02049             h = h / 3;
02050             for (i = h; i <= 255; i++) {
02051                vv = runningOrder[i];
02052                j = i;
02053                while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
02054                   runningOrder[j] = runningOrder[j-h];
02055                   j = j - h;
02056                   if (j <= (h - 1)) goto zero;
02057                }
02058                zero:
02059                runningOrder[j] = vv;
02060             }
02061          } while (h != 1);
02062       }
02063 
02064       /*--
02065          The main sorting loop.
02066       --*/
02067 
02068       for (i = 0; i <= 255; i++) {
02069 
02070          /*--
02071             Process big buckets, starting with the least full.
02072          --*/
02073          ss = runningOrder[i];
02074 
02075          /*--
02076             Complete the big bucket [ss] by quicksorting
02077             any unsorted small buckets [ss, j].  Hopefully
02078             previous pointer-scanning phases have already
02079             completed many of the small buckets [ss, j], so
02080             we don't have to sort them at all.
02081          --*/
02082          for (j = 0; j <= 255; j++) {
02083             sb = (ss << 8) + j;
02084             if ( ! (ftab[sb] & SETMASK) ) {
02085                Int32 lo = ftab[sb]   & CLEARMASK;
02086                Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
02087                if (hi > lo) {
02088                   if (verbosity >= 4)
02089                      fprintf ( stderr,
02090                                "        qsort [0x%x, 0x%x]   done %d   this %d\n",
02091                                ss, j, numQSorted, hi - lo + 1 );
02092                   qSort3 ( lo, hi, 2 );
02093                   numQSorted += ( hi - lo + 1 );
02094                   if (workDone > workLimit && firstAttempt) return;
02095                }
02096                ftab[sb] |= SETMASK;
02097             }
02098          }
02099 
02100          /*--
02101             The ss big bucket is now done.  Record this fact,
02102             and update the quadrant descriptors.  Remember to
02103             update quadrants in the overshoot area too, if
02104             necessary.  The "if (i < 255)" test merely skips
02105             this updating for the last bucket processed, since
02106             updating for the last bucket is pointless.
02107          --*/
02108          bigDone[ss] = True;
02109 
02110          if (i < 255) {
02111             Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
02112             Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
02113             Int32 shifts   = 0;
02114 
02115             while ((bbSize >> shifts) > 65534) shifts++;
02116 
02117             for (j = 0; j < bbSize; j++) {
02118                Int32 a2update     = zptr[bbStart + j];
02119                UInt16 qVal        = (UInt16)(j >> shifts);
02120                quadrant[a2update] = qVal;
02121                if (a2update < NUM_OVERSHOOT_BYTES)
02122                   quadrant[a2update + last + 1] = qVal;
02123             }
02124 
02125             if (! ( ((bbSize-1) >> shifts) <= 65535 )) panic ( "sortIt" );
02126          }
02127 
02128          /*--
02129             Now scan this big bucket so as to synthesise the
02130             sorted order for small buckets [t, ss] for all t != ss.
02131          --*/
02132          for (j = 0; j <= 255; j++)
02133             copy[j] = ftab[(j << 8) + ss] & CLEARMASK;
02134 
02135          for (j = ftab[ss << 8] & CLEARMASK;
02136               j < (ftab[(ss+1) << 8] & CLEARMASK);
02137               j++) {
02138             c1 = block[zptr[j]-1];
02139             if ( ! bigDone[c1] ) {
02140                zptr[copy[c1]] = zptr[j] == 0 ? last : zptr[j] - 1;
02141                copy[c1] ++;
02142             }
02143          }
02144 
02145          for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
02146       }
02147       if (verbosity >= 4)
02148          fprintf ( stderr, "        %d pointers, %d sorted, %d scanned\n",
02149                            last+1, numQSorted, (last+1) - numQSorted );
02150    }
02151 }
02152 
02153 
02154 /*---------------------------------------------------*/
02155 /*--- Stuff for randomising repetitive blocks     ---*/
02156 /*---------------------------------------------------*/
02157 
02158 /*---------------------------------------------*/
02159 Int32 rNums[512] = { 
02160    619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 
02161    985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 
02162    733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 
02163    419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 
02164    878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 
02165    862, 687, 507, 283, 482, 129, 807, 591, 733, 623, 
02166    150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 
02167    170, 607, 520, 932, 727, 476, 693, 425, 174, 647, 
02168    73, 122, 335, 530, 442, 853, 695, 249, 445, 515, 
02169    909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 
02170    641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 
02171    161, 604, 958, 533, 221, 400, 386, 867, 600, 782, 
02172    382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 
02173    98, 553, 163, 354, 666, 933, 424, 341, 533, 870, 
02174    227, 730, 475, 186, 263, 647, 537, 686, 600, 224, 
02175    469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 
02176    184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 
02177    715, 67, 618, 276, 204, 918, 873, 777, 604, 560, 
02178    951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 
02179    652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 
02180    645, 863, 803, 350, 139, 93, 354, 99, 820, 908, 
02181    609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 
02182    653, 282, 762, 623, 680, 81, 927, 626, 789, 125, 
02183    411, 521, 938, 300, 821, 78, 343, 175, 128, 250, 
02184    170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 
02185    857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 
02186    669, 112, 134, 694, 363, 992, 809, 743, 168, 974, 
02187    944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 
02188    344, 805, 988, 739, 511, 655, 814, 334, 249, 515, 
02189    897, 955, 664, 981, 649, 113, 974, 459, 893, 228, 
02190    433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 
02191    686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 
02192    946, 670, 656, 610, 738, 392, 760, 799, 887, 653, 
02193    978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 
02194    680, 879, 194, 572, 640, 724, 926, 56, 204, 700, 
02195    707, 151, 457, 449, 797, 195, 791, 558, 945, 679, 
02196    297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 
02197    134, 108, 571, 364, 631, 212, 174, 643, 304, 329, 
02198    343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 
02199    140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 
02200    170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 
02201    369, 970, 294, 750, 807, 827, 150, 790, 288, 923, 
02202    804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 
02203    896, 831, 547, 261, 524, 462, 293, 465, 502, 56, 
02204    661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 
02205    768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 
02206    61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 
02207    372, 567, 466, 434, 645, 210, 389, 550, 919, 135, 
02208    780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 
02209    920, 176, 193, 713, 857, 265, 203, 50, 668, 108, 
02210    645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 
02211    936, 638
02212 };
02213 
02214 
02215 #define RAND_DECLS                                \
02216    Int32 rNToGo = 0;                              \
02217    Int32 rTPos  = 0;                              \
02218 
02219 #define RAND_MASK ((rNToGo == 1) ? 1 : 0)
02220 
02221 #define RAND_UPD_MASK                             \
02222    if (rNToGo == 0) {                             \
02223       rNToGo = rNums[rTPos];                      \
02224       rTPos++; if (rTPos == 512) rTPos = 0;       \
02225    }                                              \
02226    rNToGo--;
02227 
02228 
02229 
02230 /*---------------------------------------------------*/
02231 /*--- The Reversible Transformation (tm)          ---*/
02232 /*---------------------------------------------------*/
02233 
02234 /*---------------------------------------------*/
02235 void randomiseBlock ( void )
02236 {
02237    Int32 i;
02238    RAND_DECLS;
02239    for (i = 0; i < 256; i++) inUse[i] = False;
02240 
02241    for (i = 0; i <= last; i++) {
02242       RAND_UPD_MASK;
02243       block[i] ^= RAND_MASK;
02244       inUse[block[i]] = True;
02245    }
02246 }
02247 
02248 
02249 /*---------------------------------------------*/
02250 void doReversibleTransformation ( void )
02251 {
02252    Int32 i;
02253 
02254    if (verbosity >= 2) fprintf ( stderr, "\n" );
02255 
02256    workLimit       = workFactor * last;
02257    workDone        = 0;
02258    blockRandomised = False;
02259    firstAttempt    = True;
02260 
02261    sortIt ();
02262 
02263    if (verbosity >= 3)
02264       fprintf ( stderr, "      %d work, %d block, ratio %5.2f\n",
02265                         workDone, last, (float)workDone / (float)(last) );
02266 
02267    if (workDone > workLimit && firstAttempt) {
02268       if (verbosity >= 2)
02269          fprintf ( stderr, "    sorting aborted; randomising block\n" );
02270       randomiseBlock ();
02271       workLimit = workDone = 0;
02272       blockRandomised = True;
02273       firstAttempt = False;
02274       sortIt();
02275       if (verbosity >= 3)
02276          fprintf ( stderr, "      %d work, %d block, ratio %f\n",
02277                            workDone, last, (float)workDone / (float)(last) );
02278    }
02279 
02280    origPtr = -1;
02281    for (i = 0; i <= last; i++)
02282        if (zptr[i] == 0)
02283           { origPtr = i; break; };
02284 
02285    if (origPtr == -1) panic ( "doReversibleTransformation" );
02286 }
02287 
02288 
02289 /*---------------------------------------------*/
02290 
02291 INLINE Int32 indexIntoF ( Int32 indx, Int32 *cftab )
02292 {
02293    Int32 nb, na, mid;
02294    nb = 0;
02295    na = 256;
02296    do {
02297       mid = (nb + na) >> 1;
02298       if (indx >= cftab[mid]) nb = mid; else na = mid;
02299    }
02300    while (na - nb != 1);
02301    return nb;
02302 }
02303 
02304 
02305 #define GET_SMALL(cccc)                     \
02306                                             \
02307       cccc = indexIntoF ( tPos, cftab );    \
02308       tPos = GET_LL(tPos);
02309 
02310 
02311 void undoReversibleTransformation_small ( FILE* dst )
02312 {
02313    Int32  cftab[257], cftabAlso[257];
02314    Int32  i, j, tmp, tPos;
02315    UChar  ch;
02316 
02317    /*--
02318       We assume here that the global array unzftab will
02319       already be holding the frequency counts for
02320       ll8[0 .. last].
02321    --*/
02322 
02323    /*-- Set up cftab to facilitate generation of indexIntoF --*/
02324    cftab[0] = 0;
02325    for (i = 1; i <= 256; i++) cftab[i] = unzftab[i-1];
02326    for (i = 1; i <= 256; i++) cftab[i] += cftab[i-1];
02327 
02328    /*-- Make a copy of it, used in generation of T --*/
02329    for (i = 0; i <= 256; i++) cftabAlso[i] = cftab[i];
02330 
02331    /*-- compute the T vector --*/
02332    for (i = 0; i <= last; i++) {
02333       ch = (UChar)ll16[i];
02334       SET_LL(i, cftabAlso[ch]);
02335       cftabAlso[ch]++;
02336    }
02337 
02338    /*--
02339       Compute T^(-1) by pointer reversal on T.  This is rather
02340       subtle, in that, if the original block was two or more
02341       (in general, N) concatenated copies of the same thing,
02342       the T vector will consist of N cycles, each of length
02343       blocksize / N, and decoding will involve traversing one
02344       of these cycles N times.  Which particular cycle doesn't
02345       matter -- they are all equivalent.  The tricky part is to
02346       make sure that the pointer reversal creates a correct
02347       reversed cycle for us to traverse.  So, the code below
02348       simply reverses whatever cycle origPtr happens to fall into,
02349       without regard to the cycle length.  That gives one reversed
02350       cycle, which for normal blocks, is the entire block-size long.
02351       For repeated blocks, it will be interspersed with the other
02352       N-1 non-reversed cycles.  Providing that the F-subscripting
02353       phase which follows starts at origPtr, all then works ok.
02354    --*/
02355    i = origPtr;
02356    j = GET_LL(i);
02357    do {
02358       tmp = GET_LL(j);
02359       SET_LL(j, i);
02360       i = j;
02361       j = tmp;
02362    }
02363       while (i != origPtr);
02364 
02365    /*--
02366       We recreate the original by subscripting F through T^(-1).
02367       The run-length-decoder below requires characters incrementally,
02368       so tPos is set to a starting value, and is updated by
02369       the GET_SMALL macro.
02370    --*/
02371    tPos   = origPtr;
02372 
02373    /*-------------------------------------------------*/
02374    /*--
02375       This is pretty much a verbatim copy of the
02376       run-length decoder present in the distribution
02377       bzip-0.21; it has to be here to avoid creating
02378       block[] as an intermediary structure.  As in 0.21,
02379       this code derives from some sent to me by
02380       Christian von Roques.
02381 
02382       It allows dst==NULL, so as to support the test (-t)
02383       option without slowing down the fast decompression
02384       code.
02385    --*/
02386    {
02387       IntNative retVal;
02388       Int32     i2, count, chPrev, ch2;
02389       UInt32    localCrc;
02390 
02391       count    = 0;
02392       i2       = 0;
02393       ch2      = 256;   /*-- not a char and not EOF --*/
02394       localCrc = getGlobalCRC();
02395 
02396       {
02397          RAND_DECLS;
02398          while ( i2 <= last ) {
02399             chPrev = ch2;
02400             GET_SMALL(ch2);
02401             if (blockRandomised) {
02402                RAND_UPD_MASK;
02403                ch2 ^= (UInt32)RAND_MASK;
02404             }
02405             i2++;
02406    
02407             if (dst)
02408                retVal = putc ( ch2, dst );
02409    
02410             UPDATE_CRC ( localCrc, (UChar)ch2 );
02411    
02412             if (ch2 != chPrev) {
02413                count = 1;
02414             } else {
02415                count++;
02416                if (count >= 4) {
02417                   Int32 j2;
02418                   UChar z;
02419                   GET_SMALL(z);
02420                   if (blockRandomised) {
02421                      RAND_UPD_MASK;
02422                      z ^= RAND_MASK;
02423                   }
02424                   for (j2 = 0;  j2 < (Int32)z;  j2++) {
02425                      if (dst) retVal = putc (ch2, dst);
02426                      UPDATE_CRC ( localCrc, (UChar)ch2 );
02427                   }
02428                   i2++;
02429                   count = 0;
02430                }
02431             }
02432          }
02433       }
02434 
02435       setGlobalCRC ( localCrc );
02436    }
02437    /*-- end of the in-line run-length-decoder. --*/
02438 }
02439 #undef GET_SMALL
02440 
02441 
02442 /*---------------------------------------------*/
02443 
02444 #define GET_FAST(cccc)                       \
02445                                              \
02446       cccc = ll8[tPos];                      \
02447       tPos = tt[tPos];
02448 
02449 
02450 void undoReversibleTransformation_fast ( FILE* dst )
02451 {
02452    Int32  cftab[257];
02453    Int32  i, tPos;
02454    UChar  ch;
02455 
02456    /*--
02457       We assume here that the global array unzftab will
02458       already be holding the frequency counts for
02459       ll8[0 .. last].
02460    --*/
02461 
02462    /*-- Set up cftab to facilitate generation of T^(-1) --*/
02463    cftab[0] = 0;
02464    for (i = 1; i <= 256; i++) cftab[i] = unzftab[i-1];
02465    for (i = 1; i <= 256; i++) cftab[i] += cftab[i-1];
02466 
02467    /*-- compute the T^(-1) vector --*/
02468    for (i = 0; i <= last; i++) {
02469       ch = (UChar)ll8[i];
02470       tt[cftab[ch]] = i;
02471       cftab[ch]++;
02472    }
02473 
02474    /*--
02475       We recreate the original by subscripting L through T^(-1).
02476       The run-length-decoder below requires characters incrementally,
02477       so tPos is set to a starting value, and is updated by
02478       the GET_FAST macro.
02479    --*/
02480    tPos   = tt[origPtr];
02481 
02482    /*-------------------------------------------------*/
02483    /*--
02484       This is pretty much a verbatim copy of the
02485       run-length decoder present in the distribution
02486       bzip-0.21; it has to be here to avoid creating
02487       block[] as an intermediary structure.  As in 0.21,
02488       this code derives from some sent to me by
02489       Christian von Roques.
02490    --*/
02491    {
02492       IntNative retVal;
02493       Int32     i2, count, chPrev, ch2;
02494       UInt32    localCrc;
02495 
02496       count    = 0;
02497       i2       = 0;
02498       ch2      = 256;   /*-- not a char and not EOF --*/
02499       localCrc = getGlobalCRC();
02500 
02501       if (blockRandomised) {
02502          RAND_DECLS;
02503          while ( i2 <= last ) {
02504             chPrev = ch2;
02505             GET_FAST(ch2);
02506             RAND_UPD_MASK;
02507             ch2 ^= (UInt32)RAND_MASK;
02508             i2++;
02509    
02510             retVal = putc ( ch2, dst );
02511             UPDATE_CRC ( localCrc, (UChar)ch2 );
02512    
02513             if (ch2 != chPrev) {
02514                count = 1;
02515             } else {
02516                count++;
02517                if (count >= 4) {
02518                   Int32 j2;
02519                   UChar z;
02520                   GET_FAST(z);
02521                   RAND_UPD_MASK;
02522                   z ^= RAND_MASK;
02523                   for (j2 = 0;  j2 < (Int32)z;  j2++) {
02524                      retVal = putc (ch2, dst);
02525                      UPDATE_CRC ( localCrc, (UChar)ch2 );
02526                   }
02527                   i2++;
02528                   count = 0;
02529                }
02530             }
02531          }
02532 
02533       } else {
02534 
02535          while ( i2 <= last ) {
02536             chPrev = ch2;
02537             GET_FAST(ch2);
02538             i2++;
02539    
02540             retVal = putc ( ch2, dst );
02541             UPDATE_CRC ( localCrc, (UChar)ch2 );
02542    
02543             if (ch2 != chPrev) {
02544                count = 1;
02545             } else {
02546                count++;
02547                if (count >= 4) {
02548                   Int32 j2;
02549                   UChar z;
02550                   GET_FAST(z);
02551                   for (j2 = 0;  j2 < (Int32)z;  j2++) {
02552                      retVal = putc (ch2, dst);
02553                      UPDATE_CRC ( localCrc, (UChar)ch2 );
02554                   }
02555                   i2++;
02556                   count = 0;
02557                }
02558             }
02559          }
02560 
02561       }   /*-- if (blockRandomised) --*/
02562 
02563       setGlobalCRC ( localCrc );
02564    }
02565    /*-- end of the in-line run-length-decoder. --*/
02566 }
02567 #undef GET_FAST
02568 
02569 
02570 /*---------------------------------------------------*/
02571 /*--- The block loader and RLEr                   ---*/
02572 /*---------------------------------------------------*/
02573 
02574 /*---------------------------------------------*/
02575 /*  Top 16:   run length, 1 to 255.
02576 *   Lower 16: the char, or MY_EOF for EOF.
02577 */
02578 
02579 #define MY_EOF 257
02580 
02581 INLINE Int32 getRLEpair ( FILE* src )
02582 {
02583    Int32     runLength;
02584    IntNative ch, chLatest;
02585 
02586    ch = getc ( src );
02587 
02588    /*--- Because I have no idea what kind of a value EOF is. ---*/
02589    if (ch == EOF) {
02590       ERROR_IF_NOT_ZERO ( ferror(src));
02591       return (1 << 16) | MY_EOF;
02592    }
02593 
02594    runLength = 0;
02595    do {
02596       chLatest = getc ( src );
02597       runLength++;
02598       bytesIn++;
02599    }
02600       while (ch == chLatest && runLength < 255);
02601 
02602    if ( chLatest != EOF ) {
02603       if ( ungetc ( chLatest, src ) == EOF )
02604          panic ( "getRLEpair: ungetc failed" );
02605    } else {
02606       ERROR_IF_NOT_ZERO ( ferror(src) );
02607    }
02608 
02609    /*--- Conditional is just a speedup hack. ---*/
02610    if (runLength == 1) {
02611       UPDATE_CRC ( globalCrc, (UChar)ch );
02612       return (1 << 16) | ch;
02613    } else {
02614       Int32 i;
02615       for (i = 1; i <= runLength; i++)
02616          UPDATE_CRC ( globalCrc, (UChar)ch );
02617       return (runLength << 16) | ch;
02618    }
02619 }
02620 
02621 
02622 /*---------------------------------------------*/
02623 void loadAndRLEsource ( FILE* src )
02624 {
02625    Int32 ch, allowableBlockSize, i;
02626 
02627    last = -1;
02628    ch   = 0;
02629 
02630    for (i = 0; i < 256; i++) inUse[i] = False;
02631 
02632    /*--- 20 is just a paranoia constant ---*/
02633    allowableBlockSize = 100000 * blockSize100k - 20;
02634 
02635    while (last < allowableBlockSize && ch != MY_EOF) {
02636       Int32 rlePair, runLen;
02637       rlePair = getRLEpair ( src );
02638       ch      = rlePair & 0xFFFF;
02639       runLen  = (UInt32)rlePair >> 16;
02640 
02641       #if DEBUG
02642          assert (runLen >= 1 && runLen <= 255);
02643       #endif
02644 
02645       if (ch != MY_EOF) {
02646          inUse[ch] = True;
02647          switch (runLen) {
02648             case 1:
02649                last++; block[last] = (UChar)ch; break;
02650             case 2:
02651                last++; block[last] = (UChar)ch;
02652                last++; block[last] = (UChar)ch; break;
02653             case 3:
02654                last++; block[last] = (UChar)ch;
02655                last++; block[last] = (UChar)ch;
02656                last++; block[last] = (UChar)ch; break;
02657             default:
02658                inUse[runLen-4] = True;
02659                last++; block[last] = (UChar)ch;
02660                last++; block[last] = (UChar)ch;
02661                last++; block[last] = (UChar)ch;
02662                last++; block[last] = (UChar)ch;
02663                last++; block[last] = (UChar)(runLen-4); break;
02664          }
02665       }
02666    }
02667 }
02668 
02669 
02670 /*---------------------------------------------------*/
02671 /*--- Processing of complete files and streams    ---*/
02672 /*---------------------------------------------------*/
02673 
02674 /*---------------------------------------------*/
02675 void compressStream ( FILE *stream, FILE *zStream )
02676 {
02677    IntNative  retVal;
02678    UInt32     blockCRC, combinedCRC;
02679    Int32      blockNo;
02680 
02681    blockNo  = 0;
02682    bytesIn  = 0;
02683    bytesOut = 0;
02684    nBlocksRandomised = 0;
02685 
02686    SET_BINARY_MODE(stream);
02687    SET_BINARY_MODE(zStream);
02688 
02689    ERROR_IF_NOT_ZERO ( ferror(stream) );
02690    ERROR_IF_NOT_ZERO ( ferror(zStream) );
02691 
02692    bsSetStream ( zStream, True );
02693 
02694    /*--- Write `magic' bytes B and Z,
02695          then h indicating file-format == huffmanised,
02696          followed by a digit indicating blockSize100k.
02697    ---*/
02698    bsPutUChar ( 'B' );
02699    bsPutUChar ( 'Z' );
02700    bsPutUChar ( 'h' );
02701    bsPutUChar ( '0' + blockSize100k );
02702 
02703    combinedCRC = 0;
02704 
02705    if (verbosity >= 2) fprintf ( stderr, "\n" );
02706 
02707    while (True) {
02708 
02709       blockNo++;
02710       initialiseCRC ();
02711       loadAndRLEsource ( stream );
02712       ERROR_IF_NOT_ZERO ( ferror(stream) );
02713       if (last == -1) break;
02714 
02715       blockCRC = getFinalCRC ();
02716       combinedCRC = (combinedCRC << 1) | (combinedCRC >> 31);
02717       combinedCRC ^= blockCRC;
02718 
02719       if (verbosity >= 2)
02720          fprintf ( stderr, "    block %d: crc = 0x%8x, combined CRC = 0x%8x, size = %d",
02721                            blockNo, blockCRC, combinedCRC, last+1 );
02722 
02723       /*-- sort the block and establish posn of original string --*/
02724       doReversibleTransformation ();
02725 
02726       /*--
02727         A 6-byte block header, the value chosen arbitrarily
02728         as 0x314159265359 :-).  A 32 bit value does not really
02729         give a strong enough guarantee that the value will not
02730         appear by chance in the compressed datastream.  Worst-case
02731         probability of this event, for a 900k block, is about
02732         2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits.
02733         For a compressed file of size 100Gb -- about 100000 blocks --
02734         only a 48-bit marker will do.  NB: normal compression/
02735         decompression do *not* rely on these statistical properties.
02736         They are only important when trying to recover blocks from
02737         damaged files.
02738       --*/
02739       bsPutUChar ( 0x31 ); bsPutUChar ( 0x41 );
02740       bsPutUChar ( 0x59 ); bsPutUChar ( 0x26 );
02741       bsPutUChar ( 0x53 ); bsPutUChar ( 0x59 );
02742 
02743       /*-- Now the block's CRC, so it is in a known place. --*/
02744       bsPutUInt32 ( blockCRC );
02745 
02746       /*-- Now a single bit indicating randomisation. --*/
02747       if (blockRandomised) {
02748          bsW(1,1); nBlocksRandomised++;
02749       } else
02750          bsW(1,0);
02751 
02752       /*-- Finally, block's contents proper. --*/
02753       moveToFrontCodeAndSend ();
02754 
02755       ERROR_IF_NOT_ZERO ( ferror(zStream) );
02756    }
02757 
02758    if (verbosity >= 2 && nBlocksRandomised > 0)
02759       fprintf ( stderr, "    %d block%s needed randomisation\n", 
02760                         nBlocksRandomised,
02761                         nBlocksRandomised == 1 ? "" : "s" );
02762 
02763    /*--
02764       Now another magic 48-bit number, 0x177245385090, to
02765       indicate the end of the last block.  (sqrt(pi), if
02766       you want to know.  I did want to use e, but it contains
02767       too much repetition -- 27 18 28 18 28 46 -- for me
02768       to feel statistically comfortable.  Call me paranoid.)
02769    --*/
02770 
02771    bsPutUChar ( 0x17 ); bsPutUChar ( 0x72 );
02772    bsPutUChar ( 0x45 ); bsPutUChar ( 0x38 );
02773    bsPutUChar ( 0x50 ); bsPutUChar ( 0x90 );
02774 
02775    bsPutUInt32 ( combinedCRC );
02776    if (verbosity >= 2)
02777       fprintf ( stderr, "    final combined CRC = 0x%x\n   ", combinedCRC );
02778 
02779    /*-- Close the files in an utterly paranoid way. --*/
02780    bsFinishedWithStream ();
02781 
02782    ERROR_IF_NOT_ZERO ( ferror(zStream) );
02783    retVal = fflush ( zStream );
02784    ERROR_IF_EOF ( retVal );
02785    retVal = fclose ( zStream );
02786    ERROR_IF_EOF ( retVal );
02787 
02788    ERROR_IF_NOT_ZERO ( ferror(stream) );
02789    retVal = fclose ( stream );
02790    ERROR_IF_EOF ( retVal );
02791 
02792    if (bytesIn == 0) bytesIn = 1;
02793    if (bytesOut == 0) bytesOut = 1;
02794 
02795    if (verbosity >= 1)
02796       fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, "
02797                         "%5.2f%% saved, %d in, %d out.\n",
02798                 (float)bytesIn / (float)bytesOut,
02799                 (8.0 * (float)bytesOut) / (float)bytesIn,
02800                 100.0 * (1.0 - (float)bytesOut / (float)bytesIn),
02801                 bytesIn,
02802                 bytesOut
02803               );
02804 }
02805 
02806 
02807 /*---------------------------------------------*/
02808 Bool uncompressStream ( FILE *zStream, FILE *stream )
02809 {
02810    UChar      magic1, magic2, magic3, magic4;
02811    UChar      magic5, magic6;
02812    UInt32     storedBlockCRC, storedCombinedCRC;
02813    UInt32     computedBlockCRC, computedCombinedCRC;
02814    Int32      currBlockNo;
02815    IntNative  retVal;
02816 
02817    SET_BINARY_MODE(stream);
02818    SET_BINARY_MODE(zStream);
02819 
02820    ERROR_IF_NOT_ZERO ( ferror(stream) );
02821    ERROR_IF_NOT_ZERO ( ferror(zStream) );
02822 
02823    bsSetStream ( zStream, False );
02824 
02825    /*--
02826       A bad magic number is `recoverable from';
02827       return with False so the caller skips the file.
02828    --*/
02829    magic1 = bsGetUChar ();
02830    magic2 = bsGetUChar ();
02831    magic3 = bsGetUChar ();
02832    magic4 = bsGetUChar ();
02833    if (magic1 != 'B' ||
02834        magic2 != 'Z' ||
02835        magic3 != 'h' ||
02836        magic4 < '1'  ||
02837        magic4 > '9') {
02838      bsFinishedWithStream();
02839      retVal = fclose ( stream );
02840      ERROR_IF_EOF ( retVal );
02841      return False;
02842    }
02843 
02844    setDecompressStructureSizes ( magic4 - '0' );
02845    computedCombinedCRC = 0;
02846 
02847    if (verbosity >= 2) fprintf ( stderr, "\n    " );
02848    currBlockNo = 0;
02849 
02850    while (True) {
02851       magic1 = bsGetUChar ();
02852       magic2 = bsGetUChar ();
02853       magic3 = bsGetUChar ();
02854       magic4 = bsGetUChar ();
02855       magic5 = bsGetUChar ();
02856       magic6 = bsGetUChar ();
02857       if (magic1 == 0x17 && magic2 == 0x72 &&
02858           magic3 == 0x45 && magic4 == 0x38 &&
02859           magic5 == 0x50 && magic6 == 0x90) break;
02860 
02861       if (magic1 != 0x31 || magic2 != 0x41 ||
02862           magic3 != 0x59 || magic4 != 0x26 ||
02863           magic5 != 0x53 || magic6 != 0x59) badBlockHeader();
02864 
02865       storedBlockCRC = bsGetUInt32 ();
02866 
02867       if (bsR(1) == 1)
02868          blockRandomised = True; else
02869          blockRandomised = False;
02870 
02871       currBlockNo++;
02872       if (verbosity >= 2)
02873          fprintf ( stderr, "[%d: huff+mtf ", currBlockNo );
02874       getAndMoveToFrontDecode ();
02875       ERROR_IF_NOT_ZERO ( ferror(zStream) );
02876 
02877       initialiseCRC();
02878       if (verbosity >= 2) fprintf ( stderr, "rt+rld" );
02879       if (smallMode)
02880          undoReversibleTransformation_small ( stream );
02881          else
02882          undoReversibleTransformation_fast  ( stream );
02883 
02884       ERROR_IF_NOT_ZERO ( ferror(stream) );
02885 
02886       computedBlockCRC = getFinalCRC();
02887       if (verbosity >= 3)
02888          fprintf ( stderr, " {0x%x, 0x%x}", storedBlockCRC, computedBlockCRC );
02889       if (verbosity >= 2) fprintf ( stderr, "] " );
02890 
02891       /*-- A bad CRC is considered a fatal error. --*/
02892       if (storedBlockCRC != computedBlockCRC)
02893          crcError ( storedBlockCRC, computedBlockCRC );
02894 
02895       computedCombinedCRC = (computedCombinedCRC << 1) | (computedCombinedCRC >> 31);
02896       computedCombinedCRC ^= computedBlockCRC;
02897    };
02898 
02899    if (verbosity >= 2) fprintf ( stderr, "\n    " );
02900 
02901    storedCombinedCRC  = bsGetUInt32 ();
02902    if (verbosity >= 2)
02903       fprintf ( stderr,
02904                 "combined CRCs: stored = 0x%x, computed = 0x%x\n    ",
02905                 storedCombinedCRC, computedCombinedCRC );
02906    if (storedCombinedCRC != computedCombinedCRC)
02907       crcError ( storedCombinedCRC, computedCombinedCRC );
02908 
02909 
02910    bsFinishedWithStream ();
02911    ERROR_IF_NOT_ZERO ( ferror(zStream) );
02912    retVal = fclose ( zStream );
02913    ERROR_IF_EOF ( retVal );
02914 
02915    ERROR_IF_NOT_ZERO ( ferror(stream) );
02916    retVal = fflush ( stream );
02917    ERROR_IF_NOT_ZERO ( retVal );
02918    if (stream != stdout) {
02919       retVal = fclose ( stream );
02920       ERROR_IF_EOF ( retVal );
02921    }
02922    return True;
02923 }
02924 
02925 
02926 /*---------------------------------------------*/
02927 Bool testStream ( FILE *zStream )
02928 {
02929    UChar      magic1, magic2, magic3, magic4;
02930    UChar      magic5, magic6;
02931    UInt32     storedBlockCRC, storedCombinedCRC;
02932    UInt32     computedBlockCRC, computedCombinedCRC;
02933    Int32      currBlockNo;
02934    IntNative  retVal;
02935 
02936    SET_BINARY_MODE(zStream);
02937    ERROR_IF_NOT_ZERO ( ferror(zStream) );
02938 
02939    bsSetStream ( zStream, False );
02940 
02941    magic1 = bsGetUChar ();
02942    magic2 = bsGetUChar ();
02943    magic3 = bsGetUChar ();
02944    magic4 = bsGetUChar ();
02945    if (magic1 != 'B' ||
02946        magic2 != 'Z' ||
02947        magic3 != 'h' ||
02948        magic4 < '1'  ||
02949        magic4 > '9') {
02950      bsFinishedWithStream();
02951      fclose ( zStream );
02952      fprintf ( stderr, "\n%s: bad magic number (ie, not created by bzip2)\n",
02953                        inName );
02954      return False;
02955    }
02956 
02957    smallMode = True;
02958    setDecompressStructureSizes ( magic4 - '0' );
02959    computedCombinedCRC = 0;
02960 
02961    if (verbosity >= 2) fprintf ( stderr, "\n" );
02962    currBlockNo = 0;
02963 
02964    while (True) {
02965       magic1 = bsGetUChar ();
02966       magic2 = bsGetUChar ();
02967       magic3 = bsGetUChar ();
02968       magic4 = bsGetUChar ();
02969       magic5 = bsGetUChar ();
02970       magic6 = bsGetUChar ();
02971       if (magic1 == 0x17 && magic2 == 0x72 &&
02972           magic3 == 0x45 && magic4 == 0x38 &&
02973           magic5 == 0x50 && magic6 == 0x90) break;
02974 
02975       currBlockNo++;
02976       if (magic1 != 0x31 || magic2 != 0x41 ||
02977           magic3 != 0x59 || magic4 != 0x26 ||
02978           magic5 != 0x53 || magic6 != 0x59) {
02979          bsFinishedWithStream();
02980          fclose ( zStream );
02981          fprintf ( stderr,
02982                    "\n%s, block %d: bad header (not == 0x314159265359)\n",
02983                    inName, currBlockNo );
02984          return False;
02985       }
02986       storedBlockCRC = bsGetUInt32 ();
02987 
02988       if (bsR(1) == 1)
02989          blockRandomised = True; else
02990          blockRandomised = False;
02991 
02992       if (verbosity >= 2)
02993          fprintf ( stderr, "    block [%d: huff+mtf ", currBlockNo );
02994       getAndMoveToFrontDecode ();
02995       ERROR_IF_NOT_ZERO ( ferror(zStream) );
02996 
02997       initialiseCRC();
02998       if (verbosity >= 2) fprintf ( stderr, "rt+rld" );
02999       undoReversibleTransformation_small ( NULL );
03000 
03001       computedBlockCRC = getFinalCRC();
03002       if (verbosity >= 3)
03003          fprintf ( stderr, " {0x%x, 0x%x}", storedBlockCRC, computedBlockCRC );
03004       if (verbosity >= 2) fprintf ( stderr, "] " );
03005 
03006       if (storedBlockCRC != computedBlockCRC) {
03007          bsFinishedWithStream();
03008          fclose ( zStream );
03009          fprintf ( stderr, "\n%s, block %d: computed CRC does not match stored one\n",
03010                            inName, currBlockNo );
03011          return False;
03012       }
03013 
03014       if (verbosity >= 2) fprintf ( stderr, "ok\n" );
03015       computedCombinedCRC = (computedCombinedCRC << 1) | (computedCombinedCRC >> 31);
03016       computedCombinedCRC ^= computedBlockCRC;
03017    };
03018 
03019    storedCombinedCRC  = bsGetUInt32 ();
03020    if (verbosity >= 2)
03021       fprintf ( stderr,
03022                 "    combined CRCs: stored = 0x%x, computed = 0x%x\n    ",
03023                 storedCombinedCRC, computedCombinedCRC );
03024    if (storedCombinedCRC != computedCombinedCRC) {
03025       bsFinishedWithStream();
03026       fclose ( zStream );
03027       fprintf ( stderr, "\n%s: computed CRC does not match stored one\n",
03028                         inName );
03029       return False;
03030    }
03031 
03032    bsFinishedWithStream ();
03033    ERROR_IF_NOT_ZERO ( ferror(zStream) );
03034    retVal = fclose ( zStream );
03035    ERROR_IF_EOF ( retVal );
03036    return True;
03037 }
03038 
03039 
03040 
03041 /*---------------------------------------------------*/
03042 /*--- Error [non-] handling grunge                ---*/
03043 /*---------------------------------------------------*/
03044 
03045 /*---------------------------------------------*/
03046 void cadvise ( void )
03047 {
03048    fprintf (
03049       stderr,
03050       "\nIt is possible that the compressed file(s) have become corrupted.\n"
03051         "You can use the -tvv option to test integrity of such files.\n\n"
03052         "You can use the `bzip2recover' program to *attempt* to recover\n"
03053         "data from undamaged sections of corrupted files.\n\n"
03054     );
03055 }
03056 
03057 
03058 /*---------------------------------------------*/
03059 void showFileNames ( void )
03060 {
03061    fprintf (
03062       stderr,
03063       "\tInput file = %s, output file = %s\n",
03064       inName==NULL  ? "(null)" : inName,
03065       outName==NULL ? "(null)" : outName
03066    );
03067 }
03068 
03069 
03070 /*---------------------------------------------*/
03071 void cleanUpAndFail ( Int32 ec )
03072 {
03073    IntNative retVal;
03074 
03075    if ( srcMode == SM_F2F && opMode != OM_TEST ) {
03076       fprintf ( stderr, "%s: Deleting output file %s, if it exists.\n",
03077                 progName,
03078                 outName==NULL ? "(null)" : outName );
03079       if (outputHandleJustInCase != NULL)
03080          fclose ( outputHandleJustInCase );
03081       retVal = remove ( outName );
03082       if (retVal != 0)
03083          fprintf ( stderr,
03084                    "%s: WARNING: deletion of output file (apparently) failed.\n",
03085                    progName );
03086    }
03087    if (numFileNames > 0 && numFilesProcessed < numFileNames) {
03088       fprintf ( stderr, 
03089                 "%s: WARNING: some files have not been processed:\n"
03090                 "\t%d specified on command line, %d not processed yet.\n\n",
03091                 progName, numFileNames, 
03092                           numFileNames - numFilesProcessed );
03093    }
03094    exit ( ec );
03095 }
03096 
03097 
03098 /*---------------------------------------------*/
03099 void panic ( Char* s )
03100 {
03101    fprintf ( stderr,
03102              "\n%s: PANIC -- internal consistency error:\n"
03103              "\t%s\n"
03104              "\tThis is a BUG.  Please report it to me at:\n"
03105              "\tjseward@acm.org\n",
03106              progName, s );
03107    showFileNames();
03108    cleanUpAndFail( 3 );
03109 }
03110 
03111 
03112 /*---------------------------------------------*/
03113 void badBGLengths ( void )
03114 {
03115    fprintf ( stderr,
03116              "\n%s: error when reading background model code lengths,\n"
03117              "\twhich probably means the compressed file is corrupted.\n",
03118              progName );
03119    showFileNames();
03120    cadvise();
03121    cleanUpAndFail( 2 );
03122 }
03123 
03124 
03125 /*---------------------------------------------*/
03126 void crcError ( UInt32 crcStored, UInt32 crcComputed )
03127 {
03128    fprintf ( stderr,
03129              "\n%s: Data integrity error when decompressing.\n"
03130              "\tStored CRC = 0x%x, computed CRC = 0x%x\n",
03131              progName, crcStored, crcComputed );
03132    showFileNames();
03133    cadvise();
03134    cleanUpAndFail( 2 );
03135 }
03136 
03137 
03138 /*---------------------------------------------*/
03139 void compressedStreamEOF ( void )
03140 {
03141    fprintf ( stderr,
03142              "\n%s: Compressed file ends unexpectedly;\n\t"
03143              "perhaps it is corrupted?  *Possible* reason follows.\n",
03144              progName );
03145    perror ( progName );
03146    showFileNames();
03147    cadvise();
03148    cleanUpAndFail( 2 );
03149 }
03150 
03151 
03152 /*---------------------------------------------*/
03153 void ioError ( )
03154 {
03155    fprintf ( stderr,
03156              "\n%s: I/O or other error, bailing out.  Possible reason follows.\n",
03157              progName );
03158    perror ( progName );
03159    showFileNames();
03160    cleanUpAndFail( 1 );
03161 }
03162 
03163 
03164 /*---------------------------------------------*/
03165 void blockOverrun ()
03166 {
03167    fprintf ( stderr,
03168              "\n%s: block overrun during decompression,\n"
03169              "\twhich probably means the compressed file\n"
03170              "\tis corrupted.\n",
03171              progName );
03172    showFileNames();
03173    cadvise();
03174    cleanUpAndFail( 2 );
03175 }
03176 
03177 
03178 /*---------------------------------------------*/
03179 void badBlockHeader ()
03180 {
03181    fprintf ( stderr,
03182              "\n%s: bad block header in the compressed file,\n"
03183              "\twhich probably means it is corrupted.\n",
03184              progName );
03185    showFileNames();
03186    cadvise();
03187    cleanUpAndFail( 2 );
03188 }
03189 
03190 
03191 /*---------------------------------------------*/
03192 void bitStreamEOF ()
03193 {
03194    fprintf ( stderr,
03195              "\n%s: read past the end of compressed data,\n"
03196              "\twhich probably means it is corrupted.\n",
03197              progName );
03198    showFileNames();
03199    cadvise();
03200    cleanUpAndFail( 2 );
03201 }
03202 
03203 
03204 /*---------------------------------------------*/
03205 void mySignalCatcher ( IntNative n )
03206 {
03207    fprintf ( stderr,
03208              "\n%s: Control-C (or similar) caught, quitting.\n",
03209              progName );
03210    cleanUpAndFail(1);
03211 }
03212 
03213 
03214 /*---------------------------------------------*/
03215 void mySIGSEGVorSIGBUScatcher ( IntNative n )
03216 {
03217    if (opMode == OM_Z)
03218       fprintf ( stderr,
03219                 "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing,\n"
03220                 "\twhich probably indicates a bug in bzip2.  Please\n"
03221                 "\treport it to me at: jseward@acm.org\n",
03222                 progName );
03223       else
03224       fprintf ( stderr,
03225                 "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing,\n"
03226                 "\twhich probably indicates that the compressed data\n"
03227                 "\tis corrupted.\n",
03228                 progName );
03229 
03230    showFileNames();
03231    if (opMode == OM_Z)
03232       cleanUpAndFail( 3 ); else
03233       { cadvise(); cleanUpAndFail( 2 ); }
03234 }
03235 
03236 
03237 /*---------------------------------------------*/
03238 void uncompressOutOfMemory ( Int32 draw, Int32 blockSize )
03239 {
03240    fprintf ( stderr,
03241              "\n%s: Can't allocate enough memory for decompression.\n"
03242              "\tRequested %d bytes for a block size of %d.\n"
03243              "\tTry selecting space-economic decompress (with flag -s)\n"
03244              "\tand failing that, find a machine with more memory.\n",
03245              progName, draw, blockSize );
03246    showFileNames();
03247    cleanUpAndFail(1);
03248 }
03249 
03250 
03251 /*---------------------------------------------*/
03252 void compressOutOfMemory ( Int32 draw, Int32 blockSize )
03253 {
03254    fprintf ( stderr,
03255              "\n%s: Can't allocate enough memory for compression.\n"
03256              "\tRequested %d bytes for a block size of %d.\n"
03257              "\tTry selecting a small block size (with flag -s).\n",
03258              progName, draw, blockSize );
03259    showFileNames();
03260    cleanUpAndFail(1);
03261 }
03262 
03263 
03264 /*---------------------------------------------------*/
03265 /*--- The main driver machinery                   ---*/
03266 /*---------------------------------------------------*/
03267 
03268 /*---------------------------------------------*/
03269 void pad ( Char *s )
03270 {
03271    Int32 i;
03272    if ( (Int32)strlen(s) >= longestFileName ) return;
03273    for (i = 1; i <= longestFileName - (Int32)strlen(s); i++)
03274       fprintf ( stderr, " " );
03275 }
03276 
03277 
03278 /*---------------------------------------------*/
03279 Bool fileExists ( Char* name )
03280 {
03281    FILE *tmp   = fopen ( name, "rb" );
03282    Bool exists = (tmp != NULL);
03283    if (tmp != NULL) fclose ( tmp );
03284    return exists;
03285 }
03286 
03287 
03288 /*---------------------------------------------*/
03289 /*--
03290   if in doubt, return True
03291 --*/
03292 Bool notABogStandardFile ( Char* name )
03293 {
03294    IntNative      i;
03295    struct MY_STAT statBuf;
03296 
03297    i = MY_LSTAT ( name, &statBuf );
03298    if (i != 0) return True;
03299    if (MY_S_IFREG(statBuf.st_mode)) return False;
03300    return True;
03301 }
03302 
03303 
03304 /*---------------------------------------------*/
03305 void copyDateAndPermissions ( Char *srcName, Char *dstName )
03306 {
03307    #if BZ_UNIX
03308    IntNative      retVal;
03309    struct MY_STAT statBuf;
03310    struct utimbuf uTimBuf;
03311 
03312    retVal = MY_LSTAT ( srcName, &statBuf );
03313    ERROR_IF_NOT_ZERO ( retVal );
03314    uTimBuf.actime = statBuf.st_atime;
03315    uTimBuf.modtime = statBuf.st_mtime;
03316 
03317    retVal = chmod ( dstName, statBuf.st_mode );
03318    ERROR_IF_NOT_ZERO ( retVal );
03319    retVal = utime ( dstName, &uTimBuf );
03320    ERROR_IF_NOT_ZERO ( retVal );
03321    #endif
03322 }
03323 
03324 
03325 /*---------------------------------------------*/
03326 Bool endsInBz2 ( Char* name )
03327 {
03328    Int32 n = strlen ( name );
03329    if (n <= 4) return False;
03330    return
03331       (name[n-4] == '.' &&
03332        name[n-3] == 'b' &&
03333        name[n-2] == 'z' &&
03334        name[n-1] == '2');
03335 }
03336 
03337 
03338 /*---------------------------------------------*/
03339 Bool containsDubiousChars ( Char* name )
03340 {
03341    Bool cdc = False;
03342    for (; *name != '\0'; name++)
03343       if (*name == '?' || *name == '*') cdc = True;
03344    return cdc;
03345 }
03346 
03347 
03348 /*---------------------------------------------*/
03349 void compress ( Char *name )
03350 {
03351    FILE *inStr;
03352    FILE *outStr;
03353 
03354    if (name == NULL && srcMode != SM_I2O)
03355       panic ( "compress: bad modes\n" );
03356 
03357    switch (srcMode) {
03358       case SM_I2O: strcpy ( inName, "(stdin)" );
03359                    strcpy ( outName, "(stdout)" ); break;
03360       case SM_F2F: strcpy ( inName, name );
03361                    strcpy ( outName, name );
03362                    strcat ( outName, ".bz2" ); break;
03363       case SM_F2O: strcpy ( inName, name );
03364                    strcpy ( outName, "(stdout)" ); break;
03365    }
03366 
03367    if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
03368       fprintf ( stderr, "%s: There are no files matching `%s'.\n",
03369       progName, inName );
03370       return;
03371    }
03372    if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
03373       fprintf ( stderr, "%s: Input file %s doesn't exist, skipping.\n",
03374                 progName, inName );
03375       return;
03376    }
03377    if ( srcMode != SM_I2O && endsInBz2 ( inName )) {
03378       fprintf ( stderr, "%s: Input file name %s ends in `.bz2', skipping.\n",
03379                 progName, inName );
03380       return;
03381    }
03382    if ( srcMode != SM_I2O && notABogStandardFile ( inName )) {
03383       fprintf ( stderr, "%s: Input file %s is not a normal file, skipping.\n",
03384                 progName, inName );
03385       return;
03386    }
03387    if ( srcMode == SM_F2F && fileExists ( outName ) ) {
03388       fprintf ( stderr, "%s: Output file %s already exists, skipping.\n",
03389                 progName, outName );
03390       return;
03391    }
03392 
03393    switch ( srcMode ) {
03394 
03395       case SM_I2O:
03396          inStr = stdin;
03397          outStr = stdout;
03398          if ( isatty ( fileno ( stdout ) ) ) {
03399             fprintf ( stderr,
03400                       "%s: I won't write compressed data to a terminal.\n",
03401                       progName );
03402             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
03403                               progName, progName );
03404             return;
03405          };
03406          break;
03407 
03408       case SM_F2O:
03409          inStr = fopen ( inName, "rb" );
03410          outStr = stdout;
03411          if ( isatty ( fileno ( stdout ) ) ) {
03412             fprintf ( stderr,
03413                       "%s: I won't write compressed data to a terminal.\n",
03414                       progName );
03415             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
03416                               progName, progName );
03417             return;
03418          };
03419          if ( inStr == NULL ) {
03420             fprintf ( stderr, "%s: Can't open input file %s, skipping.\n",
03421                       progName, inName );
03422             return;
03423          };
03424          break;
03425 
03426       case SM_F2F:
03427          inStr = fopen ( inName, "rb" );
03428          outStr = fopen ( outName, "wb" );
03429          if ( outStr == NULL) {
03430             fprintf ( stderr, "%s: Can't create output file %s, skipping.\n",
03431                       progName, outName );
03432             return;
03433          }
03434          if ( inStr == NULL ) {
03435             fprintf ( stderr, "%s: Can't open input file %s, skipping.\n",
03436                       progName, inName );
03437             return;
03438          };
03439          break;
03440 
03441       default:
03442          panic ( "compress: bad srcMode" );
03443          break;
03444    }
03445 
03446    if (verbosity >= 1) {
03447       fprintf ( stderr,  "  %s: ", inName );
03448       pad ( inName );
03449       fflush ( stderr );
03450    }
03451 
03452    /*--- Now the input and output handles are sane.  Do the Biz. ---*/
03453    outputHandleJustInCase = outStr;
03454    compressStream ( inStr, outStr );
03455    outputHandleJustInCase = NULL;
03456 
03457    /*--- If there was an I/O error, we won't get here. ---*/
03458    if ( srcMode == SM_F2F ) {
03459       copyDateAndPermissions ( inName, outName );
03460       if ( !keepInputFiles ) {
03461          IntNative retVal = remove ( inName );
03462          ERROR_IF_NOT_ZERO ( retVal );
03463       }
03464    }
03465 }
03466 
03467 
03468 /*---------------------------------------------*/
03469 void uncompress ( Char *name )
03470 {
03471    FILE *inStr;
03472    FILE *outStr;
03473    Bool magicNumberOK;
03474 
03475    if (name == NULL && srcMode != SM_I2O)
03476       panic ( "uncompress: bad modes\n" );
03477 
03478    switch (srcMode) {
03479       case SM_I2O: strcpy ( inName, "(stdin)" );
03480                    strcpy ( outName, "(stdout)" ); break;
03481       case SM_F2F: strcpy ( inName, name );
03482                    strcpy ( outName, name );
03483                    if (endsInBz2 ( outName ))
03484                       outName [ strlen ( outName ) - 4 ] = '\0';
03485                    break;
03486       case SM_F2O: strcpy ( inName, name );
03487                    strcpy ( outName, "(stdout)" ); break;
03488    }
03489 
03490    if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
03491       fprintf ( stderr, "%s: There are no files matching `%s'.\n",
03492                 progName, inName );
03493       return;
03494    }
03495    if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
03496       fprintf ( stderr, "%s: Input file %s doesn't exist, skipping.\n",
03497                 progName, inName );
03498       return;
03499    }
03500    if ( srcMode != SM_I2O && !endsInBz2 ( inName )) {
03501       fprintf ( stderr,
03502                 "%s: Input file name %s doesn't end in `.bz2', skipping.\n",
03503                 progName, inName );
03504       return;
03505    }
03506    if ( srcMode != SM_I2O && notABogStandardFile ( inName )) {
03507       fprintf ( stderr, "%s: Input file %s is not a normal file, skipping.\n",
03508                 progName, inName );
03509       return;
03510    }
03511    if ( srcMode == SM_F2F && fileExists ( outName ) ) {
03512       fprintf ( stderr, "%s: Output file %s already exists, skipping.\n",
03513                 progName, outName );
03514       return;
03515    }
03516 
03517    switch ( srcMode ) {
03518 
03519       case SM_I2O:
03520          inStr = stdin;
03521          outStr = stdout;
03522          if ( isatty ( fileno ( stdin ) ) ) {
03523             fprintf ( stderr,
03524                       "%s: I won't read compressed data from a terminal.\n",
03525                       progName );
03526             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
03527                               progName, progName );
03528             return;
03529          };
03530          break;
03531 
03532       case SM_F2O:
03533          inStr = fopen ( inName, "rb" );
03534          outStr = stdout;
03535          if ( inStr == NULL ) {
03536             fprintf ( stderr, "%s: Can't open input file %s, skipping.\n",
03537                       progName, inName );
03538             return;
03539          };
03540          break;
03541 
03542       case SM_F2F:
03543          inStr = fopen ( inName, "rb" );
03544          outStr = fopen ( outName, "wb" );
03545          if ( outStr == NULL) {
03546             fprintf ( stderr, "%s: Can't create output file %s, skipping.\n",
03547                       progName, outName );
03548             return;
03549          }
03550          if ( inStr == NULL ) {
03551             fprintf ( stderr, "%s: Can't open input file %s, skipping.\n",
03552                       progName, inName );
03553             return;
03554          };
03555          break;
03556 
03557       default:
03558          panic ( "uncompress: bad srcMode" );
03559          break;
03560    }
03561 
03562    if (verbosity >= 1) {
03563       fprintf ( stderr, "  %s: ", inName );
03564       pad ( inName );
03565       fflush ( stderr );
03566    }
03567 
03568    /*--- Now the input and output handles are sane.  Do the Biz. ---*/
03569    outputHandleJustInCase = outStr;
03570    magicNumberOK = uncompressStream ( inStr, outStr );
03571    outputHandleJustInCase = NULL;
03572 
03573    /*--- If there was an I/O error, we won't get here. ---*/
03574    if ( magicNumberOK ) {
03575       if ( srcMode == SM_F2F ) {
03576          copyDateAndPermissions ( inName, outName );
03577          if ( !keepInputFiles ) {
03578             IntNative retVal = remove ( inName );
03579             ERROR_IF_NOT_ZERO ( retVal );
03580          }
03581       }
03582    } else {
03583       if ( srcMode == SM_F2F ) {
03584          IntNative retVal = remove ( outName );
03585          ERROR_IF_NOT_ZERO ( retVal );
03586       }
03587    }
03588 
03589    if ( magicNumberOK ) {
03590       if (verbosity >= 1)
03591          fprintf ( stderr, "done\n" );
03592    } else {
03593       if (verbosity >= 1)
03594          fprintf ( stderr, "not a bzip2 file, skipping.\n" ); else
03595          fprintf ( stderr,
03596                    "%s: %s is not a bzip2 file, skipping.\n",
03597                    progName, inName );
03598    }
03599 
03600 }
03601 
03602 
03603 /*---------------------------------------------*/
03604 void testf ( Char *name )
03605 {
03606    FILE *inStr;
03607    Bool allOK;
03608 
03609    if (name == NULL && srcMode != SM_I2O)
03610       panic ( "testf: bad modes\n" );
03611 
03612    strcpy ( outName, "(none)" );
03613    switch (srcMode) {
03614       case SM_I2O: strcpy ( inName, "(stdin)" ); break;
03615       case SM_F2F: strcpy ( inName, name ); break;
03616       case SM_F2O: strcpy ( inName, name ); break;
03617    }
03618 
03619    if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
03620       fprintf ( stderr, "%s: There are no files matching `%s'.\n",
03621                 progName, inName );
03622       return;
03623    }
03624    if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
03625       fprintf ( stderr, "%s: Input file %s doesn't exist, skipping.\n",
03626                 progName, inName );
03627       return;
03628    }
03629    if ( srcMode != SM_I2O && !endsInBz2 ( inName )) {
03630       fprintf ( stderr,
03631                 "%s: Input file name %s doesn't end in `.bz2', skipping.\n",
03632                 progName, inName );
03633       return;
03634    }
03635    if ( srcMode != SM_I2O && notABogStandardFile ( inName )) {
03636       fprintf ( stderr, "%s: Input file %s is not a normal file, skipping.\n",
03637                 progName, inName );
03638       return;
03639    }
03640 
03641    switch ( srcMode ) {
03642 
03643       case SM_I2O:
03644          if ( isatty ( fileno ( stdin ) ) ) {
03645             fprintf ( stderr,
03646                       "%s: I won't read compressed data from a terminal.\n",
03647                       progName );
03648             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
03649                               progName, progName );
03650             return;
03651          };
03652          inStr = stdin;
03653          break;
03654 
03655       case SM_F2O: case SM_F2F:
03656          inStr = fopen ( inName, "rb" );
03657          if ( inStr == NULL ) {
03658             fprintf ( stderr, "%s: Can't open input file %s, skipping.\n",
03659                       progName, inName );
03660             return;
03661          };
03662          break;
03663 
03664       default:
03665          panic ( "testf: bad srcMode" );
03666          break;
03667    }
03668 
03669    if (verbosity >= 1) {
03670       fprintf ( stderr, "  %s: ", inName );
03671       pad ( inName );
03672       fflush ( stderr );
03673    }
03674 
03675    /*--- Now the input handle is sane.  Do the Biz. ---*/
03676    allOK = testStream ( inStr );
03677 
03678    if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" );
03679    if (!allOK) testFailsExist = True;
03680 }
03681 
03682 
03683 /*---------------------------------------------*/
03684 void license ( void )
03685 {
03686    fprintf ( stderr,
03687 
03688     "bzip2, a block-sorting file compressor.  "
03689     "Version 0.1pl2, 29-Aug-97.\n"
03690     "   \n"
03691     "   Copyright (C) 1996, 1997 by Julian Seward.\n"
03692     "   \n"
03693     "   This program is free software; you can redistribute it and/or modify\n"
03694     "   it under the terms of the GNU General Public License as published by\n"
03695     "   the Free Software Foundation; either version 2 of the License, or\n"
03696     "   (at your option) any later version.\n"
03697     "   \n"
03698     "   This program is distributed in the hope that it will be useful,\n"
03699     "   but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
03700     "   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
03701     "   GNU General Public License for more details.\n"
03702     "   \n"
03703     "   You should have received a copy of the GNU General Public License\n"
03704     "   along with this program; if not, write to the Free Software\n"
03705     "   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
03706     "   \n"
03707     "   The GNU General Public License is contained in the file LICENSE.\n"
03708     "   \n"
03709    );
03710 }
03711 
03712 
03713 /*---------------------------------------------*/
03714 void usage ( Char *fullProgName )
03715 {
03716    fprintf (
03717       stderr,
03718       "bzip2, a block-sorting file compressor.  "
03719       "Version 0.1pl2, 29-Aug-97.\n"
03720       "\n   usage: %s [flags and input files in any order]\n"
03721       "\n"
03722       "   -h --help           print this message\n"
03723       "   -d --decompress     force decompression\n"
03724       "   -f --compress       force compression\n"
03725       "   -t --test           test compressed file integrity\n"
03726       "   -c --stdout         output to standard out\n"
03727       "   -v --verbose        be verbose (a 2nd -v gives more)\n"
03728       "   -k --keep           keep (don't delete) input files\n"
03729       "   -L --license        display software version & license\n"
03730       "   -V --version        display software version & license\n"
03731       "   -s --small          use less memory (at most 2500k)\n"
03732       "   -1 .. -9            set block size to 100k .. 900k\n"
03733       "   --repetitive-fast   compress repetitive blocks faster\n"
03734       "   --repetitive-best   compress repetitive blocks better\n"
03735       "\n"
03736       "   If invoked as `bzip2', the default action is to compress.\n"
03737       "              as `bunzip2', the default action is to decompress.\n"
03738       "\n"
03739       "   If no file names are given, bzip2 compresses or decompresses\n"
03740       "   from standard input to standard output.  You can combine\n"
03741       "   flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
03742       #if BZ_UNIX
03743       "\n"
03744       #endif
03745       ,
03746 
03747       fullProgName
03748    );
03749 }
03750 
03751 
03752 /*---------------------------------------------*/
03753 /*--
03754   All the garbage from here to main() is purely to
03755   implement a linked list of command-line arguments,
03756   into which main() copies argv[1 .. argc-1].
03757 
03758   The purpose of this ridiculous exercise is to
03759   facilitate the expansion of wildcard characters
03760   * and ? in filenames for halfwitted OSs like
03761   MSDOS, Windows 95 and NT.
03762 
03763   The actual Dirty Work is done by the platform-specific
03764   macro APPEND_FILESPEC.
03765 --*/
03766 
03767 typedef
03768    struct zzzz {
03769       Char        *name;
03770       struct zzzz *link;
03771    }
03772    Cell;
03773 
03774 
03775 /*---------------------------------------------*/
03776 void *myMalloc ( Int32 n )
03777 {
03778    void* p;
03779 
03780    p = malloc ( (size_t)n );
03781    if (p == NULL) {
03782       fprintf (
03783          stderr,
03784          "%s: `malloc' failed on request for %d bytes.\n",
03785          progName, n
03786       );
03787       exit ( 1 );
03788    }
03789    return p;
03790 }
03791 
03792 
03793 /*---------------------------------------------*/
03794 Cell *mkCell ( void )
03795 {
03796    Cell *c;
03797 
03798    c = (Cell*) myMalloc ( sizeof ( Cell ) );
03799    c->name = NULL;
03800    c->link = NULL;
03801    return c;
03802 }
03803 
03804 
03805 /*---------------------------------------------*/
03806 Cell *snocString ( Cell *root, Char *name )
03807 {
03808    if (root == NULL) {
03809       Cell *tmp = mkCell();
03810       tmp->name = (Char*) myMalloc ( 5 + strlen(name) );
03811       strcpy ( tmp->name, name );
03812       return tmp;
03813    } else {
03814       Cell *tmp = root;
03815       while (tmp->link != NULL) tmp = tmp->link;
03816       tmp->link = snocString ( tmp->link, name );
03817       return root;
03818    }
03819 }
03820 
03821 
03822 
03823 /*---------------------------------------------*/
03824 #define ISFLAG(s) (strcmp(aa->name, (s))==0)
03825 
03826 
03827 IntNative main ( IntNative argc, Char *argv[] )
03828 {
03829    Int32  i, j;
03830    Char   *tmp;
03831    Cell   *argList;
03832    Cell   *aa;
03833 
03834 
03835    #if DEBUG
03836       fprintf ( stderr, "bzip2: *** compiled with debugging ON ***\n" );
03837    #endif
03838 
03839    /*-- Be really really really paranoid :-) --*/
03840    if (sizeof(Int32) != 4 || sizeof(UInt32) != 4  ||
03841        sizeof(Int16) != 2 || sizeof(UInt16) != 2  ||
03842        sizeof(Char)  != 1 || sizeof(UChar)  != 1) {
03843       fprintf ( stderr,
03844                 "bzip2: I'm not configured correctly for this platform!\n"
03845                 "\tI require Int32, Int16 and Char to have sizes\n"
03846                 "\tof 4, 2 and 1 bytes to run properly, and they don't.\n"
03847                 "\tProbably you can fix this by defining them correctly,\n"
03848                 "\tand recompiling.  Bye!\n" );
03849       exit(1);
03850    }
03851 
03852 
03853    /*-- Set up signal handlers --*/
03854    signal (SIGINT,  mySignalCatcher);
03855    signal (SIGTERM, mySignalCatcher);
03856    signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
03857    #if BZ_UNIX
03858    signal (SIGHUP,  mySignalCatcher);
03859    signal (SIGBUS,  mySIGSEGVorSIGBUScatcher);
03860    #endif
03861 
03862 
03863    /*-- Initialise --*/
03864    outputHandleJustInCase  = NULL;
03865    ftab                    = NULL;
03866    ll4                     = NULL;
03867    ll16                    = NULL;
03868    ll8                     = NULL;
03869    tt                      = NULL;
03870    block                   = NULL;
03871    zptr                    = NULL;
03872    smallMode               = False;
03873    keepInputFiles          = False;
03874    verbosity               = 0;
03875    blockSize100k           = 9;
03876    testFailsExist          = False;
03877    bsStream                = NULL;
03878    numFileNames            = 0;
03879    numFilesProcessed       = 0;
03880    workFactor              = 30;
03881 
03882    strcpy ( inName,  "(none)" );
03883    strcpy ( outName, "(none)" );
03884 
03885    strcpy ( progNameReally, argv[0] );
03886    progName = &progNameReally[0];
03887    for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++)
03888       if (*tmp == PATH_SEP) progName = tmp + 1;
03889 
03890 
03891    /*-- Expand filename wildcards in arg list --*/
03892    argList = NULL;
03893    for (i = 1; i <= argc-1; i++)
03894       APPEND_FILESPEC(argList, argv[i]);
03895 
03896 
03897    /*-- Find the length of the longest filename --*/
03898    longestFileName = 7;
03899    numFileNames    = 0;
03900    for (aa = argList; aa != NULL; aa = aa->link)
03901       if (aa->name[0] != '-') {
03902          numFileNames++;
03903          if (longestFileName < (Int32)strlen(aa->name) )
03904             longestFileName = (Int32)strlen(aa->name);
03905       }
03906 
03907 
03908    /*-- Determine what to do (compress/uncompress/test). --*/
03909    /*-- Note that subsequent flag handling may change this. --*/
03910    opMode = OM_Z;
03911 
03912    if ( (strcmp ( "bunzip2",     progName ) == 0) ||
03913         (strcmp ( "BUNZIP2",     progName ) == 0) ||
03914         (strcmp ( "bunzip2.exe", progName ) == 0) ||
03915         (strcmp ( "BUNZIP2.EXE", progName ) == 0) )
03916       opMode = OM_UNZ;
03917 
03918 
03919    /*-- Determine source modes; flag handling may change this too. --*/
03920    if (numFileNames == 0)
03921       srcMode = SM_I2O; else srcMode = SM_F2F;
03922 
03923 
03924    /*-- Look at the flags. --*/
03925    for (aa = argList; aa != NULL; aa = aa->link)
03926       if (aa->name[0] == '-' && aa->name[1] != '-')
03927          for (j = 1; aa->name[j] != '\0'; j++)
03928             switch (aa->name[j]) {
03929                case 'c': srcMode          = SM_F2O; break;
03930                case 'd': opMode           = OM_UNZ; break;
03931                case 'f': opMode           = OM_Z; break;
03932                case 't': opMode           = OM_TEST; break;
03933                case 'k': keepInputFiles   = True; break;
03934                case 's': smallMode        = True; break;
03935                case '1': blockSize100k    = 1; break;
03936                case '2': blockSize100k    = 2; break;
03937                case '3': blockSize100k    = 3; break;
03938                case '4': blockSize100k    = 4; break;
03939                case '5': blockSize100k    = 5; break;
03940                case '6': blockSize100k    = 6; break;
03941                case '7': blockSize100k    = 7; break;
03942                case '8': blockSize100k    = 8; break;
03943                case '9': blockSize100k    = 9; break;
03944                case 'V':
03945                case 'L': license();            break;
03946                case 'v': verbosity++; break;
03947                case 'h': usage ( progName );
03948                          exit ( 1 );
03949                          break;
03950                default:  fprintf ( stderr, "%s: Bad flag `%s'\n",
03951                                    progName, aa->name );
03952                          usage ( progName );
03953                          exit ( 1 );
03954                          break;
03955          }
03956 
03957    /*-- And again ... --*/
03958    for (aa = argList; aa != NULL; aa = aa->link) {
03959       if (ISFLAG("--stdout"))            srcMode          = SM_F2O;  else
03960       if (ISFLAG("--decompress"))        opMode           = OM_UNZ;  else
03961       if (ISFLAG("--compress"))          opMode           = OM_Z;    else
03962       if (ISFLAG("--test"))              opMode           = OM_TEST; else
03963       if (ISFLAG("--keep"))              keepInputFiles   = True;    else
03964       if (ISFLAG("--small"))             smallMode        = True;    else
03965       if (ISFLAG("--version"))           license();                  else
03966       if (ISFLAG("--license"))           license();                  else
03967       if (ISFLAG("--repetitive-fast"))   workFactor = 5;             else
03968       if (ISFLAG("--repetitive-best"))   workFactor = 150;           else
03969       if (ISFLAG("--verbose"))           verbosity++;                else
03970       if (ISFLAG("--help"))              { usage ( progName ); exit ( 1 ); }
03971          else
03972          if (strncmp ( aa->name, "--", 2) == 0) {
03973             fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name );
03974             usage ( progName );
03975             exit ( 1 );
03976          }
03977    }
03978 
03979    if (opMode == OM_Z && smallMode) blockSize100k = 2;
03980 
03981    if (opMode == OM_Z && srcMode == SM_F2O && numFileNames > 1) {
03982       fprintf ( stderr, "%s: I won't compress multiple files to stdout.\n",
03983                 progName );
03984       exit ( 1 );
03985    }
03986 
03987    if (srcMode == SM_F2O && numFileNames == 0) {
03988       fprintf ( stderr, "%s: -c expects at least one filename.\n",
03989                 progName );
03990       exit ( 1 );
03991    }
03992 
03993    if (opMode == OM_TEST && srcMode == SM_F2O) {
03994       fprintf ( stderr, "%s: -c and -t cannot be used together.\n",
03995                 progName );
03996       exit ( 1 );
03997    }
03998 
03999    if (opMode != OM_Z) blockSize100k = 0;
04000 
04001    if (opMode == OM_Z) {
04002       allocateCompressStructures();
04003       if (srcMode == SM_I2O)
04004          compress ( NULL );
04005          else
04006          for (aa = argList; aa != NULL; aa = aa->link)
04007             if (aa->name[0] != '-') {
04008                numFilesProcessed++;
04009                compress ( aa->name );
04010             }
04011    } else
04012    if (opMode == OM_UNZ) {
04013       if (srcMode == SM_I2O)
04014          uncompress ( NULL );
04015          else
04016          for (aa = argList; aa != NULL; aa = aa->link)
04017             if (aa->name[0] != '-') {
04018                numFilesProcessed++;
04019                uncompress ( aa->name );
04020             }
04021    } else {
04022       testFailsExist = False;
04023       if (srcMode == SM_I2O)
04024          testf ( NULL );
04025          else
04026          for (aa = argList; aa != NULL; aa = aa->link)
04027             if (aa->name[0] != '-') {
04028                numFilesProcessed++;
04029                testf ( aa->name );
04030             }
04031       if (testFailsExist) {
04032          fprintf ( stderr,
04033            "\n"
04034            "You can use the `bzip2recover' program to *attempt* to recover\n"
04035            "data from undamaged sections of corrupted files.\n\n"
04036          );
04037          exit(2);
04038       }
04039    }
04040    return 0;
04041 }
04042 
04043 
04044 /*-----------------------------------------------------------*/
04045 /*--- end                                         bzip2.c ---*/
04046 /*-----------------------------------------------------------*/
 

Powered by Plone

This site conforms to the following standards: