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