00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 #define BZ_UNIX      1
00098 
00099 
00100 
00101 
00102 
00103 
00104 #define BZ_LCCWIN32  0
00105 
00106 
00107 
00108 
00109 
00110 
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 
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 
00161 
00162 
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    
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 
00234 
00235 
00236 #define Bool   unsigned char
00237 #define True   1
00238 #define False  0
00239 
00240 
00241 
00242 
00243 
00244 #define IntNative int
00245 
00246 
00247 
00248 
00249 
00250 #ifndef DEBUG
00251 #define DEBUG 0
00252 #endif
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272 
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 UInt32  bytesIn, bytesOut;
00337 Int32   verbosity;
00338 Bool    keepInputFiles, smallMode, testFailsExist;
00339 UInt32  globalCrc;
00340 Int32   numFileNames, numFilesProcessed;
00341 
00342 
00343 
00344 #define SM_I2O           1
00345 #define SM_F2O           2
00346 #define SM_F2F           3
00347 
00348 
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 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 #define NUM_OVERSHOOT_BYTES 20
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 UChar    *block;    
00412 UInt16   *quadrant; 
00413 Int32    *zptr;      
00414 UInt16   *szptr;    
00415 Int32    *ftab;     
00416 
00417 UInt16   *ll16;     
00418 UChar    *ll4;      
00419 
00420 Int32    *tt;       
00421 UChar    *ll8;      
00422 
00423 
00424 
00425 
00426 
00427 
00428 Int32   unzftab[256];
00429 
00430 
00431 
00432 
00433 
00434 
00435 Int32  last;
00436 
00437 
00438 
00439 
00440 
00441 Int32  origPtr;
00442 
00443 
00444 
00445 
00446 
00447 
00448 Int32  blockSize100k;
00449 
00450 
00451 
00452 
00453 
00454 
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 
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 
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 
00504 Int32  code [N_GROUPS][MAX_ALPHA_SIZE];
00505 Int32  rfreq[N_GROUPS][MAX_ALPHA_SIZE];
00506 
00507 
00508 
00509 
00510 
00511 
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519 UInt32 crc32Table[256] = {
00520 
00521    
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 
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 
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 
00833 
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 
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 
00976 
00977 
00978 
00979 
00980 
00981 
00982 
00983 
00984 
00985 
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 
01011 
01012 
01013 
01014    block++;
01015 
01016    
01017 
01018 
01019 
01020 
01021 
01022 
01023 
01024 
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 
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 
01187 
01188 
01189 
01190 
01191 
01192 
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    
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    
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 
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          
01272          if (gs >= nMTF) break;
01273          ge = gs + G_SIZE - 1; 
01274          if (ge >= nMTF) ge = nMTF-1;
01275 
01276          
01277 
01278 
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 
01305 
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 
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 
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    
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    
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    
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    
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    
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++;  };
01420          while (curr > len[t][i]) { bsW(2,3); curr--;  };
01421          bsW ( 1, 0 );
01422       }
01423    }
01424 
01425    if (verbosity >= 3)
01426       fprintf ( stderr, "code lengths %d, ", bytesOut-nBytes );
01427 
01428    
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    
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    
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    
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    
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    
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 
01574 
01575 
01576 
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 
01635 
01636 
01637 
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 
01659 
01660 
01661 
01662 
01663 
01664 
01665 
01666 
01667 
01668 
01669 
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 
01680 
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 
01765 
01766 
01767 
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          
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          
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          
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 
01838 
01839 
01840 
01841 
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 
01886 
01887 
01888 
01889 
01890 
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 
01981 
01982 
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 
01997 
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 
02038 
02039 
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 
02066 
02067 
02068       for (i = 0; i <= 255; i++) {
02069 
02070          
02071 
02072 
02073          ss = runningOrder[i];
02074 
02075          
02076 
02077 
02078 
02079 
02080 
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 
02102 
02103 
02104 
02105 
02106 
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 
02130 
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 
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 
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 
02319 
02320 
02321 
02322 
02323    
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    
02329    for (i = 0; i <= 256; i++) cftabAlso[i] = cftab[i];
02330 
02331    
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 
02340 
02341 
02342 
02343 
02344 
02345 
02346 
02347 
02348 
02349 
02350 
02351 
02352 
02353 
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 
02367 
02368 
02369 
02370 
02371    tPos   = origPtr;
02372 
02373    
02374    
02375 
02376 
02377 
02378 
02379 
02380 
02381 
02382 
02383 
02384 
02385 
02386    {
02387       IntNative retVal;
02388       Int32     i2, count, chPrev, ch2;
02389       UInt32    localCrc;
02390 
02391       count    = 0;
02392       i2       = 0;
02393       ch2      = 256;   
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    
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 
02458 
02459 
02460 
02461 
02462    
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    
02468    for (i = 0; i <= last; i++) {
02469       ch = (UChar)ll8[i];
02470       tt[cftab[ch]] = i;
02471       cftab[ch]++;
02472    }
02473 
02474    
02475 
02476 
02477 
02478 
02479 
02480    tPos   = tt[origPtr];
02481 
02482    
02483    
02484 
02485 
02486 
02487 
02488 
02489 
02490 
02491    {
02492       IntNative retVal;
02493       Int32     i2, count, chPrev, ch2;
02494       UInt32    localCrc;
02495 
02496       count    = 0;
02497       i2       = 0;
02498       ch2      = 256;   
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       }   
02562 
02563       setGlobalCRC ( localCrc );
02564    }
02565    
02566 }
02567 #undef GET_FAST
02568 
02569 
02570 
02571 
02572 
02573 
02574 
02575 
02576 
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    
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    
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    
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 
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    
02695 
02696 
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       
02724       doReversibleTransformation ();
02725 
02726       
02727 
02728 
02729 
02730 
02731 
02732 
02733 
02734 
02735 
02736 
02737 
02738 
02739       bsPutUChar ( 0x31 ); bsPutUChar ( 0x41 );
02740       bsPutUChar ( 0x59 ); bsPutUChar ( 0x26 );
02741       bsPutUChar ( 0x53 ); bsPutUChar ( 0x59 );
02742 
02743       
02744       bsPutUInt32 ( blockCRC );
02745 
02746       
02747       if (blockRandomised) {
02748          bsW(1,1); nBlocksRandomised++;
02749       } else
02750          bsW(1,0);
02751 
02752       
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 
02765 
02766 
02767 
02768 
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    
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 
02827 
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       
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 
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 
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 
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    
03453    outputHandleJustInCase = outStr;
03454    compressStream ( inStr, outStr );
03455    outputHandleJustInCase = NULL;
03456 
03457    
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    
03569    outputHandleJustInCase = outStr;
03570    magicNumberOK = uncompressStream ( inStr, outStr );
03571    outputHandleJustInCase = NULL;
03572 
03573    
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    
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 
03755 
03756 
03757 
03758 
03759 
03760 
03761 
03762 
03763 
03764 
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    
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    
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    
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    
03892    argList = NULL;
03893    for (i = 1; i <= argc-1; i++)
03894       APPEND_FILESPEC(argList, argv[i]);
03895 
03896 
03897    
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    
03909    
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    
03920    if (numFileNames == 0)
03921       srcMode = SM_I2O; else srcMode = SM_F2F;
03922 
03923 
03924    
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    
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 
04046