Commit bb2dc47110fe0a0a05ee2039adc1de4ddf2fb9c2

Authored by dg
1 parent e4822482

test


git-svn-id: http://svn.net-core.org/repos/t-engine4@4373 51575b47-30f0-44d4-a5cc-537603b46e54

Too many changes to show.

To preserve performance only 13 of 13+ files are displayed.

... ... @@ -22,7 +22,7 @@ project "TEngine"
22 22 language "C"
23 23 targetname("t-engine")
24 24 files { "../src/*.c", }
25   - links { "physfs", "lua".._OPTIONS.lua, "fov", "luasocket", "luaprofiler", "lualanes", "lpeg", "tcodimport", "lxp", "expatstatic", "luamd5", "luazlib", "luabitop" }
  25 + links { "physfs", "lua".._OPTIONS.lua, "fov", "luasocket", "luaprofiler", "lualanes", "lpeg", "tcodimport", "lxp", "expatstatic", "luamd5", "luazlib", "luabitop", "te4-bzip" }
26 26 defines { "_DEFAULT_VIDEOMODE_FLAGS_='SDL_HWSURFACE|SDL_DOUBLEBUF'" }
27 27 defines { [[TENGINE_HOME_PATH='".t-engine"']], "TE4CORE_VERSION="..TE4CORE_VERSION }
28 28
... ... @@ -272,3 +272,10 @@ project "utf8proc"
272 272 targetname "utf8proc"
273 273
274 274 files { "../src/utf8proc/utf8proc.c", }
  275 +
  276 +project "te4-bzip"
  277 + kind "StaticLib"
  278 + language "C"
  279 + targetname "te4-bzip"
  280 +
  281 + files { "../src/bzip2/*.c", }
... ...
... ... @@ -45,13 +45,19 @@ Still, this is a golden age. Civilisations are healing the wounds of thousands o
45 45 You are an adventurer, set out to discover wonders, explore old places, and venture into the unknown for wealth and glory.
46 46 ]]
47 47 starter = "mod.load"
  48 +
  49 +-- List of additional team files required
  50 +teams = {
  51 + { "#name#-#version#-music.team", "optional", {"/data/music/"} },
  52 + { "#name#-#version#-gfx-shockbolt.team", "optional", {"/data/gfx/shockbolt/"} },
  53 +}
  54 +
48 55 loading_wait_ticks = 260
49 56 profile_stats_fields = {"artifacts", "characters", "deaths", "uniques", "scores", "lore", "escorts"}
50 57 allow_userchat = true -- We can talk to the online community
51 58 no_get_name = true -- Name setting for new characters is done by the module itself
52 59
53 60 -- Define the fields that are sync'ed online, and how they are sync'ed
54   --- '
55 61 profile_defs = {
56 62 allow_build = { {name="index:string:30"}, receive=function(data, save) save[data.name] = true end, export=function(env) for k, _ in pairs(env) do add{name=k} end end },
57 63 lore = { {name="index:string:30"}, receive=function(data, save) save.lore = save.lore or {} save.lore[data.name] = true end, export=function(env) for k, v in pairs(env.lore or {}) do add{name=k} end end },
... ... @@ -82,6 +88,7 @@ profile_defs = {
82 88 },
83 89 }
84 90
  91 +-- Formatter for scores
85 92 score_formatters = {
86 93 ["Maj'Eyal"] = {
87 94 alive="#LIGHT_GREEN#{score} : #BLUE#{name}#LAST# the #LIGHT_RED#level {level} {subrace} {subclass}#LAST# is still alive and well on #GREEN#{where}#LAST##WHITE#",
... ...
... ... @@ -17,6 +17,7 @@ solution "TEngine"
17 17 "src/utf8proc",
18 18 "src/physfs",
19 19 "src/physfs/zlib123",
  20 + "src/bzip2",
20 21 "/opt/SDL-1.3/include/SDL/",
21 22 "/usr/include/GL",
22 23 }
... ...
  1 +/*-
  2 + * Copyright 2003-2005 Colin Percival
  3 + * All rights reserved
  4 + *
  5 + * Redistribution and use in source and binary forms, with or without
  6 + * modification, are permitted providing that the following conditions
  7 + * are met:
  8 + * 1. Redistributions of source code must retain the above copyright
  9 + * notice, this list of conditions and the following disclaimer.
  10 + * 2. Redistributions in binary form must reproduce the above copyright
  11 + * notice, this list of conditions and the following disclaimer in the
  12 + * documentation and/or other materials provided with the distribution.
  13 + *
  14 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  18 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  22 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  23 + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24 + * POSSIBILITY OF SUCH DAMAGE.
  25 + */
  26 +
  27 +#include "bzlib.h"
  28 +#include <stdlib.h>
  29 +#include <stdio.h>
  30 +#include <string.h>
  31 +#include <unistd.h>
  32 +#include <fcntl.h>
  33 +
  34 +static off_t offtin(u_char *buf)
  35 +{
  36 + off_t y;
  37 +
  38 + y=buf[7]&0x7F;
  39 + y=y*256;y+=buf[6];
  40 + y=y*256;y+=buf[5];
  41 + y=y*256;y+=buf[4];
  42 + y=y*256;y+=buf[3];
  43 + y=y*256;y+=buf[2];
  44 + y=y*256;y+=buf[1];
  45 + y=y*256;y+=buf[0];
  46 +
  47 + if(buf[7]&0x80) y=-y;
  48 +
  49 + return y;
  50 +}
  51 +
  52 +#define returnerr(ret, str, f1, f2) { printf(str, f1, f2); perror("\nError in bspatch\n"); return (ret); }
  53 +
  54 +int bspatch(char *infile, char *outfile, char *patchfile)
  55 +{
  56 + FILE * f, * cpf, * dpf, * epf;
  57 + BZFILE * cpfbz2, * dpfbz2, * epfbz2;
  58 + int cbz2err, dbz2err, ebz2err;
  59 + int fd;
  60 + ssize_t oldsize,newsize;
  61 + ssize_t bzctrllen,bzdatalen;
  62 + u_char header[32],buf[8];
  63 + u_char *old, *new;
  64 + off_t oldpos,newpos;
  65 + off_t ctrl[3];
  66 + off_t lenread;
  67 + off_t i;
  68 +
  69 + /* Open patch file */
  70 + if ((f = fopen(patchfile, "r")) == NULL)
  71 + returnerr(1, "fopen(%s)", patchfile, 0);
  72 +
  73 + /*
  74 + File format:
  75 + 0 8 "BSDIFF40"
  76 + 8 8 X
  77 + 16 8 Y
  78 + 24 8 sizeof(newfile)
  79 + 32 X bzip2(control block)
  80 + 32+X Y bzip2(diff block)
  81 + 32+X+Y ??? bzip2(extra block)
  82 + with control block a set of triples (x,y,z) meaning "add x bytes
  83 + from oldfile to x bytes from the diff block; copy y bytes from the
  84 + extra block; seek forwards in oldfile by z bytes".
  85 + */
  86 +
  87 + /* Read header */
  88 + if (fread(header, 1, 32, f) < 32) {
  89 + if (feof(f))
  90 + errx(1, "Corrupt patch\n");
  91 + returnerr(1, "fread(%s)", patchfile, 0);
  92 + }
  93 +
  94 + /* Check for appropriate magic */
  95 + if (memcmp(header, "BSDIFF40", 8) != 0)
  96 + errx(1, "Corrupt patch\n");
  97 +
  98 + /* Read lengths from header */
  99 + bzctrllen=offtin(header+8);
  100 + bzdatalen=offtin(header+16);
  101 + newsize=offtin(header+24);
  102 + if((bzctrllen<0) || (bzdatalen<0) || (newsize<0))
  103 + errx(1,"Corrupt patch\n");
  104 +
  105 + /* Close patch file and re-open it via libbzip2 at the right places */
  106 + if (fclose(f))
  107 + returnerr(1, "fclose(%s)", patchfile, 0);
  108 + if ((cpf = fopen(patchfile, "r")) == NULL)
  109 + returnerr(1, "fopen(%s)", patchfile, 0);
  110 + if (fseeko(cpf, 32, SEEK_SET))
  111 + returnerr(1, "fseeko(%s, %lld)", patchfile,
  112 + (long long)32);
  113 + if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
  114 + errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
  115 + if ((dpf = fopen(patchfile, "r")) == NULL)
  116 + returnerr(1, "fopen(%s)", patchfile, 0);
  117 + if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
  118 + returnerr(1, "fseeko(%s, %lld)", patchfile,
  119 + (long long)(32 + bzctrllen));
  120 + if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
  121 + errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
  122 + if ((epf = fopen(patchfile, "r")) == NULL)
  123 + returnerr(1, "fopen(%s)", patchfile, 0);
  124 + if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
  125 + returnerr(1, "fseeko(%s, %lld)", patchfile,
  126 + (long long)(32 + bzctrllen + bzdatalen));
  127 + if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
  128 + errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
  129 +
  130 + if(((fd=open(infile,O_RDONLY,0))<0) ||
  131 + ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
  132 + ((old=malloc(oldsize+1))==NULL) ||
  133 + (lseek(fd,0,SEEK_SET)!=0) ||
  134 + (read(fd,old,oldsize)!=oldsize) ||
  135 + (close(fd)==-1)) returnerr(1,"%s",infile, 0);
  136 + if((new=malloc(newsize+1))==NULL) returnerr(1,"not enough memory", 0, 0);
  137 +
  138 + oldpos=0;newpos=0;
  139 + while(newpos<newsize) {
  140 + /* Read control data */
  141 + for(i=0;i<=2;i++) {
  142 + lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
  143 + if ((lenread < 8) || ((cbz2err != BZ_OK) &&
  144 + (cbz2err != BZ_STREAM_END)))
  145 + errx(1, "Corrupt patch\n");
  146 + ctrl[i]=offtin(buf);
  147 + };
  148 +
  149 + /* Sanity-check */
  150 + if(newpos+ctrl[0]>newsize)
  151 + errx(1,"Corrupt patch\n");
  152 +
  153 + /* Read diff string */
  154 + lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]);
  155 + if ((lenread < ctrl[0]) ||
  156 + ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
  157 + errx(1, "Corrupt patch\n");
  158 +
  159 + /* Add old data to diff string */
  160 + for(i=0;i<ctrl[0];i++)
  161 + if((oldpos+i>=0) && (oldpos+i<oldsize))
  162 + new[newpos+i]+=old[oldpos+i];
  163 +
  164 + /* Adjust pointers */
  165 + newpos+=ctrl[0];
  166 + oldpos+=ctrl[0];
  167 +
  168 + /* Sanity-check */
  169 + if(newpos+ctrl[1]>newsize)
  170 + errx(1,"Corrupt patch\n");
  171 +
  172 + /* Read extra string */
  173 + lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]);
  174 + if ((lenread < ctrl[1]) ||
  175 + ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
  176 + errx(1, "Corrupt patch\n");
  177 +
  178 + /* Adjust pointers */
  179 + newpos+=ctrl[1];
  180 + oldpos+=ctrl[2];
  181 + };
  182 +
  183 + /* Clean up the bzip2 reads */
  184 + BZ2_bzReadClose(&cbz2err, cpfbz2);
  185 + BZ2_bzReadClose(&dbz2err, dpfbz2);
  186 + BZ2_bzReadClose(&ebz2err, epfbz2);
  187 + if (fclose(cpf) || fclose(dpf) || fclose(epf))
  188 + returnerr(1, "fclose(%s)", patchfile, 0);
  189 +
  190 + /* Write the new file */
  191 + if(((fd=open(outfile,O_CREAT|O_TRUNC|O_WRONLY,0666))<0) ||
  192 + (write(fd,new,newsize)!=newsize) || (close(fd)==-1))
  193 + returnerr(1,"%s",outfile, 0);
  194 +
  195 + free(new);
  196 + free(old);
  197 +
  198 + return 0;
  199 +}
... ...
  1 +extern int bspatch(char *infile, char *outfile, char *patchfile);
... ...
  1 + ------------------------------------------------------------------
  2 + This file is part of bzip2/libbzip2, a program and library for
  3 + lossless, block-sorting data compression.
  4 +
  5 + bzip2/libbzip2 version 1.0.6 of 6 September 2010
  6 + Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
  7 +
  8 + Please read the WARNING, DISCLAIMER and PATENTS sections in the
  9 + README file.
  10 +
  11 + This program is released under the terms of the license contained
  12 + in the file LICENSE.
  13 + ------------------------------------------------------------------
  14 +
  15 +
  16 +0.9.0
  17 +~~~~~
  18 +First version.
  19 +
  20 +
  21 +0.9.0a
  22 +~~~~~~
  23 +Removed 'ranlib' from Makefile, since most modern Unix-es
  24 +don't need it, or even know about it.
  25 +
  26 +
  27 +0.9.0b
  28 +~~~~~~
  29 +Fixed a problem with error reporting in bzip2.c. This does not effect
  30 +the library in any way. Problem is: versions 0.9.0 and 0.9.0a (of the
  31 +program proper) compress and decompress correctly, but give misleading
  32 +error messages (internal panics) when an I/O error occurs, instead of
  33 +reporting the problem correctly. This shouldn't give any data loss
  34 +(as far as I can see), but is confusing.
  35 +
  36 +Made the inline declarations disappear for non-GCC compilers.
  37 +
  38 +
  39 +0.9.0c
  40 +~~~~~~
  41 +Fixed some problems in the library pertaining to some boundary cases.
  42 +This makes the library behave more correctly in those situations. The
  43 +fixes apply only to features (calls and parameters) not used by
  44 +bzip2.c, so the non-fixedness of them in previous versions has no
  45 +effect on reliability of bzip2.c.
  46 +
  47 +In bzlib.c:
  48 + * made zero-length BZ_FLUSH work correctly in bzCompress().
  49 + * fixed bzWrite/bzRead to ignore zero-length requests.
  50 + * fixed bzread to correctly handle read requests after EOF.
  51 + * wrong parameter order in call to bzDecompressInit in
  52 + bzBuffToBuffDecompress. Fixed.
  53 +
  54 +In compress.c:
  55 + * changed setting of nGroups in sendMTFValues() so as to
  56 + do a bit better on small files. This _does_ effect
  57 + bzip2.c.
  58 +
  59 +
  60 +0.9.5a
  61 +~~~~~~
  62 +Major change: add a fallback sorting algorithm (blocksort.c)
  63 +to give reasonable behaviour even for very repetitive inputs.
  64 +Nuked --repetitive-best and --repetitive-fast since they are
  65 +no longer useful.
  66 +
  67 +Minor changes: mostly a whole bunch of small changes/
  68 +bugfixes in the driver (bzip2.c). Changes pertaining to the
  69 +user interface are:
  70 +
  71 + allow decompression of symlink'd files to stdout
  72 + decompress/test files even without .bz2 extension
  73 + give more accurate error messages for I/O errors
  74 + when compressing/decompressing to stdout, don't catch control-C
  75 + read flags from BZIP2 and BZIP environment variables
  76 + decline to break hard links to a file unless forced with -f
  77 + allow -c flag even with no filenames
  78 + preserve file ownerships as far as possible
  79 + make -s -1 give the expected block size (100k)
  80 + add a flag -q --quiet to suppress nonessential warnings
  81 + stop decoding flags after --, so files beginning in - can be handled
  82 + resolved inconsistent naming: bzcat or bz2cat ?
  83 + bzip2 --help now returns 0
  84 +
  85 +Programming-level changes are:
  86 +
  87 + fixed syntax error in GET_LL4 for Borland C++ 5.02
  88 + let bzBuffToBuffDecompress return BZ_DATA_ERROR{_MAGIC}
  89 + fix overshoot of mode-string end in bzopen_or_bzdopen
  90 + wrapped bzlib.h in #ifdef __cplusplus ... extern "C" { ... }
  91 + close file handles under all error conditions
  92 + added minor mods so it compiles with DJGPP out of the box
  93 + fixed Makefile so it doesn't give problems with BSD make
  94 + fix uninitialised memory reads in dlltest.c
  95 +
  96 +0.9.5b
  97 +~~~~~~
  98 +Open stdin/stdout in binary mode for DJGPP.
  99 +
  100 +0.9.5c
  101 +~~~~~~
  102 +Changed BZ_N_OVERSHOOT to be ... + 2 instead of ... + 1. The + 1
  103 +version could cause the sorted order to be wrong in some extremely
  104 +obscure cases. Also changed setting of quadrant in blocksort.c.
  105 +
  106 +0.9.5d
  107 +~~~~~~
  108 +The only functional change is to make bzlibVersion() in the library
  109 +return the correct string. This has no effect whatsoever on the
  110 +functioning of the bzip2 program or library. Added a couple of casts
  111 +so the library compiles without warnings at level 3 in MS Visual
  112 +Studio 6.0. Included a Y2K statement in the file Y2K_INFO. All other
  113 +changes are minor documentation changes.
  114 +
  115 +1.0
  116 +~~~
  117 +Several minor bugfixes and enhancements:
  118 +
  119 +* Large file support. The library uses 64-bit counters to
  120 + count the volume of data passing through it. bzip2.c
  121 + is now compiled with -D_FILE_OFFSET_BITS=64 to get large
  122 + file support from the C library. -v correctly prints out
  123 + file sizes greater than 4 gigabytes. All these changes have
  124 + been made without assuming a 64-bit platform or a C compiler
  125 + which supports 64-bit ints, so, except for the C library
  126 + aspect, they are fully portable.
  127 +
  128 +* Decompression robustness. The library/program should be
  129 + robust to any corruption of compressed data, detecting and
  130 + handling _all_ corruption, instead of merely relying on
  131 + the CRCs. What this means is that the program should
  132 + never crash, given corrupted data, and the library should
  133 + always return BZ_DATA_ERROR.
  134 +
  135 +* Fixed an obscure race-condition bug only ever observed on
  136 + Solaris, in which, if you were very unlucky and issued
  137 + control-C at exactly the wrong time, both input and output
  138 + files would be deleted.
  139 +
  140 +* Don't run out of file handles on test/decompression when
  141 + large numbers of files have invalid magic numbers.
  142 +
  143 +* Avoid library namespace pollution. Prefix all exported
  144 + symbols with BZ2_.
  145 +
  146 +* Minor sorting enhancements from my DCC2000 paper.
  147 +
  148 +* Advance the version number to 1.0, so as to counteract the
  149 + (false-in-this-case) impression some people have that programs
  150 + with version numbers less than 1.0 are in some way, experimental,
  151 + pre-release versions.
  152 +
  153 +* Create an initial Makefile-libbz2_so to build a shared library.
  154 + Yes, I know I should really use libtool et al ...
  155 +
  156 +* Make the program exit with 2 instead of 0 when decompression
  157 + fails due to a bad magic number (ie, an invalid bzip2 header).
  158 + Also exit with 1 (as the manual claims :-) whenever a diagnostic
  159 + message would have been printed AND the corresponding operation
  160 + is aborted, for example
  161 + bzip2: Output file xx already exists.
  162 + When a diagnostic message is printed but the operation is not
  163 + aborted, for example
  164 + bzip2: Can't guess original name for wurble -- using wurble.out
  165 + then the exit value 0 is returned, unless some other problem is
  166 + also detected.
  167 +
  168 + I think it corresponds more closely to what the manual claims now.
  169 +
  170 +
  171 +1.0.1
  172 +~~~~~
  173 +* Modified dlltest.c so it uses the new BZ2_ naming scheme.
  174 +* Modified makefile-msc to fix minor build probs on Win2k.
  175 +* Updated README.COMPILATION.PROBLEMS.
  176 +
  177 +There are no functionality changes or bug fixes relative to version
  178 +1.0.0. This is just a documentation update + a fix for minor Win32
  179 +build problems. For almost everyone, upgrading from 1.0.0 to 1.0.1 is
  180 +utterly pointless. Don't bother.
  181 +
  182 +
  183 +1.0.2
  184 +~~~~~
  185 +A bug fix release, addressing various minor issues which have appeared
  186 +in the 18 or so months since 1.0.1 was released. Most of the fixes
  187 +are to do with file-handling or documentation bugs. To the best of my
  188 +knowledge, there have been no data-loss-causing bugs reported in the
  189 +compression/decompression engine of 1.0.0 or 1.0.1.
  190 +
  191 +Note that this release does not improve the rather crude build system
  192 +for Unix platforms. The general plan here is to autoconfiscate/
  193 +libtoolise 1.0.2 soon after release, and release the result as 1.1.0
  194 +or perhaps 1.2.0. That, however, is still just a plan at this point.
  195 +
  196 +Here are the changes in 1.0.2. Bug-reporters and/or patch-senders in
  197 +parentheses.
  198 +
  199 +* Fix an infinite segfault loop in 1.0.1 when a directory is
  200 + encountered in -f (force) mode.
  201 + (Trond Eivind Glomsrod, Nicholas Nethercote, Volker Schmidt)
  202 +
  203 +* Avoid double fclose() of output file on certain I/O error paths.
  204 + (Solar Designer)
  205 +
  206 +* Don't fail with internal error 1007 when fed a long stream (> 48MB)
  207 + of byte 251. Also print useful message suggesting that 1007s may be
  208 + caused by bad memory.
  209 + (noticed by Juan Pedro Vallejo, fixed by me)
  210 +
  211 +* Fix uninitialised variable silly bug in demo prog dlltest.c.
  212 + (Jorj Bauer)
  213 +
  214 +* Remove 512-MB limitation on recovered file size for bzip2recover
  215 + on selected platforms which support 64-bit ints. At the moment
  216 + all GCC supported platforms, and Win32.
  217 + (me, Alson van der Meulen)
  218 +
  219 +* Hard-code header byte values, to give correct operation on platforms
  220 + using EBCDIC as their native character set (IBM's OS/390).
  221 + (Leland Lucius)
  222 +
  223 +* Copy file access times correctly.
  224 + (Marty Leisner)
  225 +
  226 +* Add distclean and check targets to Makefile.
  227 + (Michael Carmack)
  228 +
  229 +* Parameterise use of ar and ranlib in Makefile. Also add $(LDFLAGS).
  230 + (Rich Ireland, Bo Thorsen)
  231 +
  232 +* Pass -p (create parent dirs as needed) to mkdir during make install.
  233 + (Jeremy Fusco)
  234 +
  235 +* Dereference symlinks when copying file permissions in -f mode.
  236 + (Volker Schmidt)
  237 +
  238 +* Majorly simplify implementation of uInt64_qrm10.
  239 + (Bo Lindbergh)
  240 +
  241 +* Check the input file still exists before deleting the output one,
  242 + when aborting in cleanUpAndFail().
  243 + (Joerg Prante, Robert Linden, Matthias Krings)
  244 +
  245 +Also a bunch of patches courtesy of Philippe Troin, the Debian maintainer
  246 +of bzip2:
  247 +
  248 +* Wrapper scripts (with manpages): bzdiff, bzgrep, bzmore.
  249 +
  250 +* Spelling changes and minor enhancements in bzip2.1.
  251 +
  252 +* Avoid race condition between creating the output file and setting its
  253 + interim permissions safely, by using fopen_output_safely().
  254 + No changes to bzip2recover since there is no issue with file
  255 + permissions there.
  256 +
  257 +* do not print senseless report with -v when compressing an empty
  258 + file.
  259 +
  260 +* bzcat -f works on non-bzip2 files.
  261 +
  262 +* do not try to escape shell meta-characters on unix (the shell takes
  263 + care of these).
  264 +
  265 +* added --fast and --best aliases for -1 -9 for gzip compatibility.
  266 +
  267 +
  268 +1.0.3 (15 Feb 05)
  269 +~~~~~~~~~~~~~~~~~
  270 +Fixes some minor bugs since the last version, 1.0.2.
  271 +
  272 +* Further robustification against corrupted compressed data.
  273 + There are currently no known bitstreams which can cause the
  274 + decompressor to crash, loop or access memory which does not
  275 + belong to it. If you are using bzip2 or the library to
  276 + decompress bitstreams from untrusted sources, an upgrade
  277 + to 1.0.3 is recommended. This fixes CAN-2005-1260.
  278 +
  279 +* The documentation has been converted to XML, from which html
  280 + and pdf can be derived.
  281 +
  282 +* Various minor bugs in the documentation have been fixed.
  283 +
  284 +* Fixes for various compilation warnings with newer versions of
  285 + gcc, and on 64-bit platforms.
  286 +
  287 +* The BZ_NO_STDIO cpp symbol was not properly observed in 1.0.2.
  288 + This has been fixed.
  289 +
  290 +
  291 +1.0.4 (20 Dec 06)
  292 +~~~~~~~~~~~~~~~~~
  293 +Fixes some minor bugs since the last version, 1.0.3.
  294 +
  295 +* Fix file permissions race problem (CAN-2005-0953).
  296 +
  297 +* Avoid possible segfault in BZ2_bzclose. From Coverity's NetBSD
  298 + scan.
  299 +
  300 +* 'const'/prototype cleanups in the C code.
  301 +
  302 +* Change default install location to /usr/local, and handle multiple
  303 + 'make install's without error.
  304 +
  305 +* Sanitise file names more carefully in bzgrep. Fixes CAN-2005-0758
  306 + to the extent that applies to bzgrep.
  307 +
  308 +* Use 'mktemp' rather than 'tempfile' in bzdiff.
  309 +
  310 +* Tighten up a couple of assertions in blocksort.c following automated
  311 + analysis.
  312 +
  313 +* Fix minor doc/comment bugs.
  314 +
  315 +
  316 +1.0.5 (10 Dec 07)
  317 +~~~~~~~~~~~~~~~~~
  318 +Security fix only. Fixes CERT-FI 20469 as it applies to bzip2.
  319 +
  320 +
  321 +1.0.6 (6 Sept 10)
  322 +~~~~~~~~~~~~~~~~~
  323 +
  324 +* Security fix for CVE-2010-0405. This was reported by Mikolaj
  325 + Izdebski.
  326 +
  327 +* Make the documentation build on Ubuntu 10.04
... ...
  1 +
  2 +--------------------------------------------------------------------------
  3 +
  4 +This program, "bzip2", the associated library "libbzip2", and all
  5 +documentation, are copyright (C) 1996-2010 Julian R Seward. All
  6 +rights reserved.
  7 +
  8 +Redistribution and use in source and binary forms, with or without
  9 +modification, are permitted provided that the following conditions
  10 +are met:
  11 +
  12 +1. Redistributions of source code must retain the above copyright
  13 + notice, this list of conditions and the following disclaimer.
  14 +
  15 +2. The origin of this software must not be misrepresented; you must
  16 + not claim that you wrote the original software. If you use this
  17 + software in a product, an acknowledgment in the product
  18 + documentation would be appreciated but is not required.
  19 +
  20 +3. Altered source versions must be plainly marked as such, and must
  21 + not be misrepresented as being the original software.
  22 +
  23 +4. The name of the author may not be used to endorse or promote
  24 + products derived from this software without specific prior written
  25 + permission.
  26 +
  27 +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  28 +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  29 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30 +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  31 +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  33 +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34 +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  35 +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  36 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  37 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38 +
  39 +Julian Seward, jseward@bzip.org
  40 +bzip2/libbzip2 version 1.0.6 of 6 September 2010
  41 +
  42 +--------------------------------------------------------------------------
... ...
  1 +
  2 +/*-------------------------------------------------------------*/
  3 +/*--- Block sorting machinery ---*/
  4 +/*--- blocksort.c ---*/
  5 +/*-------------------------------------------------------------*/
  6 +
  7 +/* ------------------------------------------------------------------
  8 + This file is part of bzip2/libbzip2, a program and library for
  9 + lossless, block-sorting data compression.
  10 +
  11 + bzip2/libbzip2 version 1.0.6 of 6 September 2010
  12 + Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
  13 +
  14 + Please read the WARNING, DISCLAIMER and PATENTS sections in the
  15 + README file.
  16 +
  17 + This program is released under the terms of the license contained
  18 + in the file LICENSE.
  19 + ------------------------------------------------------------------ */
  20 +
  21 +
  22 +#include "bzlib_private.h"
  23 +
  24 +/*---------------------------------------------*/
  25 +/*--- Fallback O(N log(N)^2) sorting ---*/
  26 +/*--- algorithm, for repetitive blocks ---*/
  27 +/*---------------------------------------------*/
  28 +
  29 +/*---------------------------------------------*/
  30 +static
  31 +__inline__
  32 +void fallbackSimpleSort ( UInt32* fmap,
  33 + UInt32* eclass,
  34 + Int32 lo,
  35 + Int32 hi )
  36 +{
  37 + Int32 i, j, tmp;
  38 + UInt32 ec_tmp;
  39 +
  40 + if (lo == hi) return;
  41 +
  42 + if (hi - lo > 3) {
  43 + for ( i = hi-4; i >= lo; i-- ) {
  44 + tmp = fmap[i];
  45 + ec_tmp = eclass[tmp];
  46 + for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
  47 + fmap[j-4] = fmap[j];
  48 + fmap[j-4] = tmp;
  49 + }
  50 + }
  51 +
  52 + for ( i = hi-1; i >= lo; i-- ) {
  53 + tmp = fmap[i];
  54 + ec_tmp = eclass[tmp];
  55 + for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
  56 + fmap[j-1] = fmap[j];
  57 + fmap[j-1] = tmp;
  58 + }
  59 +}
  60 +
  61 +
  62 +/*---------------------------------------------*/
  63 +#define fswap(zz1, zz2) \
  64 + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
  65 +
  66 +#define fvswap(zzp1, zzp2, zzn) \
  67 +{ \
  68 + Int32 yyp1 = (zzp1); \
  69 + Int32 yyp2 = (zzp2); \
  70 + Int32 yyn = (zzn); \
  71 + while (yyn > 0) { \
  72 + fswap(fmap[yyp1], fmap[yyp2]); \
  73 + yyp1++; yyp2++; yyn--; \
  74 + } \
  75 +}
  76 +
  77 +
  78 +#define fmin(a,b) ((a) < (b)) ? (a) : (b)
  79 +
  80 +#define fpush(lz,hz) { stackLo[sp] = lz; \
  81 + stackHi[sp] = hz; \
  82 + sp++; }
  83 +
  84 +#define fpop(lz,hz) { sp--; \
  85 + lz = stackLo[sp]; \
  86 + hz = stackHi[sp]; }
  87 +
  88 +#define FALLBACK_QSORT_SMALL_THRESH 10
  89 +#define FALLBACK_QSORT_STACK_SIZE 100
  90 +
  91 +
  92 +static
  93 +void fallbackQSort3 ( UInt32* fmap,
  94 + UInt32* eclass,
  95 + Int32 loSt,
  96 + Int32 hiSt )
  97 +{
  98 + Int32 unLo, unHi, ltLo, gtHi, n, m;
  99 + Int32 sp, lo, hi;
  100 + UInt32 med, r, r3;
  101 + Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
  102 + Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
  103 +
  104 + r = 0;
  105 +
  106 + sp = 0;
  107 + fpush ( loSt, hiSt );
  108 +
  109 + while (sp > 0) {
  110 +
  111 + AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 );
  112 +
  113 + fpop ( lo, hi );
  114 + if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
  115 + fallbackSimpleSort ( fmap, eclass, lo, hi );
  116 + continue;
  117 + }
  118 +
  119 + /* Random partitioning. Median of 3 sometimes fails to
  120 + avoid bad cases. Median of 9 seems to help but
  121 + looks rather expensive. This too seems to work but
  122 + is cheaper. Guidance for the magic constants
  123 + 7621 and 32768 is taken from Sedgewick's algorithms
  124 + book, chapter 35.
  125 + */
  126 + r = ((r * 7621) + 1) % 32768;
  127 + r3 = r % 3;
  128 + if (r3 == 0) med = eclass[fmap[lo]]; else
  129 + if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
  130 + med = eclass[fmap[hi]];
  131 +
  132 + unLo = ltLo = lo;
  133 + unHi = gtHi = hi;
  134 +
  135 + while (1) {
  136 + while (1) {
  137 + if (unLo > unHi) break;
  138 + n = (Int32)eclass[fmap[unLo]] - (Int32)med;
  139 + if (n == 0) {
  140 + fswap(fmap[unLo], fmap[ltLo]);
  141 + ltLo++; unLo++;
  142 + continue;
  143 + };
  144 + if (n > 0) break;
  145 + unLo++;
  146 + }
  147 + while (1) {
  148 + if (unLo > unHi) break;
  149 + n = (Int32)eclass[fmap[unHi]] - (Int32)med;
  150 + if (n == 0) {
  151 + fswap(fmap[unHi], fmap[gtHi]);
  152 + gtHi--; unHi--;
  153 + continue;
  154 + };
  155 + if (n < 0) break;
  156 + unHi--;
  157 + }
  158 + if (unLo > unHi) break;
  159 + fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
  160 + }
  161 +
  162 + AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
  163 +
  164 + if (gtHi < ltLo) continue;
  165 +
  166 + n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
  167 + m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
  168 +
  169 + n = lo + unLo - ltLo - 1;
  170 + m = hi - (gtHi - unHi) + 1;
  171 +
  172 + if (n - lo > hi - m) {
  173 + fpush ( lo, n );
  174 + fpush ( m, hi );
  175 + } else {
  176 + fpush ( m, hi );
  177 + fpush ( lo, n );
  178 + }
  179 + }
  180 +}
  181 +
  182 +#undef fmin
  183 +#undef fpush
  184 +#undef fpop
  185 +#undef fswap
  186 +#undef fvswap
  187 +#undef FALLBACK_QSORT_SMALL_THRESH
  188 +#undef FALLBACK_QSORT_STACK_SIZE
  189 +
  190 +
  191 +/*---------------------------------------------*/
  192 +/* Pre:
  193 + nblock > 0
  194 + eclass exists for [0 .. nblock-1]
  195 + ((UChar*)eclass) [0 .. nblock-1] holds block
  196 + ptr exists for [0 .. nblock-1]
  197 +
  198 + Post:
  199 + ((UChar*)eclass) [0 .. nblock-1] holds block
  200 + All other areas of eclass destroyed
  201 + fmap [0 .. nblock-1] holds sorted order
  202 + bhtab [ 0 .. 2+(nblock/32) ] destroyed
  203 +*/
  204 +
  205 +#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
  206 +#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
  207 +#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
  208 +#define WORD_BH(zz) bhtab[(zz) >> 5]
  209 +#define UNALIGNED_BH(zz) ((zz) & 0x01f)
  210 +
  211 +static
  212 +void fallbackSort ( UInt32* fmap,
  213 + UInt32* eclass,
  214 + UInt32* bhtab,
  215 + Int32 nblock,
  216 + Int32 verb )
  217 +{
  218 + Int32 ftab[257];
  219 + Int32 ftabCopy[256];
  220 + Int32 H, i, j, k, l, r, cc, cc1;
  221 + Int32 nNotDone;
  222 + Int32 nBhtab;
  223 + UChar* eclass8 = (UChar*)eclass;
  224 +
  225 + /*--
  226 + Initial 1-char radix sort to generate
  227 + initial fmap and initial BH bits.
  228 + --*/
  229 + if (verb >= 4)
  230 + VPrintf0 ( " bucket sorting ...\n" );
  231 + for (i = 0; i < 257; i++) ftab[i] = 0;
  232 + for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
  233 + for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i];
  234 + for (i = 1; i < 257; i++) ftab[i] += ftab[i-1];
  235 +
  236 + for (i = 0; i < nblock; i++) {
  237 + j = eclass8[i];
  238 + k = ftab[j] - 1;
  239 + ftab[j] = k;
  240 + fmap[k] = i;
  241 + }
  242 +
  243 + nBhtab = 2 + (nblock / 32);
  244 + for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
  245 + for (i = 0; i < 256; i++) SET_BH(ftab[i]);
  246 +
  247 + /*--
  248 + Inductively refine the buckets. Kind-of an
  249 + "exponential radix sort" (!), inspired by the
  250 + Manber-Myers suffix array construction algorithm.
  251 + --*/
  252 +
  253 + /*-- set sentinel bits for block-end detection --*/
  254 + for (i = 0; i < 32; i++) {
  255 + SET_BH(nblock + 2*i);
  256 + CLEAR_BH(nblock + 2*i + 1);
  257 + }
  258 +
  259 + /*-- the log(N) loop --*/
  260 + H = 1;
  261 + while (1) {
  262 +
  263 + if (verb >= 4)
  264 + VPrintf1 ( " depth %6d has ", H );
  265 +
  266 + j = 0;
  267 + for (i = 0; i < nblock; i++) {
  268 + if (ISSET_BH(i)) j = i;
  269 + k = fmap[i] - H; if (k < 0) k += nblock;
  270 + eclass[k] = j;
  271 + }
  272 +
  273 + nNotDone = 0;
  274 + r = -1;
  275 + while (1) {
  276 +
  277 + /*-- find the next non-singleton bucket --*/
  278 + k = r + 1;
  279 + while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
  280 + if (ISSET_BH(k)) {
  281 + while (WORD_BH(k) == 0xffffffff) k += 32;
  282 + while (ISSET_BH(k)) k++;
  283 + }
  284 + l = k - 1;
  285 + if (l >= nblock) break;
  286 + while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
  287 + if (!ISSET_BH(k)) {
  288 + while (WORD_BH(k) == 0x00000000) k += 32;
  289 + while (!ISSET_BH(k)) k++;
  290 + }
  291 + r = k - 1;
  292 + if (r >= nblock) break;
  293 +
  294 + /*-- now [l, r] bracket current bucket --*/
  295 + if (r > l) {
  296 + nNotDone += (r - l + 1);
  297 + fallbackQSort3 ( fmap, eclass, l, r );
  298 +
  299 + /*-- scan bucket and generate header bits-- */
  300 + cc = -1;
  301 + for (i = l; i <= r; i++) {
  302 + cc1 = eclass[fmap[i]];
  303 + if (cc != cc1) { SET_BH(i); cc = cc1; };
  304 + }
  305 + }
  306 + }
  307 +
  308 + if (verb >= 4)
  309 + VPrintf1 ( "%6d unresolved strings\n", nNotDone );
  310 +
  311 + H *= 2;
  312 + if (H > nblock || nNotDone == 0) break;
  313 + }
  314 +
  315 + /*--
  316 + Reconstruct the original block in
  317 + eclass8 [0 .. nblock-1], since the
  318 + previous phase destroyed it.
  319 + --*/
  320 + if (verb >= 4)
  321 + VPrintf0 ( " reconstructing block ...\n" );
  322 + j = 0;
  323 + for (i = 0; i < nblock; i++) {
  324 + while (ftabCopy[j] == 0) j++;
  325 + ftabCopy[j]--;
  326 + eclass8[fmap[i]] = (UChar)j;
  327 + }
  328 + AssertH ( j < 256, 1005 );
  329 +}
  330 +
  331 +#undef SET_BH
  332 +#undef CLEAR_BH
  333 +#undef ISSET_BH
  334 +#undef WORD_BH
  335 +#undef UNALIGNED_BH
  336 +
  337 +
  338 +/*---------------------------------------------*/
  339 +/*--- The main, O(N^2 log(N)) sorting ---*/
  340 +/*--- algorithm. Faster for "normal" ---*/
  341 +/*--- non-repetitive blocks. ---*/
  342 +/*---------------------------------------------*/
  343 +
  344 +/*---------------------------------------------*/
  345 +static
  346 +__inline__
  347 +Bool mainGtU ( UInt32 i1,
  348 + UInt32 i2,
  349 + UChar* block,
  350 + UInt16* quadrant,
  351 + UInt32 nblock,
  352 + Int32* budget )
  353 +{
  354 + Int32 k;
  355 + UChar c1, c2;
  356 + UInt16 s1, s2;
  357 +
  358 + AssertD ( i1 != i2, "mainGtU" );
  359 + /* 1 */
  360 + c1 = block[i1]; c2 = block[i2];
  361 + if (c1 != c2) return (c1 > c2);
  362 + i1++; i2++;
  363 + /* 2 */
  364 + c1 = block[i1]; c2 = block[i2];
  365 + if (c1 != c2) return (c1 > c2);
  366 + i1++; i2++;
  367 + /* 3 */
  368 + c1 = block[i1]; c2 = block[i2];
  369 + if (c1 != c2) return (c1 > c2);
  370 + i1++; i2++;
  371 + /* 4 */
  372 + c1 = block[i1]; c2 = block[i2];
  373 + if (c1 != c2) return (c1 > c2);
  374 + i1++; i2++;
  375 + /* 5 */
  376 + c1 = block[i1]; c2 = block[i2];
  377 + if (c1 != c2) return (c1 > c2);
  378 + i1++; i2++;
  379 + /* 6 */
  380 + c1 = block[i1]; c2 = block[i2];
  381 + if (c1 != c2) return (c1 > c2);
  382 + i1++; i2++;
  383 + /* 7 */
  384 + c1 = block[i1]; c2 = block[i2];
  385 + if (c1 != c2) return (c1 > c2);
  386 + i1++; i2++;
  387 + /* 8 */
  388 + c1 = block[i1]; c2 = block[i2];
  389 + if (c1 != c2) return (c1 > c2);
  390 + i1++; i2++;
  391 + /* 9 */
  392 + c1 = block[i1]; c2 = block[i2];
  393 + if (c1 != c2) return (c1 > c2);
  394 + i1++; i2++;
  395 + /* 10 */
  396 + c1 = block[i1]; c2 = block[i2];
  397 + if (c1 != c2) return (c1 > c2);
  398 + i1++; i2++;
  399 + /* 11 */
  400 + c1 = block[i1]; c2 = block[i2];
  401 + if (c1 != c2) return (c1 > c2);
  402 + i1++; i2++;
  403 + /* 12 */
  404 + c1 = block[i1]; c2 = block[i2];
  405 + if (c1 != c2) return (c1 > c2);
  406 + i1++; i2++;
  407 +
  408 + k = nblock + 8;
  409 +
  410 + do {
  411 + /* 1 */
  412 + c1 = block[i1]; c2 = block[i2];
  413 + if (c1 != c2) return (c1 > c2);
  414 + s1 = quadrant[i1]; s2 = quadrant[i2];
  415 + if (s1 != s2) return (s1 > s2);
  416 + i1++; i2++;
  417 + /* 2 */
  418 + c1 = block[i1]; c2 = block[i2];
  419 + if (c1 != c2) return (c1 > c2);
  420 + s1 = quadrant[i1]; s2 = quadrant[i2];
  421 + if (s1 != s2) return (s1 > s2);
  422 + i1++; i2++;
  423 + /* 3 */
  424 + c1 = block[i1]; c2 = block[i2];
  425 + if (c1 != c2) return (c1 > c2);
  426 + s1 = quadrant[i1]; s2 = quadrant[i2];
  427 + if (s1 != s2) return (s1 > s2);
  428 + i1++; i2++;
  429 + /* 4 */
  430 + c1 = block[i1]; c2 = block[i2];
  431 + if (c1 != c2) return (c1 > c2);
  432 + s1 = quadrant[i1]; s2 = quadrant[i2];
  433 + if (s1 != s2) return (s1 > s2);
  434 + i1++; i2++;
  435 + /* 5 */
  436 + c1 = block[i1]; c2 = block[i2];
  437 + if (c1 != c2) return (c1 > c2);
  438 + s1 = quadrant[i1]; s2 = quadrant[i2];
  439 + if (s1 != s2) return (s1 > s2);
  440 + i1++; i2++;
  441 + /* 6 */
  442 + c1 = block[i1]; c2 = block[i2];
  443 + if (c1 != c2) return (c1 > c2);
  444 + s1 = quadrant[i1]; s2 = quadrant[i2];
  445 + if (s1 != s2) return (s1 > s2);
  446 + i1++; i2++;
  447 + /* 7 */
  448 + c1 = block[i1]; c2 = block[i2];
  449 + if (c1 != c2) return (c1 > c2);
  450 + s1 = quadrant[i1]; s2 = quadrant[i2];
  451 + if (s1 != s2) return (s1 > s2);
  452 + i1++; i2++;
  453 + /* 8 */
  454 + c1 = block[i1]; c2 = block[i2];
  455 + if (c1 != c2) return (c1 > c2);
  456 + s1 = quadrant[i1]; s2 = quadrant[i2];
  457 + if (s1 != s2) return (s1 > s2);
  458 + i1++; i2++;
  459 +
  460 + if (i1 >= nblock) i1 -= nblock;
  461 + if (i2 >= nblock) i2 -= nblock;
  462 +
  463 + k -= 8;
  464 + (*budget)--;
  465 + }
  466 + while (k >= 0);
  467 +
  468 + return False;
  469 +}
  470 +
  471 +
  472 +/*---------------------------------------------*/
  473 +/*--
  474 + Knuth's increments seem to work better
  475 + than Incerpi-Sedgewick here. Possibly
  476 + because the number of elems to sort is
  477 + usually small, typically <= 20.
  478 +--*/
  479 +static
  480 +Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
  481 + 9841, 29524, 88573, 265720,
  482 + 797161, 2391484 };
  483 +
  484 +static
  485 +void mainSimpleSort ( UInt32* ptr,
  486 + UChar* block,
  487 + UInt16* quadrant,
  488 + Int32 nblock,
  489 + Int32 lo,
  490 + Int32 hi,
  491 + Int32 d,
  492 + Int32* budget )
  493 +{
  494 + Int32 i, j, h, bigN, hp;
  495 + UInt32 v;
  496 +
  497 + bigN = hi - lo + 1;
  498 + if (bigN < 2) return;
  499 +
  500 + hp = 0;
  501 + while (incs[hp] < bigN) hp++;
  502 + hp--;
  503 +
  504 + for (; hp >= 0; hp--) {
  505 + h = incs[hp];
  506 +
  507 + i = lo + h;
  508 + while (True) {
  509 +
  510 + /*-- copy 1 --*/
  511 + if (i > hi) break;
  512 + v = ptr[i];
  513 + j = i;
  514 + while ( mainGtU (
  515 + ptr[j-h]+d, v+d, block, quadrant, nblock, budget
  516 + ) ) {
  517 + ptr[j] = ptr[j-h];
  518 + j = j - h;
  519 + if (j <= (lo + h - 1)) break;
  520 + }
  521 + ptr[j] = v;
  522 + i++;
  523 +
  524 + /*-- copy 2 --*/
  525 + if (i > hi) break;
  526 + v = ptr[i];
  527 + j = i;
  528 + while ( mainGtU (
  529 + ptr[j-h]+d, v+d, block, quadrant, nblock, budget
  530 + ) ) {
  531 + ptr[j] = ptr[j-h];
  532 + j = j - h;
  533 + if (j <= (lo + h - 1)) break;
  534 + }
  535 + ptr[j] = v;
  536 + i++;
  537 +
  538 + /*-- copy 3 --*/
  539 + if (i > hi) break;
  540 + v = ptr[i];
  541 + j = i;
  542 + while ( mainGtU (
  543 + ptr[j-h]+d, v+d, block, quadrant, nblock, budget
  544 + ) ) {
  545 + ptr[j] = ptr[j-h];
  546 + j = j - h;
  547 + if (j <= (lo + h - 1)) break;
  548 + }
  549 + ptr[j] = v;
  550 + i++;
  551 +
  552 + if (*budget < 0) return;
  553 + }
  554 + }
  555 +}
  556 +
  557 +
  558 +/*---------------------------------------------*/
  559 +/*--
  560 + The following is an implementation of
  561 + an elegant 3-way quicksort for strings,
  562 + described in a paper "Fast Algorithms for
  563 + Sorting and Searching Strings", by Robert
  564 + Sedgewick and Jon L. Bentley.
  565 +--*/
  566 +
  567 +#define mswap(zz1, zz2) \
  568 + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
  569 +
  570 +#define mvswap(zzp1, zzp2, zzn) \
  571 +{ \
  572 + Int32 yyp1 = (zzp1); \
  573 + Int32 yyp2 = (zzp2); \
  574 + Int32 yyn = (zzn); \
  575 + while (yyn > 0) { \
  576 + mswap(ptr[yyp1], ptr[yyp2]); \
  577 + yyp1++; yyp2++; yyn--; \
  578 + } \
  579 +}
  580 +
  581 +static
  582 +__inline__
  583 +UChar mmed3 ( UChar a, UChar b, UChar c )
  584 +{
  585 + UChar t;
  586 + if (a > b) { t = a; a = b; b = t; };
  587 + if (b > c) {
  588 + b = c;
  589 + if (a > b) b = a;
  590 + }
  591 + return b;
  592 +}
  593 +
  594 +#define mmin(a,b) ((a) < (b)) ? (a) : (b)
  595 +
  596 +#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
  597 + stackHi[sp] = hz; \
  598 + stackD [sp] = dz; \
  599 + sp++; }
  600 +
  601 +#define mpop(lz,hz,dz) { sp--; \
  602 + lz = stackLo[sp]; \
  603 + hz = stackHi[sp]; \
  604 + dz = stackD [sp]; }
  605 +
  606 +
  607 +#define mnextsize(az) (nextHi[az]-nextLo[az])
  608 +
  609 +#define mnextswap(az,bz) \
  610 + { Int32 tz; \
  611 + tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
  612 + tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
  613 + tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
  614 +
  615 +
  616 +#define MAIN_QSORT_SMALL_THRESH 20
  617 +#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
  618 +#define MAIN_QSORT_STACK_SIZE 100
  619 +
  620 +static
  621 +void mainQSort3 ( UInt32* ptr,
  622 + UChar* block,
  623 + UInt16* quadrant,
  624 + Int32 nblock,
  625 + Int32 loSt,
  626 + Int32 hiSt,
  627 + Int32 dSt,
  628 + Int32* budget )
  629 +{
  630 + Int32 unLo, unHi, ltLo, gtHi, n, m, med;
  631 + Int32 sp, lo, hi, d;
  632 +
  633 + Int32 stackLo[MAIN_QSORT_STACK_SIZE];
  634 + Int32 stackHi[MAIN_QSORT_STACK_SIZE];
  635 + Int32 stackD [MAIN_QSORT_STACK_SIZE];
  636 +
  637 + Int32 nextLo[3];
  638 + Int32 nextHi[3];
  639 + Int32 nextD [3];
  640 +
  641 + sp = 0;
  642 + mpush ( loSt, hiSt, dSt );
  643 +
  644 + while (sp > 0) {
  645 +
  646 + AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 );
  647 +
  648 + mpop ( lo, hi, d );
  649 + if (hi - lo < MAIN_QSORT_SMALL_THRESH ||
  650 + d > MAIN_QSORT_DEPTH_THRESH) {
  651 + mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
  652 + if (*budget < 0) return;
  653 + continue;
  654 + }
  655 +
  656 + med = (Int32)
  657 + mmed3 ( block[ptr[ lo ]+d],
  658 + block[ptr[ hi ]+d],
  659 + block[ptr[ (lo+hi)>>1 ]+d] );
  660 +
  661 + unLo = ltLo = lo;
  662 + unHi = gtHi = hi;
  663 +
  664 + while (True) {
  665 + while (True) {
  666 + if (unLo > unHi) break;
  667 + n = ((Int32)block[ptr[unLo]+d]) - med;
  668 + if (n == 0) {
  669 + mswap(ptr[unLo], ptr[ltLo]);
  670 + ltLo++; unLo++; continue;
  671 + };
  672 + if (n > 0) break;
  673 + unLo++;
  674 + }
  675 + while (True) {
  676 + if (unLo > unHi) break;
  677 + n = ((Int32)block[ptr[unHi]+d]) - med;
  678 + if (n == 0) {
  679 + mswap(ptr[unHi], ptr[gtHi]);
  680 + gtHi--; unHi--; continue;
  681 + };
  682 + if (n < 0) break;
  683 + unHi--;
  684 + }
  685 + if (unLo > unHi) break;
  686 + mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
  687 + }
  688 +
  689 + AssertD ( unHi == unLo-1, "mainQSort3(2)" );
  690 +
  691 + if (gtHi < ltLo) {
  692 + mpush(lo, hi, d+1 );
  693 + continue;
  694 + }
  695 +
  696 + n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
  697 + m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
  698 +
  699 + n = lo + unLo - ltLo - 1;
  700 + m = hi - (gtHi - unHi) + 1;
  701 +
  702 + nextLo[0] = lo; nextHi[0] = n; nextD[0] = d;
  703 + nextLo[1] = m; nextHi[1] = hi; nextD[1] = d;
  704 + nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
  705 +
  706 + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
  707 + if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
  708 + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
  709 +
  710 + AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
  711 + AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
  712 +
  713 + mpush (nextLo[0], nextHi[0], nextD[0]);
  714 + mpush (nextLo[1], nextHi[1], nextD[1]);
  715 + mpush (nextLo[2], nextHi[2], nextD[2]);
  716 + }
  717 +}
  718 +
  719 +#undef mswap
  720 +#undef mvswap
  721 +#undef mpush
  722 +#undef mpop
  723 +#undef mmin
  724 +#undef mnextsize
  725 +#undef mnextswap
  726 +#undef MAIN_QSORT_SMALL_THRESH
  727 +#undef MAIN_QSORT_DEPTH_THRESH
  728 +#undef MAIN_QSORT_STACK_SIZE
  729 +
  730 +
  731 +/*---------------------------------------------*/
  732 +/* Pre:
  733 + nblock > N_OVERSHOOT
  734 + block32 exists for [0 .. nblock-1 +N_OVERSHOOT]
  735 + ((UChar*)block32) [0 .. nblock-1] holds block