]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Remove the exp-sgcheck tool.
authorJulian Seward <jseward@acm.org>
Fri, 17 Apr 2020 17:23:26 +0000 (19:23 +0200)
committerJulian Seward <jseward@acm.org>
Fri, 17 Apr 2020 17:25:32 +0000 (19:25 +0200)
It only ever worked on x86 and amd64, and even on those it had a high false
positive rate and was slow.  Everything it does, ASan can do faster, better,
and on more architectures.  So there's no reason to keep this tool any more.

52 files changed:
Makefile.am
configure.ac
docs/xml/FAQ.xml
docs/xml/manual-core.xml
docs/xml/manual.xml
docs/xml/valgrind-manpage.xml
exp-sgcheck.supp [deleted file]
exp-sgcheck/Makefile.am [deleted file]
exp-sgcheck/docs/sg-manual.xml [deleted file]
exp-sgcheck/h_intercepts.c [deleted file]
exp-sgcheck/h_main.c [deleted file]
exp-sgcheck/h_main.h [deleted file]
exp-sgcheck/pc_common.c [deleted file]
exp-sgcheck/pc_common.h [deleted file]
exp-sgcheck/pc_main.c [deleted file]
exp-sgcheck/sg_main.c [deleted file]
exp-sgcheck/sg_main.h [deleted file]
exp-sgcheck/tests/Makefile.am [deleted file]
exp-sgcheck/tests/bad_percentify.c [deleted file]
exp-sgcheck/tests/bad_percentify.stderr.exp-glibc28-amd64 [deleted file]
exp-sgcheck/tests/bad_percentify.stdout.exp [deleted file]
exp-sgcheck/tests/bad_percentify.vgtest [deleted file]
exp-sgcheck/tests/filter_add [deleted file]
exp-sgcheck/tests/filter_stderr [deleted file]
exp-sgcheck/tests/filter_suppgen [deleted file]
exp-sgcheck/tests/globalerr.c [deleted file]
exp-sgcheck/tests/globalerr.stderr.exp-gcc491-amd64 [deleted file]
exp-sgcheck/tests/globalerr.stderr.exp-glibc28-amd64 [deleted file]
exp-sgcheck/tests/globalerr.stdout.exp [deleted file]
exp-sgcheck/tests/globalerr.vgtest [deleted file]
exp-sgcheck/tests/hackedbz2.c [deleted file]
exp-sgcheck/tests/hackedbz2.stderr.exp-glibc28-amd64 [deleted file]
exp-sgcheck/tests/hackedbz2.stdout.exp [deleted file]
exp-sgcheck/tests/hackedbz2.vgtest [deleted file]
exp-sgcheck/tests/hsg.c [deleted file]
exp-sgcheck/tests/hsg.stderr.exp [deleted file]
exp-sgcheck/tests/hsg.stdout.exp [deleted file]
exp-sgcheck/tests/hsg.vgtest [deleted file]
exp-sgcheck/tests/is_arch_supported [deleted file]
exp-sgcheck/tests/preen_invars.c [deleted file]
exp-sgcheck/tests/preen_invars.stderr.exp-glibc28-amd64 [deleted file]
exp-sgcheck/tests/preen_invars.stdout.exp [deleted file]
exp-sgcheck/tests/preen_invars.vgtest [deleted file]
exp-sgcheck/tests/preen_invars_so.c [deleted file]
exp-sgcheck/tests/stackerr.c [deleted file]
exp-sgcheck/tests/stackerr.stderr.exp-glibc27-x86 [deleted file]
exp-sgcheck/tests/stackerr.stderr.exp-glibc28-amd64 [deleted file]
exp-sgcheck/tests/stackerr.stdout.exp [deleted file]
exp-sgcheck/tests/stackerr.vgtest [deleted file]
helgrind/tests/annotate_hbefore.c
solaris/valgrind.p5m
tests/check_headers_and_includes

index 242b38a142a6bc8b8bce21416d436648ede4daf1..08db83401987180884c9efc60026b70c62597db9 100644 (file)
@@ -15,7 +15,6 @@ TOOLS = \
                none
 
 EXP_TOOLS = \
-               exp-sgcheck \
                exp-bbv
 
 # Put docs last because building the HTML is slow and we want to get
@@ -45,7 +44,6 @@ SUPP_FILES = \
        glibc-2.34567-NPTL-helgrind.supp \
        glibc-2.2-LinuxThreads-helgrind.supp \
        glibc-2.X-drd.supp \
-       exp-sgcheck.supp \
        darwin9.supp darwin9-drd.supp \
        darwin10.supp darwin10-drd.supp \
        darwin11.supp darwin12.supp darwin13.supp darwin14.supp darwin15.supp \
index 3336329e9c2f365d34c722becbb128674146a79d..9e6ed71387fc8e2a584ec84a547c6f7e2ced5f41 100755 (executable)
@@ -1166,9 +1166,6 @@ if test "$VGCONF_OS" != "solaris"; then
     # add the suppressions antidisirregardless.
     DEFAULT_SUPP="xfree-4.supp ${DEFAULT_SUPP}"
     DEFAULT_SUPP="xfree-3.supp ${DEFAULT_SUPP}"
-
-    # Add glibc and X11 suppressions for exp-sgcheck
-    DEFAULT_SUPP="exp-sgcheck.supp ${DEFAULT_SUPP}"
 fi
 
 
@@ -4853,8 +4850,6 @@ AC_CONFIG_FILES([
    none/tests/x86-darwin/Makefile
    none/tests/amd64-solaris/Makefile
    none/tests/x86-solaris/Makefile
-   exp-sgcheck/Makefile
-   exp-sgcheck/tests/Makefile
    exp-bbv/Makefile
    exp-bbv/tests/Makefile
    exp-bbv/tests/x86/Makefile
index d0d917edceaff15a2a7e5d3dbea795e9d42d799e..b1246062823c3d023b22963cdfe139c5f20a24e0 100644 (file)
@@ -483,10 +483,6 @@ int main(void)
     <para>Unfortunately, Memcheck doesn't do bounds checking on global
     or stack arrays.  We'd like to, but it's just not possible to do in
     a reasonable way that fits with how Memcheck works.  Sorry.</para>
-    
-    <para>However, the experimental tool SGcheck can detect errors like
-    this.  Run Valgrind with the <option>--tool=exp-sgcheck</option> option
-    to try it, but be aware that it is not as robust as Memcheck.</para>
   </answer>
 </qandaentry>
 
index 8d24616a0ed91d51a6bd931b1c32d0d6f2c9961c..72730ec7bbfe57671db60cfb6ec1013ce4f86a9b 100644 (file)
@@ -613,7 +613,7 @@ in most cases.  We group the available options by rough categories.</para>
     <listitem>
       <para>Run the Valgrind tool called <varname>toolname</varname>,
       e.g. memcheck, cachegrind, callgrind, helgrind, drd, massif,
-      dhat, lackey, none, exp-sgcheck, exp-bbv, etc.</para>
+      dhat, lackey, none, exp-bbv, etc.</para>
     </listitem>
   </varlistentry>
 
@@ -2562,7 +2562,7 @@ need to use them.</para>
       malloc related functions, using the
       synonym <varname>somalloc</varname>.  This synonym is usable for
       all tools doing standard replacement of malloc related functions
-      (e.g. memcheck, helgrind, drd, massif, dhat, exp-sgcheck).
+      (e.g. memcheck, helgrind, drd, massif, dhat).
       </para>
 
       <itemizedlist>
index b90514935a85ca77b58903babbfe3ff9135d40a5..da37102d009c6bf0cd8351340b33b4bd35e390f2 100644 (file)
@@ -42,8 +42,6 @@
       xmlns:xi="http://www.w3.org/2001/XInclude" />
   <xi:include href="../../none/docs/nl-manual.xml" parse="xml"  
       xmlns:xi="http://www.w3.org/2001/XInclude" />
-  <xi:include href="../../exp-sgcheck/docs/sg-manual.xml" parse="xml"  
-      xmlns:xi="http://www.w3.org/2001/XInclude" />
   <xi:include href="../../exp-bbv/docs/bbv-manual.xml" parse="xml"  
       xmlns:xi="http://www.w3.org/2001/XInclude" />      
 
index 7498c614c45c826ca91dd30facbd1e478fb9e88a..332ca4884c6b0091d1e5d99aa7fce1afcf46530e 100644 (file)
@@ -202,15 +202,6 @@ system: <filename>&vg-docs-path;</filename>, or online:
 
 
 
-<refsect1 id="sgcheck-options">
-<title>SGcheck Options</title>
-
-<xi:include href="../../exp-sgcheck/docs/sg-manual.xml" 
-            xpointer="sg.opts.list"
-            xmlns:xi="http://www.w3.org/2001/XInclude" />
-
-</refsect1>
-
 <refsect1 id="bbv-options">
 <title>BBV Options</title>
 
diff --git a/exp-sgcheck.supp b/exp-sgcheck.supp
deleted file mode 100644 (file)
index b2d4aeb..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-   ld-2.X possibly applying relocations
-   exp-sgcheck:SorG
-   obj:*/*lib*/ld-2.*so*
-   obj:*/*lib*/ld-2.*so*
-}
-
-# I'm pretty sure this is a false positive caused by the sg_ stuff
-{
-   glibc realpath false positive
-   exp-sgcheck:SorG
-   fun:realpath
-   fun:*
-}
-
-{
-   I think this is glibc's ultra optimised getenv doing 2 byte reads
-   exp-sgcheck:SorG
-   fun:getenv
-}
diff --git a/exp-sgcheck/Makefile.am b/exp-sgcheck/Makefile.am
deleted file mode 100644 (file)
index 8927ff6..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-include $(top_srcdir)/Makefile.tool.am
-
-EXTRA_DIST = docs/sg-manual.xml
-
-#----------------------------------------------------------------------------
-# Headers, etc
-#----------------------------------------------------------------------------
-
-noinst_HEADERS = \
-       h_main.h \
-       pc_common.h \
-       sg_main.h
-
-#----------------------------------------------------------------------------
-# exp-sgcheck-<platform>
-#----------------------------------------------------------------------------
-
-noinst_PROGRAMS  = exp-sgcheck-@VGCONF_ARCH_PRI@-@VGCONF_OS@
-if VGCONF_HAVE_PLATFORM_SEC
-noinst_PROGRAMS += exp-sgcheck-@VGCONF_ARCH_SEC@-@VGCONF_OS@
-endif
-
-EXP_PTRCHECK_SOURCES_COMMON = \
-       h_main.c \
-       pc_common.c \
-       pc_main.c \
-       sg_main.c
-
-exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES      = \
-       $(EXP_PTRCHECK_SOURCES_COMMON)
-exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS     = \
-       $(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
-exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS       = $(LTO_CFLAGS) \
-       $(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
-exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_DEPENDENCIES = \
-       $(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_PRI_CAPS@)
-exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDADD        = \
-       $(TOOL_LDADD_@VGCONF_PLATFORM_PRI_CAPS@)
-exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS      = \
-       $(TOOL_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
-exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LINK = \
-       $(top_builddir)/coregrind/link_tool_exe_@VGCONF_OS@ \
-       @VALT_LOAD_ADDRESS_PRI@ \
-       $(LINK) \
-       $(exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) \
-       $(exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS)
-
-if VGCONF_HAVE_PLATFORM_SEC
-exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_SOURCES      = \
-       $(EXP_PTRCHECK_SOURCES_COMMON)
-exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS     = \
-       $(AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
-exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS       = $(LTO_CFLAGS) \
-       $(AM_CFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
-exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_DEPENDENCIES = \
-       $(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_SEC_CAPS@)
-exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDADD        = \
-       $(TOOL_LDADD_@VGCONF_PLATFORM_SEC_CAPS@)
-exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDFLAGS      = \
-       $(TOOL_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
-exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LINK = \
-       $(top_builddir)/coregrind/link_tool_exe_@VGCONF_OS@ \
-       @VALT_LOAD_ADDRESS_SEC@ \
-       $(LINK) \
-       $(exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) \
-       $(exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDFLAGS)
-endif
-
-#----------------------------------------------------------------------------
-# vgpreload_exp-sgcheck-<platform>.so
-#----------------------------------------------------------------------------
-
-noinst_PROGRAMS += vgpreload_exp-sgcheck-@VGCONF_ARCH_PRI@-@VGCONF_OS@.so
-if VGCONF_HAVE_PLATFORM_SEC
-noinst_PROGRAMS += vgpreload_exp-sgcheck-@VGCONF_ARCH_SEC@-@VGCONF_OS@.so
-endif
-
-if VGCONF_OS_IS_DARWIN
-noinst_DSYMS = $(noinst_PROGRAMS)
-endif
-
-VGPRELOAD_EXP_PTRCHECK_SOURCES_COMMON = h_intercepts.c
-
-vgpreload_exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_SOURCES      = \
-       $(VGPRELOAD_EXP_PTRCHECK_SOURCES_COMMON)
-vgpreload_exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS     = \
-       $(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
-vgpreload_exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS       = \
-       $(AM_CFLAGS_PSO_@VGCONF_PLATFORM_PRI_CAPS@) -O2
-vgpreload_exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_DEPENDENCIES = \
-       $(LIBREPLACEMALLOC_@VGCONF_PLATFORM_PRI_CAPS@)
-vgpreload_exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_LDFLAGS      = \
-       $(PRELOAD_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) \
-       $(LIBREPLACEMALLOC_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
-
-if VGCONF_HAVE_PLATFORM_SEC
-vgpreload_exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_SOURCES      = \
-       $(VGPRELOAD_EXP_PTRCHECK_SOURCES_COMMON)
-vgpreload_exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS     = \
-       $(AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
-vgpreload_exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS       = \
-       $(AM_CFLAGS_PSO_@VGCONF_PLATFORM_SEC_CAPS@) -O2
-vgpreload_exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_DEPENDENCIES = \
-       $(LIBREPLACEMALLOC_@VGCONF_PLATFORM_SEC_CAPS@)
-vgpreload_exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_LDFLAGS      = \
-       $(PRELOAD_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) \
-       $(LIBREPLACEMALLOC_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
-endif
-
diff --git a/exp-sgcheck/docs/sg-manual.xml b/exp-sgcheck/docs/sg-manual.xml
deleted file mode 100644 (file)
index c03e778..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-<?xml version="1.0"?> <!-- -*- sgml -*- -->
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-          "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-[ <!ENTITY % vg-entities SYSTEM "../../docs/xml/vg-entities.xml"> %vg-entities; ]>
-
-
-<chapter id="sg-manual" 
-         xreflabel="SGCheck: an experimental stack and global array overrun detector">
-  <title>SGCheck: an experimental stack and global array overrun detector</title>
-
-<para>To use this tool, you must specify
-<option>--tool=exp-sgcheck</option> on the Valgrind
-command line.</para>
-
-
-
-
-<sect1 id="sg-manual.overview" xreflabel="Overview">
-<title>Overview</title>
-
-<para>SGCheck is a tool for finding overruns of stack and global
-arrays.  It works by using a heuristic approach derived from an
-observation about the likely forms of stack and global array accesses.
-</para>
-
-</sect1>
-
-
-
-
-<sect1 id="sg-manual.options" xreflabel="SGCheck Command-line Options">
-<title>SGCheck Command-line Options</title>
-
-<para id="sg.opts.list">There are no SGCheck-specific command-line options at present.</para>
-<!--
-<para>SGCheck-specific command-line options are:</para>
-
-
-<variablelist id="sg.opts.list">
-</variablelist>
--->
-
-</sect1>
-
-
-
-<sect1 id="sg-manual.how-works.sg-checks"
-       xreflabel="How SGCheck Works">
-<title>How SGCheck Works</title>
-
-<para>When a source file is compiled
-with <option>-g</option>, the compiler attaches DWARF3
-debugging information which describes the location of all stack and
-global arrays in the file.</para>
-
-<para>Checking of accesses to such arrays would then be relatively
-simple, if the compiler could also tell us which array (if any) each
-memory referencing instruction was supposed to access.  Unfortunately
-the DWARF3 debugging format does not provide a way to represent such
-information, so we have to resort to a heuristic technique to
-approximate it.  The key observation is that
-   <emphasis>
-   if a memory referencing instruction accesses inside a stack or
-   global array once, then it is highly likely to always access that
-   same array</emphasis>.</para>
-
-<para>To see how this might be useful, consider the following buggy
-fragment:</para>
-<programlisting><![CDATA[
-   { int i, a[10];  // both are auto vars
-     for (i = 0; i <= 10; i++)
-        a[i] = 42;
-   }
-]]></programlisting>
-
-<para>At run time we will know the precise address
-of <computeroutput>a[]</computeroutput> on the stack, and so we can
-observe that the first store resulting from <computeroutput>a[i] =
-42</computeroutput> writes <computeroutput>a[]</computeroutput>, and
-we will (correctly) assume that that instruction is intended always to
-access <computeroutput>a[]</computeroutput>.  Then, on the 11th
-iteration, it accesses somewhere else, possibly a different local,
-possibly an un-accounted for area of the stack (eg, spill slot), so
-SGCheck reports an error.</para>
-
-<para>There is an important caveat.</para>
-
-<para>Imagine a function such as <function>memcpy</function>, which is used
-to read and write many different areas of memory over the lifetime of the
-program.  If we insist that the read and write instructions in its memory
-copying loop only ever access one particular stack or global variable, we
-will be flooded with errors resulting from calls to
-<function>memcpy</function>.</para>
-
-<para>To avoid this problem, SGCheck instantiates fresh likely-target
-records for each entry to a function, and discards them on exit.  This
-allows detection of cases where (e.g.) <function>memcpy</function>
-overflows its source or destination buffers for any specific call, but
-does not carry any restriction from one call to the next.  Indeed,
-multiple threads may make multiple simultaneous calls to
-(e.g.) <function>memcpy</function> without mutual interference.</para>
-
-<para>It is important to note that the association is done between
-  a <emphasis>binary instruction</emphasis> and an array, the
-  <emphasis>first time</emphasis> this binary instruction accesses an
-  array during a function call.  When the same instruction is executed
-  again during the same function call, then SGCheck might report a
-  problem, if these further executions are not accessing the same
-  array. This technique causes several limitations in SGCheck, see
-  <xref linkend="sg-manual.limitations"/>.
-</para>
-</sect1>
-
-
-
-<sect1 id="sg-manual.cmp-w-memcheck"
-       xreflabel="Comparison with Memcheck">
-<title>Comparison with Memcheck</title>
-
-<para>SGCheck and Memcheck are complementary: their capabilities do
-not overlap.  Memcheck performs bounds checks and use-after-free
-checks for heap arrays.  It also finds uses of uninitialised values
-created by heap or stack allocations.  But it does not perform bounds
-checking for stack or global arrays.</para>
-
-<para>SGCheck, on the other hand, does do bounds checking for stack or
-global arrays, but it doesn't do anything else.</para>
-
-</sect1>
-
-
-
-
-
-<sect1 id="sg-manual.limitations"
-       xreflabel="Limitations">
-<title>Limitations</title>
-
-<para>This is an experimental tool, which relies rather too heavily on some
-not-as-robust-as-I-would-like assumptions on the behaviour of correct
-programs.  There are a number of limitations which you should be aware
-of.</para>
-
-<itemizedlist>
-
-  <listitem>
-   <para>False negatives (missed errors): it follows from the
-   description above (<xref linkend="sg-manual.how-works.sg-checks"/>)
-   that the first access by a memory referencing instruction to a
-   stack or global array creates an association between that
-   instruction and the array, which is checked on subsequent accesses
-   by that instruction, until the containing function exits.  Hence,
-   the first access by an instruction to an array (in any given
-   function instantiation) is not checked for overrun, since SGCheck
-   uses that as the "example" of how subsequent accesses should
-   behave.</para>
-   <para>It also means that errors will not be found in an instruction
-     executed only once (e.g. because this instruction is not in a loop,
-     or the loop is executed only once).</para>
-  </listitem>
-
-  <listitem>
-   <para>False positives (false errors): similarly, and more serious,
-   it is clearly possible to write legitimate pieces of code which
-   break the basic assumption upon which the checking algorithm
-   depends.  For example:</para>
-
-<programlisting><![CDATA[
-  { int a[10], b[10], *p, i;
-    for (i = 0; i < 10; i++) {
-       p = /* arbitrary condition */  ? &a[i]  : &b[i];
-       *p = 42;
-    }
-  }
-]]></programlisting>
-
-   <para>In this case the store sometimes
-   accesses <computeroutput>a[]</computeroutput> and
-   sometimes <computeroutput>b[]</computeroutput>, but in no cases is
-   the addressed array overrun.  Nevertheless the change in target
-   will cause an error to be reported.</para>
-
-   <para>It is hard to see how to get around this problem.  The only
-   mitigating factor is that such constructions appear very rare, at
-   least judging from the results using the tool so far.  Such a
-   construction appears only once in the Valgrind sources (running
-   Valgrind on Valgrind) and perhaps two or three times for a start
-   and exit of Firefox.  The best that can be done is to suppress the
-   errors.</para>
-  </listitem>
-
-  <listitem>
-   <para>Performance: SGCheck has to read all of
-   the DWARF3 type and variable information on the executable and its
-   shared objects.  This is computationally expensive and makes
-   startup quite slow.  You can expect debuginfo reading time to be in
-   the region of a minute for an OpenOffice sized application, on a
-   2.4 GHz Core 2 machine.  Reading this information also requires a
-   lot of memory.  To make it viable, SGCheck goes to considerable
-   trouble to compress the in-memory representation of the DWARF3
-   data, which is why the process of reading it appears slow.</para>
-  </listitem>
-
-  <listitem>
-   <para>Performance: SGCheck runs slower than Memcheck.  This is
-   partly due to a lack of tuning, but partly due to algorithmic
-   difficulties.  The
-   stack and global checks can sometimes require a number of range
-   checks per memory access, and these are difficult to short-circuit,
-   despite considerable efforts having been made.  A
-   redesign and reimplementation could potentially make it much faster.
-   </para>
-  </listitem>
-
-  <listitem>
-   <para>Coverage: Stack and global checking is fragile.  If a shared
-   object does not have debug information attached, then SGCheck will
-   not be able to determine the bounds of any stack or global arrays
-   defined within that shared object, and so will not be able to check
-   accesses to them.  This is true even when those arrays are accessed
-   from some other shared object which was compiled with debug
-   info.</para>
-
-   <para>At the moment SGCheck accepts objects lacking debuginfo
-   without comment.  This is dangerous as it causes SGCheck to
-   silently skip stack and global checking for such objects.  It would
-   be better to print a warning in such circumstances.</para>
-  </listitem>
-
-  <listitem>
-   <para>Coverage: SGCheck does not check whether the areas read
-   or written by system calls do overrun stack or global arrays.  This
-   would be easy to add.</para>
-  </listitem>
-
-  <listitem>
-   <para>Platforms: the stack/global checks won't work properly on
-   PowerPC, ARM or S390X platforms, only on X86 and AMD64 targets.
-   That's because the stack and global checking requires tracking
-   function calls and exits reliably, and there's no obvious way to do
-   it on ABIs that use a link register for function returns.
-   </para>
-  </listitem>
-
-  <listitem>
-   <para>Robustness: related to the previous point.  Function
-   call/exit tracking for X86 and AMD64 is believed to work properly
-   even in the presence of longjmps within the same stack (although
-   this has not been tested).  However, code which switches stacks is
-   likely to cause breakage/chaos.</para>
-  </listitem>
-</itemizedlist>
-
-</sect1>
-
-
-
-
-
-<sect1 id="sg-manual.todo-user-visible"
-       xreflabel="Still To Do: User-visible Functionality">
-<title>Still To Do: User-visible Functionality</title>
-
-<itemizedlist>
-
-  <listitem>
-   <para>Extend system call checking to work on stack and global arrays.</para>
-  </listitem>
-
-  <listitem>
-   <para>Print a warning if a shared object does not have debug info
-   attached, or if, for whatever reason, debug info could not be
-   found, or read.</para>
-  </listitem>
-
-  <listitem>
-   <para>Add some heuristic filtering that removes obvious false
-     positives.  This would be easy to do.  For example, an access
-     transition from a heap to a stack object almost certainly isn't a
-     bug and so should not be reported to the user.</para>
-  </listitem>
-
-</itemizedlist>
-
-</sect1>
-
-
-
-
-<sect1 id="sg-manual.todo-implementation"
-       xreflabel="Still To Do: Implementation Tidying">
-<title>Still To Do: Implementation Tidying</title>
-
-<para>Items marked CRITICAL are considered important for correctness:
-non-fixage of them is liable to lead to crashes or assertion failures
-in real use.</para>
-
-<itemizedlist>
-
-  <listitem>
-   <para> sg_main.c: Redesign and reimplement the basic checking
-   algorithm.  It could be done much faster than it is -- the current
-   implementation isn't very good.
-   </para>
-  </listitem>
-
-  <listitem>
-   <para> sg_main.c: Improve the performance of the stack / global
-   checks by doing some up-front filtering to ignore references in
-   areas which "obviously" can't be stack or globals.  This will
-   require using information that m_aspacemgr knows about the address
-   space layout.</para>
-  </listitem>
-  <listitem>
-   <para>sg_main.c: fix compute_II_hash to make it a bit more sensible
-   for ppc32/64 targets (except that sg_ doesn't work on ppc32/64
-   targets, so this is a bit academic at the moment).</para>
-  </listitem>
-  
-</itemizedlist>
-
-</sect1>
-
-
-
-</chapter>
diff --git a/exp-sgcheck/h_intercepts.c b/exp-sgcheck/h_intercepts.c
deleted file mode 100644 (file)
index 6fe8680..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Ptrcheck: a pointer-use checker.             pc_intercepts.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Ptrcheck, a Valgrind tool for checking pointer
-   use in programs.
-
-   Copyright (C) 2003-2017 Nicholas Nethercote
-      njn@valgrind.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-/* Nothing actually in here.  However it appears this file is needed
-   to make malloc intercepting work. (jrs, 2 july 08 -- not sure about
-   that).
-*/
-
-#include "pub_tool_basics.h"
-#include "pub_tool_hashtable.h"
-#include "pub_tool_redir.h"
-#include "pub_tool_tooliface.h"
-#include "pub_tool_clreq.h"
-
-
-/* The following intercepts are copied verbatim from
-   memcheck/mc_replace_strmem.c.  If you copy more in, please keep
-   them in the same order as in mc_replace_strmem.c. */
-
-
-#define STRRCHR(soname, fnname) \
-   char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ); \
-   char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ) \
-   { \
-      HChar ch = (HChar)c;   \
-      const HChar* p = s;       \
-      const HChar* last = NULL; \
-      while (True) { \
-         if (*p == ch) last = p; \
-         if (*p == 0) return CONST_CAST(HChar *,last);    \
-         p++; \
-      } \
-   }
-
-// Apparently rindex() is the same thing as strrchr()
-STRRCHR(VG_Z_LIBC_SONAME,   strrchr)
-STRRCHR(VG_Z_LIBC_SONAME,   rindex)
-#if defined(VGO_linux)
-STRRCHR(VG_Z_LIBC_SONAME,   __GI_strrchr)
-STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
-#elif defined(VGO_darwin)
-STRRCHR(VG_Z_DYLD,          strrchr)
-STRRCHR(VG_Z_DYLD,          rindex)
-#elif defined(VGO_solaris)
-STRRCHR(VG_Z_LD_SO_1,       strrchr)
-#endif
-
-
-#define STRCHR(soname, fnname) \
-   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
-   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
-   { \
-      HChar  ch = (HChar)c ; \
-      const HChar* p  = s;   \
-      while (True) { \
-         if (*p == ch) return CONST_CAST(HChar *,p);       \
-         if (*p == 0) return NULL; \
-         p++; \
-      } \
-   }
-
-// Apparently index() is the same thing as strchr()
-STRCHR(VG_Z_LIBC_SONAME,          strchr)
-STRCHR(VG_Z_LIBC_SONAME,          index)
-#if defined(VGO_linux)
-STRCHR(VG_Z_LIBC_SONAME,          __GI_strchr)
-STRCHR(VG_Z_LD_LINUX_SO_2,        strchr)
-STRCHR(VG_Z_LD_LINUX_SO_2,        index)
-STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
-STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
-#elif defined(VGO_darwin)
-STRCHR(VG_Z_DYLD,                 strchr)
-STRCHR(VG_Z_DYLD,                 index)
-#elif defined(VGO_solaris)
-STRCHR(VG_Z_LD_SO_1,              strchr)
-#endif
-
-
-#define STRNLEN(soname, fnname) \
-   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
-   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
-   { \
-      SizeT i = 0; \
-      while (i < n && str[i] != 0) i++; \
-      return i; \
-   }
-
-STRNLEN(VG_Z_LIBC_SONAME, strnlen)
-
-
-// Note that this replacement often doesn't get used because gcc inlines
-// calls to strlen() with its own built-in version.  This can be very
-// confusing if you aren't expecting it.  Other small functions in this file
-// may also be inline by gcc.
-#define STRLEN(soname, fnname) \
-   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
-   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
-   { \
-      SizeT i = 0; \
-      while (str[i] != 0) i++; \
-      return i; \
-   }
-
-STRLEN(VG_Z_LIBC_SONAME,          strlen)
-#if defined(VGO_linux)
-STRLEN(VG_Z_LIBC_SONAME,          __GI_strlen)
-STRLEN(VG_Z_LD_LINUX_SO_2,        strlen)
-STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
-STRLEN(VG_Z_LD_SO_1,              strlen)
-#elif defined(VGO_solaris)
-STRLEN(VG_Z_LD_SO_1,              strlen)
-#endif
-
-
-#define STRCPY(soname, fnname) \
-   char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
-   char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
-   { \
-      HChar* dst_orig = dst; \
-      \
-      while (*src) *dst++ = *src++; \
-      *dst = 0; \
-      \
-      return dst_orig; \
-   }
-
-STRCPY(VG_Z_LIBC_SONAME, strcpy)
-#if defined(VGO_linux)
-STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
-#elif defined(VGO_darwin)
-STRCPY(VG_Z_DYLD,        strcpy)
-#elif defined(VGO_solaris)
-STRCPY(VG_Z_LD_SO_1,     strcpy)
-#endif
-
-
-#define STRNCMP(soname, fnname) \
-   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
-          ( const char* s1, const char* s2, SizeT nmax ); \
-   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
-          ( const char* s1, const char* s2, SizeT nmax ) \
-   { \
-      SizeT n = 0; \
-      while (True) { \
-         if (n >= nmax) return 0; \
-         if (*s1 == 0 && *s2 == 0) return 0; \
-         if (*s1 == 0) return -1; \
-         if (*s2 == 0) return 1; \
-         \
-         if (*(const unsigned char*)s1 < *(const unsigned char*)s2) return -1; \
-         if (*(const unsigned char*)s1 > *(const unsigned char*)s2) return 1; \
-         \
-         s1++; s2++; n++; \
-      } \
-   }
-
-STRNCMP(VG_Z_LIBC_SONAME, strncmp)
-#if defined(VGO_linux)
-STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
-#elif defined(VGO_darwin)
-STRNCMP(VG_Z_DYLD,        strncmp)
-#endif
-
-
-#define STRCMP(soname, fnname) \
-   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
-          ( const char* s1, const char* s2 ); \
-   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
-          ( const char* s1, const char* s2 ) \
-   { \
-      register UChar c1; \
-      register UChar c2; \
-      while (True) { \
-         c1 = *(const UChar *)s1; \
-         c2 = *(const UChar *)s2; \
-         if (c1 != c2) break; \
-         if (c1 == 0) break; \
-         s1++; s2++; \
-      } \
-      if ((UChar)c1 < (UChar)c2) return -1; \
-      if ((UChar)c1 > (UChar)c2) return 1; \
-      return 0; \
-   }
-
-STRCMP(VG_Z_LIBC_SONAME,          strcmp)
-#if defined(VGO_linux)
-STRCMP(VG_Z_LIBC_SONAME,          __GI_strcmp)
-STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
-STRCMP(VG_Z_LD64_SO_1,            strcmp)
-#elif defined(VGO_solaris)
-STRCMP(VG_Z_LD_SO_1,              strcmp)
-#endif
-
-
-#define MEMCHR(soname, fnname) \
-   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
-   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
-   { \
-      SizeT i; \
-      UChar c0 = (UChar)c; \
-      const UChar* p = s; \
-      for (i = 0; i < n; i++) \
-         if (p[i] == c0) return CONST_CAST(void *,&p[i]);  \
-      return NULL; \
-   }
-
-MEMCHR(VG_Z_LIBC_SONAME, memchr)
-#if defined(VGO_darwin)
-MEMCHR(VG_Z_DYLD,        memchr)
-#endif
-
-
-#define MEMCPY(soname, fnname) \
-   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
-            ( void *dst, const void *src, SizeT len ); \
-   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
-            ( void *dst, const void *src, SizeT len ) \
-   { \
-      const Addr WS = sizeof(UWord); /* 8 or 4 */ \
-      const Addr WM = WS - 1;        /* 7 or 3 */ \
-      \
-      if (len > 0) { \
-         if (dst < src) { \
-         \
-            /* Copying backwards. */ \
-            SizeT n = len; \
-            Addr  d = (Addr)dst; \
-            Addr  s = (Addr)src; \
-            \
-            if (((s^d) & WM) == 0) { \
-               /* s and d have same UWord alignment. */ \
-               /* Pull up to a UWord boundary. */ \
-               while ((s & WM) != 0 && n >= 1) \
-                  { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
-               /* Copy UWords. */ \
-               while (n >= WS) \
-                  { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
-               if (n == 0) \
-                  return dst; \
-            } \
-            if (((s|d) & 1) == 0) { \
-               /* Both are 16-aligned; copy what we can thusly. */ \
-               while (n >= 2) \
-                  { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
-            } \
-            /* Copy leftovers, or everything if misaligned. */ \
-            while (n >= 1) \
-               { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
-         \
-         } else if (dst > src) { \
-         \
-            SizeT n = len; \
-            Addr  d = ((Addr)dst) + n; \
-            Addr  s = ((Addr)src) + n; \
-            \
-            /* Copying forwards. */ \
-            if (((s^d) & WM) == 0) { \
-               /* s and d have same UWord alignment. */ \
-               /* Back down to a UWord boundary. */ \
-               while ((s & WM) != 0 && n >= 1) \
-                  { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
-               /* Copy UWords. */ \
-               while (n >= WS) \
-                  { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
-               if (n == 0) \
-                  return dst; \
-            } \
-            if (((s|d) & 1) == 0) { \
-               /* Both are 16-aligned; copy what we can thusly. */ \
-               while (n >= 2) \
-                  { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
-            } \
-            /* Copy leftovers, or everything if misaligned. */ \
-            while (n >= 1) \
-               { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
-            \
-         } \
-      } \
-      \
-      return dst; \
-   }
-
-MEMCPY(VG_Z_LIBC_SONAME, memcpy)
-#if defined(VGO_linux)
-MEMCPY(VG_Z_LD_SO_1,     memcpy) /* ld.so.1 */
-MEMCPY(VG_Z_LD64_SO_1,   memcpy) /* ld64.so.1 */
-#elif defined(VGO_solaris)
-MEMCPY(VG_Z_LD_SO_1,      memcpy)
-#endif
-
-
-/* Copy SRC to DEST, returning the address of the terminating '\0' in
-   DEST. (minor variant of strcpy) */
-#define STPCPY(soname, fnname) \
-   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
-   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
-   { \
-      while (*src) *dst++ = *src++; \
-      *dst = 0; \
-      \
-      return dst; \
-   }
-
-STPCPY(VG_Z_LIBC_SONAME,          stpcpy)
-#if defined(VGO_linux)
-STPCPY(VG_Z_LD_LINUX_SO_2,        stpcpy)
-STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
-#endif
-
-
-/* Find the first occurrence of C in S.  */
-#define GLIBC232_RAWMEMCHR(soname, fnname) \
-   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in); \
-   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in) \
-   { \
-      UChar c = (UChar)c_in; \
-      const UChar* char_ptr = s; \
-      while (1) { \
-         if (*char_ptr == c) return CONST_CAST(void *,char_ptr);   \
-         char_ptr++; \
-      } \
-   }
-
-GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
-#if defined (VGO_linux)
-GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
-#endif
-
-
-#define STRSTR(soname, fnname) \
-   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
-         (const char* haystack, const char* needle); \
-   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
-         (const char* haystack, const char* needle) \
-   { \
-      const HChar* h = haystack; \
-      const HChar* n = needle; \
-      \
-      /* find the length of n, not including terminating zero */ \
-      UWord nlen = 0; \
-      while (n[nlen]) nlen++; \
-      \
-      /* if n is the empty string, match immediately. */ \
-      if (nlen == 0) return CONST_CAST(HChar *,h);         \
-      \
-      /* assert(nlen >= 1); */ \
-      HChar n0 = n[0]; \
-      \
-      while (1) { \
-         const HChar hh = *h; \
-         if (hh == 0) return NULL; \
-         if (hh != n0) { h++; continue; } \
-         \
-         UWord i; \
-         for (i = 0; i < nlen; i++) { \
-            if (n[i] != h[i]) \
-               break; \
-         } \
-         /* assert(i >= 0 && i <= nlen); */ \
-         if (i == nlen) \
-            return CONST_CAST(HChar *,h);          \
-         \
-         h++; \
-      } \
-   }
-
-#if defined(VGO_linux)
-STRSTR(VG_Z_LIBC_SONAME,          strstr)
-#elif defined(VGO_solaris)
-STRSTR(VG_Z_LIBC_SONAME,          strstr)
-#endif
-
-
-#define STRPBRK(soname, fnname) \
-   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
-         (const char* sV, const char* acceptV); \
-   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
-         (const char* sV, const char* acceptV) \
-   { \
-      const HChar* s = sV; \
-      const HChar* accept = acceptV; \
-      \
-      /*  find the length of 'accept', not including terminating zero */ \
-      UWord nacc = 0; \
-      while (accept[nacc]) nacc++; \
-      \
-      /* if n is the empty string, fail immediately. */ \
-      if (nacc == 0) return NULL; \
-      \
-      /* assert(nacc >= 1); */ \
-      while (1) { \
-         UWord i; \
-         HChar sc = *s; \
-         if (sc == 0) \
-            break; \
-         for (i = 0; i < nacc; i++) { \
-            if (sc == accept[i]) \
-               return CONST_CAST(HChar *,s);       \
-         } \
-         s++; \
-      } \
-      \
-      return NULL; \
-   }
-
-#if defined(VGO_linux)
-STRPBRK(VG_Z_LIBC_SONAME,          strpbrk)
-#elif defined(VGO_solaris)
-STRPBRK(VG_Z_LIBC_SONAME,          strpbrk)
-#endif
-
-
-/*--------------------------------------------------------------------*/
-/*--- end                                          pc_intercepts.c ---*/
-/*--------------------------------------------------------------------*/
diff --git a/exp-sgcheck/h_main.c b/exp-sgcheck/h_main.c
deleted file mode 100644 (file)
index 64cac3a..0000000
+++ /dev/null
@@ -1,722 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Ptrcheck: a pointer-use checker.                             ---*/
-/*--- This file checks heap accesses.                              ---*/
-/*---                                                     h_main.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Ptrcheck, a Valgrind tool for checking pointer
-   use in programs.
-
-   Initial version (Annelid):
-
-   Copyright (C) 2003-2017 Nicholas Nethercote
-      njn@valgrind.org
-
-   Valgrind-3.X port:
-
-   Copyright (C) 2008-2017 OpenWorks Ltd
-      info@open-works.co.uk
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#include "pub_tool_basics.h"
-#include "pub_tool_libcbase.h"
-#include "pub_tool_libcprint.h"
-#include "pub_tool_libcassert.h"
-#include "pub_tool_mallocfree.h"
-#include "pub_tool_execontext.h"
-#include "pub_tool_hashtable.h"
-#include "pub_tool_tooliface.h"
-#include "pub_tool_replacemalloc.h"
-#include "pub_tool_options.h"
-#include "pub_tool_execontext.h"
-#include "pub_tool_aspacemgr.h"    // VG_(am_shadow_malloc)
-#include "pub_tool_vki.h"          // VKI_MAX_PAGE_SIZE
-#include "pub_tool_machine.h"      // VG_({get,set}_shadow_regs_area) et al
-#include "pub_tool_debuginfo.h"    // VG_(get_fnname)
-#include "pub_tool_threadstate.h"  // VG_(get_running_tid)
-#include "pub_tool_oset.h"
-#include "pub_tool_vkiscnums.h"
-#include "pub_tool_machine.h"
-#include "pub_tool_wordfm.h"
-#include "pub_tool_xarray.h"
-
-#include "pc_common.h"
-
-//#include "h_list.h"
-#include "h_main.h"
-
-#include "sg_main.h"   // sg_instrument_*, and struct _SGEnv
-
-
-
-/*------------------------------------------------------------*/
-/*--- Debug/trace options                                  ---*/
-/*------------------------------------------------------------*/
-
-static ULong stats__client_mallocs = 0;
-static ULong stats__client_frees   = 0;
-static ULong stats__segs_allocd    = 0;
-static ULong stats__segs_recycled  = 0;
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// Segments low level storage                               //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-// NONPTR, UNKNOWN, BOTTOM defined in h_main.h since 
-// pc_common.c needs to see them, for error processing
-
-// we only start recycling segs when this many exist
-#define N_FREED_SEGS (1 * 1000 * 1000)
-
-struct _Seg {
-   Addr  addr;
-   SizeT szB; /* may be zero */
-   ExeContext* ec;  /* where malloc'd or freed */
-   /* When 1, indicates block is in use.  Otherwise, used to form a
-      linked list of freed blocks, running from oldest freed block to
-      the most recently freed block. */
-   struct _Seg* nextfree;
-};
-
-// Determines if 'a' is before, within, or after seg's range.  Sets 'cmp' to
-// -1/0/1 accordingly.  Sets 'n' to the number of bytes before/within/after.
-void Seg__cmp(Seg* seg, Addr a, Int* cmp, UWord* n)
-{
-   if (a < seg->addr) {
-      *cmp = -1;
-      *n   = seg->addr - a;
-   } else if (a < seg->addr + seg->szB && seg->szB > 0) {
-      *cmp = 0;
-      *n = a - seg->addr;
-   } else {
-      *cmp = 1;
-      *n = a - (seg->addr + seg->szB);
-   }
-}
-
-/*inline*/ Bool Seg__is_freed(Seg* seg)
-{
-   if (!is_known_segment(seg))
-      return False;
-   else
-      return seg->nextfree != (Seg*)1;
-}
-
-ExeContext* Seg__where(Seg* seg)
-{
-   tl_assert(is_known_segment(seg));
-   return seg->ec;
-}
-
-SizeT Seg__size(Seg* seg)
-{
-   tl_assert(is_known_segment(seg));
-   return seg->szB;
-}
-
-Addr Seg__addr(Seg* seg)
-{
-   tl_assert(is_known_segment(seg));
-   return seg->addr;
-}
-
-
-#define N_SEGS_PER_GROUP 10000
-
-typedef
-   struct _SegGroup {
-      struct _SegGroup* admin;
-      UWord nextfree; /* 0 .. N_SEGS_PER_GROUP */
-      Seg segs[N_SEGS_PER_GROUP];
-   }
-   SegGroup;
-
-static SegGroup* group_list = NULL;
-static UWord     nFreeSegs = 0;
-static Seg*      freesegs_youngest = NULL;
-static Seg*      freesegs_oldest = NULL;
-
-
-static SegGroup* new_SegGroup ( void ) {
-   SegGroup* g = VG_(malloc)("pc.h_main.nTG.1", sizeof(SegGroup));
-   VG_(memset)(g, 0, sizeof(*g));
-   return g;
-}
-
-/* Get a completely new Seg */
-static Seg* new_Seg ( void )
-{
-   Seg*      teg;
-   SegGroup* g;
-   if (group_list == NULL) {
-      g = new_SegGroup();
-      g->admin = NULL;
-      group_list = g;
-   }
-   tl_assert(group_list->nextfree <= N_SEGS_PER_GROUP);
-   if (group_list->nextfree == N_SEGS_PER_GROUP) {
-      g = new_SegGroup();
-      g->admin = group_list;
-      group_list = g;
-   }
-   tl_assert(group_list->nextfree < N_SEGS_PER_GROUP);
-   teg = &group_list->segs[ group_list->nextfree ];
-   group_list->nextfree++;
-   stats__segs_allocd++;
-   return teg;
-}
-
-static Seg* get_Seg_for_malloc ( void )
-{
-   Seg* seg;
-   if (nFreeSegs < N_FREED_SEGS) {
-      seg = new_Seg();
-      seg->nextfree = (Seg*)1;
-      return seg;
-   }
-   /* else recycle the oldest Seg in the free list */
-   tl_assert(freesegs_youngest);
-   tl_assert(freesegs_oldest);
-   tl_assert(freesegs_youngest != freesegs_oldest);
-   seg = freesegs_oldest;
-   freesegs_oldest = seg->nextfree;
-   nFreeSegs--;
-   seg->nextfree = (Seg*)1;
-   stats__segs_recycled++;
-   return seg;
-}
-
-static void set_Seg_freed ( Seg* seg )
-{
-   tl_assert(seg);
-   tl_assert(!Seg__is_freed(seg));
-   if (nFreeSegs == 0) {
-      tl_assert(freesegs_oldest == NULL);
-      tl_assert(freesegs_youngest == NULL);
-      seg->nextfree = NULL;
-      freesegs_youngest = seg;
-      freesegs_oldest = seg;
-      nFreeSegs++;
-   } else {
-      tl_assert(freesegs_youngest);
-      tl_assert(freesegs_oldest);
-      if (nFreeSegs == 1) {
-         tl_assert(freesegs_youngest == freesegs_oldest);
-      } else {
-         tl_assert(freesegs_youngest != freesegs_oldest);
-      }
-      tl_assert(freesegs_youngest->nextfree == NULL);
-      tl_assert(seg != freesegs_youngest && seg != freesegs_oldest);
-      seg->nextfree = NULL;
-      freesegs_youngest->nextfree = seg;
-      freesegs_youngest = seg;
-      nFreeSegs++;
-   }
-}
-
-static WordFM* addr_to_seg_map = NULL; /* GuestAddr -> Seg* */
-
-static void addr_to_seg_map_ENSURE_INIT ( void )
-{
-   if (UNLIKELY(addr_to_seg_map == NULL)) {
-      addr_to_seg_map = VG_(newFM)( VG_(malloc), "pc.h_main.attmEI.1",
-                                    VG_(free), NULL/*unboxedcmp*/ );
-   }
-}
-
-static Seg* find_Seg_by_addr ( Addr ga )
-{
-   UWord keyW, valW;
-   addr_to_seg_map_ENSURE_INIT();
-   if (VG_(lookupFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga )) {
-      tl_assert(keyW == ga);
-      return (Seg*)valW;
-   } else {
-      return NULL;
-   }
-}
-
-static void bind_addr_to_Seg ( Addr ga, Seg* seg )
-{
-   Bool b;
-   addr_to_seg_map_ENSURE_INIT();
-   b = VG_(addToFM)( addr_to_seg_map, (UWord)ga, (UWord)seg );
-   tl_assert(!b); /* else ga is already bound */
-}
-
-static void unbind_addr_from_Seg ( Addr ga )
-{
-   Bool b;
-   UWord keyW, valW;
-   addr_to_seg_map_ENSURE_INIT();
-   b = VG_(delFromFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga );
-   tl_assert(b); /* else ga was not already bound */
-   tl_assert(keyW == ga);
-   tl_assert(valW != 0);
-}
-
-
-//////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////
-
-// Returns the added heap segment
-static Seg* add_new_segment ( ThreadId tid, Addr p, SizeT size )
-{
-   Seg* seg = get_Seg_for_malloc();
-   tl_assert(seg != (Seg*)1); /* since we're using 1 as a special value */
-   seg->addr = p;
-   seg->szB  = size;
-   seg->ec   = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
-   tl_assert(!Seg__is_freed(seg));
-
-   bind_addr_to_Seg(p, seg);
-
-   return seg;
-}
-
-
-
-static
-void* alloc_and_new_mem_heap ( ThreadId tid,
-                               SizeT size, SizeT alignment, Bool is_zeroed )
-{
-   Addr p;
-
-   if ( ((SSizeT)size) < 0) return NULL;
-
-   p = (Addr)VG_(cli_malloc)(alignment, size);
-   if (is_zeroed) VG_(memset)((void*)p, 0, size);
-
-   add_new_segment( tid, p, size );
-
-   stats__client_mallocs++;
-   return (void*)p;
-}
-
-static void die_and_free_mem_heap ( ThreadId tid, Seg* seg )
-{
-   // Empty and free the actual block
-   tl_assert(!Seg__is_freed(seg));
-
-   VG_(cli_free)( (void*)seg->addr );
-
-   // Remember where freed
-   seg->ec = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
-
-   set_Seg_freed(seg);
-   unbind_addr_from_Seg( seg->addr );
-
-   stats__client_frees++;
-}
-
-static void handle_free_heap( ThreadId tid, void* p )
-{
-   Seg* seg = find_Seg_by_addr( (Addr)p );
-   if (!seg) {
-      /* freeing a block that wasn't malloc'd.  Ignore. */
-      return;
-   }
-   die_and_free_mem_heap( tid, seg );
-}
-
-
-/*------------------------------------------------------------*/
-/*--- malloc() et al replacements                          ---*/
-/*------------------------------------------------------------*/
-
-void* h_replace_malloc ( ThreadId tid, SizeT n )
-{
-   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
-                                        /*is_zeroed*/False );
-}
-
-void* h_replace___builtin_new ( ThreadId tid, SizeT n )
-{
-   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
-                                           /*is_zeroed*/False );
-}
-
-void* h_replace___builtin_vec_new ( ThreadId tid, SizeT n )
-{
-   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
-                                           /*is_zeroed*/False );
-}
-
-void* h_replace_memalign ( ThreadId tid, SizeT align, SizeT n )
-{
-   return alloc_and_new_mem_heap ( tid, n, align,
-                                        /*is_zeroed*/False );
-}
-
-void* h_replace_calloc ( ThreadId tid, SizeT nmemb, SizeT size1 )
-{
-   return alloc_and_new_mem_heap ( tid, nmemb*size1, VG_(clo_alignment),
-                                        /*is_zeroed*/True );
-}
-
-void h_replace_free ( ThreadId tid, void* p )
-{
-   // Should arguably check here if p.vseg matches the segID of the
-   // pointed-to block... unfortunately, by this stage, we don't know what
-   // p.vseg is, because we don't know the address of p (the p here is a
-   // copy, and we've lost the address of its source).  To do so would
-   // require passing &p in, which would require rewriting part of
-   // vg_replace_malloc.c... argh.
-   //
-   // However, Memcheck does free checking, and will catch almost all
-   // violations this checking would have caught.  (Would only miss if we
-   // unluckily passed an unrelated pointer to the very start of a heap
-   // block that was unrelated to that block.  This is very unlikely!)    So
-   // we haven't lost much.
-
-   handle_free_heap(tid, p);
-}
-
-void h_replace___builtin_delete ( ThreadId tid, void* p )
-{
-   handle_free_heap(tid, p);
-}
-
-void h_replace___builtin_vec_delete ( ThreadId tid, void* p )
-{
-   handle_free_heap(tid, p);
-}
-
-void* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size )
-{
-   Seg* seg;
-
-   /* First try and find the block. */
-   seg = find_Seg_by_addr( (Addr)p_old );
-   if (!seg)
-      return NULL;
-
-   tl_assert(seg->addr == (Addr)p_old);
-
-   if (new_size <= seg->szB) {
-      /* new size is smaller: allocate, copy from old to new */
-      Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
-      VG_(memcpy)((void*)p_new, p_old, new_size);
-
-      /* Free old memory */
-      die_and_free_mem_heap( tid, seg );
-
-      /* This has to be after die_and_free_mem_heap, otherwise the
-         former succeeds in shorting out the new block, not the
-         old, in the case when both are on the same list.  */
-      add_new_segment ( tid, p_new, new_size );
-
-      return (void*)p_new;
-   } else {
-      /* new size is bigger: allocate, copy from old to new */
-      Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
-      VG_(memcpy)((void*)p_new, p_old, seg->szB);
-
-      /* Free old memory */
-      die_and_free_mem_heap( tid, seg );
-
-      /* This has to be after die_and_free_mem_heap, otherwise the
-         former succeeds in shorting out the new block, not the old,
-         in the case when both are on the same list.  NB jrs
-         2008-Sept-11: not sure if this comment is valid/correct any
-         more -- I suspect not. */
-      add_new_segment ( tid, p_new, new_size );
-
-      return (void*)p_new;
-   }
-}
-
-SizeT h_replace_malloc_usable_size ( ThreadId tid, void* p )
-{
-   Seg* seg = find_Seg_by_addr( (Addr)p );
-
-   // There may be slop, but pretend there isn't because only the asked-for
-   // area will have been shadowed properly.
-   return ( seg ? seg->szB : 0 );
-}
-
-
-/*--------------------------------------------------------------------*/
-/*--- Instrumentation                                              ---*/
-/*--------------------------------------------------------------------*/
-
-/* The h_ instrumenter that follows is complex, since it deals with
-   shadow value computation.
-
-   It also needs to generate instrumentation for the sg_ side of
-   things.  That's relatively straightforward.  However, rather than
-   confuse the code herein any further, we simply delegate the problem
-   to sg_main.c, by using the four functions
-   sg_instrument_{init,fini,IRStmt,final_jump}.  These four completely
-   abstractify the sg_ instrumentation.  See comments in sg_main.c's
-   instrumentation section for further details. */
-
-
-/* Carries info about a particular tmp.  The tmp's number is not
-   recorded, as this is implied by (equal to) its index in the tmpMap
-   in PCEnv.  The tmp's type is also not recorded, as this is present
-   in PCEnv.sb->tyenv.
-
-   When .kind is NonShad, .shadow may give the identity of the temp
-   currently holding the associated shadow value, or it may be
-   IRTemp_INVALID if code to compute the shadow has not yet been
-   emitted.
-
-   When .kind is Shad tmp holds a shadow value, and so .shadow must be
-   IRTemp_INVALID, since it is illogical for a shadow tmp itself to be
-   shadowed.
-*/
-typedef
-   enum { NonShad=1, Shad=2 }
-   TempKind;
-
-typedef
-   struct {
-      TempKind kind;
-      IRTemp   shadow;
-   }
-   TempMapEnt;
-
-
-
-/* Carries around state during Ptrcheck instrumentation. */
-typedef
-   struct {
-      /* MODIFIED: the superblock being constructed.  IRStmts are
-         added. */
-      IRSB* sb;
-      Bool  trace;
-
-      /* MODIFIED: a table [0 .. #temps_in_sb-1] which gives the
-         current kind and possibly shadow temps for each temp in the
-         IRSB being constructed.  Note that it does not contain the
-         type of each tmp.  If you want to know the type, look at the
-         relevant entry in sb->tyenv.  It follows that at all times
-         during the instrumentation process, the valid indices for
-         tmpMap and sb->tyenv are identical, being 0 .. N-1 where N is
-         total number of NonShad and Shad temps allocated so far.
-
-         The reason for this strange split (types in one place, all
-         other info in another) is that we need the types to be
-         attached to sb so as to make it possible to do
-         "typeOfIRExpr(mce->bb->tyenv, ...)" at various places in the
-         instrumentation process.
-
-         Note that only integer temps of the guest word size are
-         shadowed, since it is impossible (or meaningless) to hold a
-         pointer in any other type of temp. */
-      XArray* /* of TempMapEnt */ qmpMap;
-
-      /* READONLY: the host word type.  Needed for constructing
-         arguments of type 'HWord' to be passed to helper functions.
-         Ity_I32 or Ity_I64 only. */
-      IRType hWordTy;
-
-      /* READONLY: the guest word type, Ity_I32 or Ity_I64 only. */
-      IRType gWordTy;
-
-      /* READONLY: the guest state size, so we can generate shadow
-         offsets correctly. */
-      Int guest_state_sizeB;
-   }
-   PCEnv;
-
-/* SHADOW TMP MANAGEMENT.  Shadow tmps are allocated lazily (on
-   demand), as they are encountered.  This is for two reasons.
-
-   (1) (less important reason): Many original tmps are unused due to
-   initial IR optimisation, and we do not want to spaces in tables
-   tracking them.
-
-   Shadow IRTemps are therefore allocated on demand.  pce.tmpMap is a
-   table indexed [0 .. n_types-1], which gives the current shadow for
-   each original tmp, or INVALID_IRTEMP if none is so far assigned.
-   It is necessary to support making multiple assignments to a shadow
-   -- specifically, after testing a shadow for definedness, it needs
-   to be made defined.  But IR's SSA property disallows this.
-
-   (2) (more important reason): Therefore, when a shadow needs to get
-   a new value, a new temporary is created, the value is assigned to
-   that, and the tmpMap is updated to reflect the new binding.
-
-   A corollary is that if the tmpMap maps a given tmp to
-   IRTemp_INVALID and we are hoping to read that shadow tmp, it means
-   there's a read-before-write error in the original tmps.  The IR
-   sanity checker should catch all such anomalies, however.
-*/
-
-/* Create a new IRTemp of type 'ty' and kind 'kind', and add it to
-   both the table in pce->sb and to our auxiliary mapping.  Note that
-   newTemp may cause pce->tmpMap to resize, hence previous results
-   from VG_(indexXA)(pce->tmpMap) are invalidated. */
-static IRTemp newTemp ( PCEnv* pce, IRType ty, TempKind kind )
-{
-   Word       newIx;
-   TempMapEnt ent;
-   IRTemp     tmp = newIRTemp(pce->sb->tyenv, ty);
-   ent.kind   = kind;
-   ent.shadow = IRTemp_INVALID;
-   newIx = VG_(addToXA)( pce->qmpMap, &ent );
-   tl_assert(newIx == (Word)tmp);
-   return tmp;
-}
-
-/*------------------------------------------------------------*/
-/*--- Constructing IR fragments                            ---*/
-/*------------------------------------------------------------*/
-
-/* add stmt to a bb */
-static /*inline*/ void stmt ( HChar cat, PCEnv* pce, IRStmt* st ) {
-   if (pce->trace) {
-      VG_(printf)("  %c: ", cat);
-      ppIRStmt(st);
-      VG_(printf)("\n");
-   }
-   addStmtToIRSB(pce->sb, st);
-}
-
-static IRTemp for_sg__newIRTemp_cb ( IRType ty, void* opaque )
-{
-   PCEnv* pce = (PCEnv*)opaque;
-   return newTemp( pce, ty, NonShad );
-}
-
-
-IRSB* h_instrument ( VgCallbackClosure* closure,
-                     IRSB* sbIn,
-                     const VexGuestLayout* layout,
-                     const VexGuestExtents* vge,
-                     const VexArchInfo* archinfo_host,
-                     IRType gWordTy, IRType hWordTy )
-{
-   Bool  verboze = 0||False;
-   Int   i /*, j*/;
-   PCEnv pce;
-   struct _SGEnv* sgenv;
-
-   if (gWordTy != hWordTy) {
-      /* We don't currently support this case. */
-      VG_(tool_panic)("host/guest word size mismatch");
-   }
-
-   /* Check we're not completely nuts */
-   tl_assert(sizeof(UWord)  == sizeof(void*));
-   tl_assert(sizeof(Word)   == sizeof(void*));
-   tl_assert(sizeof(Addr)   == sizeof(void*));
-   tl_assert(sizeof(ULong)  == 8);
-   tl_assert(sizeof(Long)   == 8);
-   tl_assert(sizeof(Addr)   == sizeof(void*));
-   tl_assert(sizeof(UInt)   == 4);
-   tl_assert(sizeof(Int)    == 4);
-
-   /* Set up the running environment.  Both .sb and .tmpMap are
-      modified as we go along.  Note that tmps are added to both
-      .sb->tyenv and .tmpMap together, so the valid index-set for
-      those two arrays should always be identical. */
-   VG_(memset)(&pce, 0, sizeof(pce));
-   pce.sb                = deepCopyIRSBExceptStmts(sbIn);
-   pce.trace             = verboze;
-   pce.hWordTy           = hWordTy;
-   pce.gWordTy           = gWordTy;
-   pce.guest_state_sizeB = layout->total_sizeB;
-
-   pce.qmpMap = VG_(newXA)( VG_(malloc), "pc.h_instrument.1", VG_(free),
-                            sizeof(TempMapEnt));
-   for (i = 0; i < sbIn->tyenv->types_used; i++) {
-      TempMapEnt ent;
-      ent.kind   = NonShad;
-      ent.shadow = IRTemp_INVALID;
-      VG_(addToXA)( pce.qmpMap, &ent );
-   }
-   tl_assert( VG_(sizeXA)( pce.qmpMap ) == sbIn->tyenv->types_used );
-
-   /* Also set up for the sg_ instrumenter.  See comments at the top
-      of this instrumentation section for details.  The two parameters
-      constitute a closure, which sg_ can use to correctly generate
-      new IRTemps as needed. */
-   sgenv = sg_instrument_init( for_sg__newIRTemp_cb,
-                               (void*)&pce );
-
-   /* Copy verbatim any IR preamble preceding the first IMark */
-
-   i = 0;
-   while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
-      IRStmt* st = sbIn->stmts[i];
-      tl_assert(st);
-      tl_assert(isFlatIRStmt(st));
-      stmt( 'C', &pce, sbIn->stmts[i] );
-      i++;
-   }
-
-   /* Iterate over the remaining stmts to generate instrumentation. */
-
-   tl_assert(sbIn->stmts_used > 0);
-   tl_assert(i >= 0);
-   tl_assert(i < sbIn->stmts_used);
-   tl_assert(sbIn->stmts[i]->tag == Ist_IMark);
-
-   for (/*use current i*/; i < sbIn->stmts_used; i++) {
-      /* generate sg_ instrumentation for this stmt */
-      sg_instrument_IRStmt( sgenv, pce.sb, sbIn->stmts[i],
-                            layout, gWordTy, hWordTy );
-
-      stmt( 'C', &pce, sbIn->stmts[i] );
-   }
-
-   /* generate sg_ instrumentation for the final jump */
-   sg_instrument_final_jump( sgenv, pce.sb, sbIn->next, sbIn->jumpkind,
-                             layout, gWordTy, hWordTy );
-
-   /* and finalise .. */
-   sg_instrument_fini( sgenv );
-
-   /* If this fails, there's been some serious snafu with tmp management,
-      that should be investigated. */
-   tl_assert( VG_(sizeXA)( pce.qmpMap ) == pce.sb->tyenv->types_used );
-   VG_(deleteXA)( pce.qmpMap );
-
-   return pce.sb;
-}
-
-
-/*--------------------------------------------------------------------*/
-/*--- Finalisation                                                 ---*/
-/*--------------------------------------------------------------------*/
-
-void h_fini ( Int exitcode )
-{
-   if (VG_(clo_stats)) {
-      VG_(message)(Vg_DebugMsg,
-                   "  h_:  %'10llu client allocs, %'10llu client frees\n", 
-                   stats__client_mallocs, stats__client_frees);
-      VG_(message)(Vg_DebugMsg,
-                   "  h_:  %'10llu Segs allocd,   %'10llu Segs recycled\n", 
-                   stats__segs_allocd, stats__segs_recycled);
-   }
-}
-
-
-/*--------------------------------------------------------------------*/
-/*--- end                                                 h_main.c ---*/
-/*--------------------------------------------------------------------*/
diff --git a/exp-sgcheck/h_main.h b/exp-sgcheck/h_main.h
deleted file mode 100644 (file)
index 75c0993..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Ptrcheck: a pointer-use checker.                             ---*/
-/*--- Exports for heap access checking.                            ---*/
-/*---                                                     h_main.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Ptrcheck, a Valgrind tool for checking pointer
-   use in programs.
-
-   Copyright (C) 2003-2017 Nicholas Nethercote
-      njn@valgrind.org
-   Copyright (C) 2008-2017 OpenWorks Ltd
-      info@open-works.co.uk
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef __H_MAIN_H
-
-#define __H_MAIN_H
-
-// Choose values that couldn't possibly be pointers
-#define NONPTR          ((Seg*)0xA1)
-#define UNKNOWN         ((Seg*)0xB2)
-#define BOTTOM          ((Seg*)0xC3)
-
-static inline Bool is_known_segment(Seg* teg) {
-   return (UNKNOWN != teg && BOTTOM != teg && NONPTR != teg);
-   // better?  teg <= BOTTOM
-}
-
-void        Seg__cmp(Seg* seg, Addr a, Int* cmp, UWord* n);
-Bool        Seg__is_freed(Seg* seg);
-ExeContext* Seg__where(Seg* seg);
-SizeT       Seg__size(Seg* seg);
-Addr        Seg__addr(Seg* seg);
-
-void h_pre_clo_init ( void );
-void h_post_clo_init ( void );
-void h_fini ( Int exitcode );
-
-void* h_replace_malloc ( ThreadId tid, SizeT n );
-void* h_replace___builtin_new ( ThreadId tid, SizeT n );
-void* h_replace___builtin_vec_new ( ThreadId tid, SizeT n );
-void* h_replace_memalign ( ThreadId tid, SizeT align, SizeT n );
-void* h_replace_calloc ( ThreadId tid, SizeT nmemb, SizeT size1 );
-void  h_replace_free ( ThreadId tid, void* p );
-void  h_replace___builtin_delete ( ThreadId tid, void* p );
-void  h_replace___builtin_vec_delete ( ThreadId tid, void* p );
-void* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size );
-SizeT h_replace_malloc_usable_size ( ThreadId tid, void* p );
-
-/* Note that this also does the sg_ instrumentation. */
-IRSB* h_instrument ( VgCallbackClosure* closure,
-                     IRSB* sbIn,
-                     const VexGuestLayout* layout,
-                     const VexGuestExtents* vge,
-                     const VexArchInfo* archinfo_host,
-                     IRType gWordTy, IRType hWordTy );
-
-#endif
-
-/*--------------------------------------------------------------------*/
-/*--- end                                                 h_main.h ---*/
-/*--------------------------------------------------------------------*/
diff --git a/exp-sgcheck/pc_common.c b/exp-sgcheck/pc_common.c
deleted file mode 100644 (file)
index fdad042..0000000
+++ /dev/null
@@ -1,814 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Ptrcheck: a pointer-use checker.                             ---*/
-/*--- Provides stuff shared between sg_ and h_ subtools.           ---*/
-/*---                                                  pc_common.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Ptrcheck, a Valgrind tool for checking pointer
-   use in programs.
-
-   Copyright (C) 2008-2017 OpenWorks Ltd
-      info@open-works.co.uk
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-   The GNU General Public License is contained in the file COPYING.
-
-   Neither the names of the U.S. Department of Energy nor the
-   University of California nor the names of its contributors may be
-   used to endorse or promote products derived from this software
-   without prior written permission.
-*/
-
-#include "pub_tool_basics.h"
-#include "pub_tool_libcbase.h"
-#include "pub_tool_libcprint.h"
-#include "pub_tool_xarray.h"
-#include "pub_tool_mallocfree.h"
-#include "pub_tool_libcassert.h"
-#include "pub_tool_options.h"
-#include "pub_tool_replacemalloc.h"
-#include "pub_tool_execontext.h"
-#include "pub_tool_tooliface.h"    // CorePart
-#include "pub_tool_threadstate.h"  // VG_(get_running_tid)
-#include "pub_tool_debuginfo.h"
-
-#include "pc_common.h"   // self, & Seg
-
-#include "h_main.h"      // NONPTR, BOTTOM, UNKNOWN
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// Command line options                                     //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-Bool h_clo_partial_loads_ok  = True;   /* user visible */
-/* Bool h_clo_lossage_check     = False; */ /* dev flag only */
-Bool sg_clo_enable_sg_checks = True;   /* user visible */
-
-Bool pc_process_cmd_line_options(const HChar* arg)
-{
-   if (VG_(Clo_Mode)() != cloP)
-      return False;
-
-        if VG_BOOL_CLO(arg, "--partial-loads-ok", h_clo_partial_loads_ok) {}
-   /* else if VG_BOOL_CLO(arg, "--lossage-check",    h_clo_lossage_check) {} */
-   else if VG_BOOL_CLO(arg, "--enable-sg-checks", sg_clo_enable_sg_checks) {}
-   else
-      return VG_(replacement_malloc_process_cmd_line_option)(arg);
-
-   return True;
-}
-
-void pc_print_usage(void)
-{
-   VG_(printf)(
-   "    --partial-loads-ok=no|yes  same as for Memcheck [yes]\n"
-   "    --enable-sg-checks=no|yes  enable stack & global array checking? [yes]\n"
-   );
-}
-
-void pc_print_debug_usage(void)
-{
-   VG_(printf)(
-"    (none)\n"
-//"    --lossage-check=no|yes    gather stats for quality control [no]\n"
-   );
-}
-
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// Error management -- storage                              //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-/* What kind of error it is. */
-typedef
-   enum {
-      XE_SorG=1202, // sg: stack or global array inconsistency
-      XE_Heap,      // h: mismatched ptr/addr segments on load/store
-      XE_Arith,     // h: bad arithmetic between two segment pointers
-      XE_SysParam   // h: block straddling >1 segment passed to syscall
-   }
-   XErrorTag;
-
-typedef
-   enum {
-      XS_SorG=2021,
-      XS_Heap,
-      XS_Arith,
-      XS_SysParam
-   }
-   XSuppTag;
-
-typedef
-   struct {
-      XErrorTag tag;
-      union {
-         struct {
-            Addr   addr;
-            SSizeT sszB;  /* -ve is write, +ve is read */
-            HChar  expect[128];
-            HChar  actual[128];
-            HChar  delta[32]; // text showing relation to expected
-         } SorG;
-         struct {
-            Addr     addr;
-            SSizeT   sszB;  /* -ve is write, +ve is read */
-            Seg*     vseg;
-            XArray*  descr1; /* XArray* of HChar */
-            XArray*  descr2; /* XArray* of HChar */
-            const HChar* datasym;
-            PtrdiffT datasymoff;
-         } Heap;
-         struct {
-            Seg* seg1;
-            Seg* seg2;
-            const HChar* opname; // user-understandable text name
-         } Arith;
-         struct {
-            CorePart part;
-            Addr lo;
-            Addr hi;
-            Seg* seglo;
-            Seg* seghi;
-         } SysParam;
-      } XE;
-   }
-   XError;
-
-
-void sg_record_error_SorG ( ThreadId tid,
-                            Addr addr, SSizeT sszB,
-                            HChar* expect, HChar* actual, HChar* delta )
-{
-   XError xe;
-   VG_(memset)(&xe, 0, sizeof(xe));
-   xe.tag = XE_SorG;
-   xe.XE.SorG.addr = addr;
-   xe.XE.SorG.sszB = sszB;
-   VG_(strncpy)( &xe.XE.SorG.expect[0],
-                 expect, sizeof(xe.XE.SorG.expect) );
-   VG_(strncpy)( &xe.XE.SorG.actual[0],
-                 actual, sizeof(xe.XE.SorG.actual) );
-   VG_(strncpy)( &xe.XE.SorG.delta[0],
-                 delta, sizeof(xe.XE.SorG.delta) );
-   xe.XE.SorG.expect[ sizeof(xe.XE.SorG.expect)-1 ] = 0;
-   xe.XE.SorG.actual[ sizeof(xe.XE.SorG.actual)-1 ] = 0;
-   xe.XE.SorG.delta[ sizeof(xe.XE.SorG.delta)-1 ] = 0;
-   VG_(maybe_record_error)( tid, XE_SorG, 0, NULL, &xe );
-}
-
-void h_record_heap_error( Addr a, SizeT size, Seg* vseg, Bool is_write )
-{
-   XError xe;
-   tl_assert(size > 0);
-   VG_(memset)(&xe, 0, sizeof(xe));
-   xe.tag = XE_Heap;
-   xe.XE.Heap.addr = a;
-   xe.XE.Heap.sszB = is_write ? -size : size;
-   xe.XE.Heap.vseg = vseg;
-   VG_(maybe_record_error)( VG_(get_running_tid)(), XE_Heap,
-                            /*a*/0, /*str*/NULL, /*extra*/(void*)&xe);
-}
-
-void h_record_arith_error( Seg* seg1, Seg* seg2, HChar* opname )
-{
-   XError xe;
-   VG_(memset)(&xe, 0, sizeof(xe));
-   xe.tag = XE_Arith;
-   xe.XE.Arith.seg1   = seg1;
-   xe.XE.Arith.seg2   = seg2;
-   xe.XE.Arith.opname = opname;
-   VG_(maybe_record_error)( VG_(get_running_tid)(), XE_Arith,
-                            /*a*/0, /*str*/NULL, /*extra*/(void*)&xe);
-}
-
-void h_record_sysparam_error( ThreadId tid, CorePart part, const HChar* s,
-                              Addr lo, Addr hi, Seg* seglo, Seg* seghi )
-{
-   XError xe;
-   VG_(memset)(&xe, 0, sizeof(xe));
-   xe.tag = XE_SysParam;
-   xe.XE.SysParam.part = part;
-   xe.XE.SysParam.lo = lo;
-   xe.XE.SysParam.hi = hi;
-   xe.XE.SysParam.seglo = seglo;
-   xe.XE.SysParam.seghi = seghi;
-   VG_(maybe_record_error)( tid, XE_SysParam, /*a*/(Addr)0, /*str*/s,
-                            /*extra*/(void*)&xe);
-}
-
-
-Bool pc_eq_Error ( VgRes res, const Error* e1, const Error* e2 )
-{
-   XError *xe1, *xe2;
-   tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
-   //tl_assert(VG_(get_error_string)(e1) == NULL);
-   //tl_assert(VG_(get_error_string)(e2) == NULL);
-
-   xe1 = (XError*)VG_(get_error_extra)(e1);
-   xe2 = (XError*)VG_(get_error_extra)(e2);
-   tl_assert(xe1);
-   tl_assert(xe2);
-
-   if (xe1->tag != xe2->tag)
-      return False;
-
-   switch (xe1->tag) {
-      case XE_SorG:
-         return //xe1->XE.SorG.addr == xe2->XE.SorG.addr
-                //&& 
-                xe1->XE.SorG.sszB == xe2->XE.SorG.sszB
-                && 0 == VG_(strncmp)( &xe1->XE.SorG.expect[0],
-                                      &xe2->XE.SorG.expect[0],
-                                      sizeof(xe1->XE.SorG.expect) ) 
-                && 0 == VG_(strncmp)( &xe1->XE.SorG.actual[0],
-                                      &xe2->XE.SorG.actual[0],
-                                      sizeof(xe1->XE.SorG.actual) );
-      case XE_Heap:
-      case XE_Arith:
-      case XE_SysParam:
-         return True;
-      default:
-         VG_(tool_panic)("eq_Error: unrecognised error kind");
-   }
-}
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// Error management -- printing                             //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-/* This is the "this error is due to be printed shortly; so have a
-   look at it any print any preamble you want" function.  Which, in
-   Ptrcheck, we don't use.  Hence a no-op.
-*/
-void pc_before_pp_Error ( const Error* err ) {
-}
-
-/* Do a printf-style operation on either the XML or normal output
-   channel, depending on the setting of VG_(clo_xml).
-*/
-static void emit_WRK ( const HChar* format, va_list vargs )
-{
-   if (VG_(clo_xml)) {
-      VG_(vprintf_xml)(format, vargs);
-   } else {
-      VG_(vmessage)(Vg_UserMsg, format, vargs);
-   }
-}
-static void emit ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
-static void emit ( const HChar* format, ... )
-{
-   va_list vargs;
-   va_start(vargs, format);
-   emit_WRK(format, vargs);
-   va_end(vargs);
-}
-static void emiN ( const HChar* format, ... ) /* With NO FORMAT CHECK */
-{
-   va_list vargs;
-   va_start(vargs, format);
-   emit_WRK(format, vargs);
-   va_end(vargs);
-}
-
-
-static const HChar* readwrite(SSizeT sszB)
-{
-   return ( sszB < 0 ? "write" : "read" );
-}
-
-static Word Word__abs ( Word w ) {
-   return w < 0 ? -w : w;
-}
-
-void pc_pp_Error ( const Error* err )
-{
-   const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
-
-   XError *xe = (XError*)VG_(get_error_extra)(err);
-   tl_assert(xe);
-
-   if (xml)
-      emit( "  <kind>%s</kind>\n", pc_get_error_name(err));
-
-   switch (VG_(get_error_kind)(err)) {
-
-   //----------------------------------------------------------
-   case XE_SorG:
-
-      if (xml) {
-
-         emit( "  <what>Invalid %s of size %ld</what>\n",
-               xe->XE.SorG.sszB < 0 ? "write" : "read",
-               Word__abs(xe->XE.SorG.sszB) );
-         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-         emit( "  <auxwhat>Address %#lx expected vs actual:</auxwhat>\n",
-               xe->XE.SorG.addr );
-         emiN( "  <auxwhat>Expected: %pS</auxwhat>\n",
-               &xe->XE.SorG.expect[0] );
-         emiN( "  <auxwhat>Actual:   %pS</auxwhat>\n", 
-               &xe->XE.SorG.actual[0] );
-
-      } else {
-
-         emit( "Invalid %s of size %ld\n", 
-               xe->XE.SorG.sszB < 0 ? "write" : "read",
-               Word__abs(xe->XE.SorG.sszB) );
-         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-         emit( " Address %#lx expected vs actual:\n", xe->XE.SorG.addr );
-         emit( " Expected: %s\n", &xe->XE.SorG.expect[0] );
-         emit( " Actual:   %s\n", &xe->XE.SorG.actual[0] );
-         if (xe->XE.SorG.delta[0] != 0)
-            emit(" Actual:   is %s Expected\n", &xe->XE.SorG.delta[0]);
-      }
-      break;
-
-   //----------------------------------------------------------
-   case XE_Heap: {
-      const HChar *place, *legit, *how_invalid;
-      Addr a    = xe->XE.Heap.addr;
-      Seg* vseg = xe->XE.Heap.vseg;
-
-      tl_assert(is_known_segment(vseg) || NONPTR == vseg);
-
-      if (NONPTR == vseg) {
-         // Access via a non-pointer
-
-         if (xml) {
-
-            emit( "  <what>Invalid %s of size %ld</what>\n",
-                  readwrite(xe->XE.Heap.sszB),
-                  Word__abs(xe->XE.Heap.sszB) );
-            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-            emit( "  <auxwhat>Address %#lx is not derived from "
-                  "any known block</auxwhat>\n", a );
-
-         } else {
-
-            emit( "Invalid %s of size %ld\n",
-                  readwrite(xe->XE.Heap.sszB),
-                  Word__abs(xe->XE.Heap.sszB) );
-            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-            emit( " Address %#lx is not derived from "
-                  "any known block\n", a );
-
-         }
-
-      } else {
-         // Access via a pointer, but outside its range.
-         Int cmp;
-         UWord miss_size;
-         Seg__cmp(vseg, a, &cmp, &miss_size);
-         if      (cmp  < 0) place = "before";
-         else if (cmp == 0) place = "inside";
-         else               place = "after";
-         how_invalid = ( ( Seg__is_freed(vseg) && 0 != cmp )
-                       ? "Doubly-invalid" : "Invalid" );
-         legit = ( Seg__is_freed(vseg) ? "once-" : "" );
-
-         if (xml) {
-
-            emit( "  <what>%s %s of size %ld</what>\n",
-                  how_invalid,
-                  readwrite(xe->XE.Heap.sszB),
-                  Word__abs(xe->XE.Heap.sszB) );
-            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-            emit( "  <auxwhat>Address %#lx is %lu bytes %s "
-                     "the accessing pointer's</auxwhat>\n",
-                  a, miss_size, place );
-            emit( "  <auxwhat>%slegitimate range, "
-                     "a block of size %lu %s</auxwhat>\n",
-                  legit, Seg__size(vseg),
-                  Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
-            VG_(pp_ExeContext)(Seg__where(vseg));
-
-         } else {
-
-            emit( "%s %s of size %ld\n",
-                  how_invalid,
-                  readwrite(xe->XE.Heap.sszB),
-                  Word__abs(xe->XE.Heap.sszB) );
-            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-            emit( " Address %#lx is %lu bytes %s the accessing pointer's\n",
-                  a, miss_size, place );
-            emit( " %slegitimate range, a block of size %lu %s\n",
-                  legit, Seg__size(vseg),
-                  Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
-            VG_(pp_ExeContext)(Seg__where(vseg));
-
-         }
-      }
-
-      /* If we have a better description of the address, show it.
-         Note that in XML mode, it will already by nicely wrapped up
-         in tags, either <auxwhat> or <xauxwhat>, so we can just emit
-         it verbatim. */
-      if (xml) {
-
-         if (xe->XE.Heap.descr1)
-            emiN( "  %pS\n",
-                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
-         if (xe->XE.Heap.descr2)
-            emiN( "  %pS\n",
-                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) );
-         if (xe->XE.Heap.datasym[0] != 0)
-            emiN( "  <auxwhat>Address 0x%llx is %llu bytes "
-                  "inside data symbol \"%pS\"</auxwhat>\n",
-                  (ULong)xe->XE.Heap.addr,
-                  (ULong)xe->XE.Heap.datasymoff,
-                  xe->XE.Heap.datasym );
-
-      } else {
-
-         if (xe->XE.Heap.descr1)
-            emit( " %s\n",
-                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
-         if (xe->XE.Heap.descr2)
-            emit( " %s\n",
-                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) ); 
-         if (xe->XE.Heap.datasym[0] != 0)
-            emit( " Address 0x%llx is %llu bytes "
-                  "inside data symbol \"%s\"\n",
-                  (ULong)xe->XE.Heap.addr,
-                  (ULong)xe->XE.Heap.datasymoff,
-                  xe->XE.Heap.datasym );
-
-      }
-      break;
-   }
-
-   //----------------------------------------------------------
-   case XE_Arith: {
-      Seg*   seg1   = xe->XE.Arith.seg1;
-      Seg*   seg2   = xe->XE.Arith.seg2;
-      const HChar*  which;
-
-      tl_assert(BOTTOM != seg1);
-      tl_assert(BOTTOM != seg2 && UNKNOWN != seg2);
-
-      if (xml) {
-
-         emit( "  <what>Invalid arguments to %s</what>\n",
-               xe->XE.Arith.opname );
-         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-         if (seg1 != seg2) {
-            if (NONPTR == seg1) {
-               emit( "  <auxwhat>First arg not a pointer</auxwhat>\n" );
-            } else if (UNKNOWN == seg1) {
-               emit( "  <auxwhat>First arg may be a pointer</auxwhat>\n" );
-            } else {
-               emit( "  <auxwhat>First arg derived from address %#lx of "
-                     "%lu-byte block alloc'd</auxwhat>\n",
-                     Seg__addr(seg1), Seg__size(seg1) );
-               VG_(pp_ExeContext)(Seg__where(seg1));
-            }
-            which = "Second arg";
-         } else {
-            which = "Both args";
-         }
-         if (NONPTR == seg2) {
-            emit( "  <auxwhat>%s not a pointer</auxwhat>\n", which );
-         } else {
-            emit( "  <auxwhat>%s derived from address %#lx of "
-                  "%lu-byte block alloc'd</auxwhat>\n",
-                  which, Seg__addr(seg2), Seg__size(seg2) );
-            VG_(pp_ExeContext)(Seg__where(seg2));
-         }
-
-      } else {
-
-         emit( "Invalid arguments to %s\n",
-               xe->XE.Arith.opname );
-         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-         if (seg1 != seg2) {
-            if (NONPTR == seg1) {
-               emit( " First arg not a pointer\n" );
-            } else if (UNKNOWN == seg1) {
-               emit( " First arg may be a pointer\n" );
-            } else {
-               emit( " First arg derived from address %#lx of "
-                     "%lu-byte block alloc'd\n",
-                     Seg__addr(seg1), Seg__size(seg1) );
-               VG_(pp_ExeContext)(Seg__where(seg1));
-            }
-            which = "Second arg";
-         } else {
-            which = "Both args";
-         }
-         if (NONPTR == seg2) {
-            emit( " %s not a pointer\n", which );
-         } else {
-            emit( " %s derived from address %#lx of "
-                  "%lu-byte block alloc'd\n",
-                  which, Seg__addr(seg2), Seg__size(seg2) );
-            VG_(pp_ExeContext)(Seg__where(seg2));
-         }
-
-      }
-
-      break;
-   }
-
-   //----------------------------------------------------------
-   case XE_SysParam: {
-      Addr  lo    = xe->XE.SysParam.lo;
-      Addr  hi    = xe->XE.SysParam.hi;
-      Seg*  seglo = xe->XE.SysParam.seglo;
-      Seg*  seghi = xe->XE.SysParam.seghi;
-      const HChar* s = VG_(get_error_string) (err);
-      const HChar* what;
-
-      tl_assert(BOTTOM != seglo && BOTTOM != seghi);
-
-      if      (Vg_CoreSysCall == xe->XE.SysParam.part) 
-                 what = "Syscall param ";
-      else    VG_(tool_panic)("bad CorePart");
-
-      if (seglo == seghi) {
-         // freed block
-         tl_assert(is_known_segment(seglo));
-         tl_assert(Seg__is_freed(seglo)); // XXX what if it's now recycled?
-
-         if (xml) {
-
-            emit( "  <what>%s%s contains unaddressable byte(s)</what>\n",
-                  what, s );
-            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-            emit( "  <auxwhat>Address %#lx is %lu bytes inside a "
-                  "%lu-byte block free'd</auxwhat>\n",
-                  lo, lo-Seg__addr(seglo), Seg__size(seglo) );
-            VG_(pp_ExeContext)(Seg__where(seglo));
-
-         } else {
-
-            emit( " %s%s contains unaddressable byte(s)\n",
-                  what, s );
-            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-            emit( " Address %#lx is %lu bytes inside a "
-                  "%lu-byte block free'd\n",
-                  lo, lo-Seg__addr(seglo), Seg__size(seglo) );
-            VG_(pp_ExeContext)(Seg__where(seglo));
-
-         }
-
-      } else {
-         // mismatch
-
-         if (xml) {
-
-            emit( "  <what>%s%s is non-contiguous</what>\n",
-                  what, s );
-            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-            if (UNKNOWN == seglo) {
-               emit( "  <auxwhat>First byte is "
-                        "not inside a known block</auxwhat>\n" );
-            } else {
-               emit( "  <auxwhat>First byte (%#lx) is %lu bytes inside a "
-                     "%lu-byte block alloc'd</auxwhat>\n",
-                     lo, lo-Seg__addr(seglo), Seg__size(seglo) );
-               VG_(pp_ExeContext)(Seg__where(seglo));
-            }
-   
-            if (UNKNOWN == seghi) {
-               emit( "  <auxwhat>Last byte is "
-                        "not inside a known block</auxwhat>\n" );
-            } else {
-               emit( "  <auxwhat>Last byte (%#lx) is %lu bytes inside a "
-                     "%lu-byte block alloc'd</auxwhat>\n",
-                     hi, hi-Seg__addr(seghi), Seg__size(seghi) );
-               VG_(pp_ExeContext)(Seg__where(seghi));
-            }
-
-         } else {
-
-            emit( "%s%s is non-contiguous\n",
-                  what, s );
-            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-   
-            if (UNKNOWN == seglo) {
-               emit( " First byte is not inside a known block\n" );
-            } else {
-               emit( " First byte (%#lx) is %lu bytes inside a "
-                     "%lu-byte block alloc'd\n",
-                     lo, lo-Seg__addr(seglo), Seg__size(seglo) );
-               VG_(pp_ExeContext)(Seg__where(seglo));
-            }
-   
-            if (UNKNOWN == seghi) {
-               emit( " Last byte is not inside a known block\n" );
-            } else {
-               emit( " Last byte (%#lx) is %lu bytes inside a "
-                     "%lu-byte block alloc'd\n",
-                     hi, hi-Seg__addr(seghi), Seg__size(seghi) );
-               VG_(pp_ExeContext)(Seg__where(seghi));
-            }
-
-         }
-
-      }
-      break;
-   }
-
-   default:
-      VG_(tool_panic)("pp_Error: unrecognised error kind");
-   }
-}
-
-
-UInt pc_update_Error_extra ( const Error* err )
-{
-   XError *xe = (XError*)VG_(get_error_extra)(err);
-   const DiEpoch ep = VG_(get_ExeContext_epoch)(VG_(get_error_where)(err));
-
-   tl_assert(xe);
-   switch (xe->tag) {
-      case XE_SorG:
-         break;
-      case XE_Heap: {
-         Bool have_descr;
-
-         xe->XE.Heap.datasymoff = 0;
-         xe->XE.Heap.datasym    = NULL;
-
-         tl_assert(!xe->XE.Heap.descr1);
-         tl_assert(!xe->XE.Heap.descr2);
-
-         xe->XE.Heap.descr1
-            = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
-                          VG_(free), sizeof(HChar) );
-         xe->XE.Heap.descr2
-            = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
-                          VG_(free), sizeof(HChar) );
-
-         xe->XE.Heap.datasymoff = 0;
-
-         have_descr
-            = VG_(get_data_description)( xe->XE.Heap.descr1,
-                                         xe->XE.Heap.descr2,
-                                         ep, xe->XE.Heap.addr );
-
-         /* If there's nothing in descr1/2, free it.  Why is it safe to
-            to VG_(indexXA) at zero here?  Because
-            VG_(get_data_description) guarantees to zero terminate
-            descr1/2 regardless of the outcome of the call.  So there's
-            always at least one element in each XA after the call.
-         */
-         if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Heap.descr1, 0 ))
-             || !have_descr) {
-            VG_(deleteXA)( xe->XE.Heap.descr1 );
-            xe->XE.Heap.descr1 = NULL;
-         }
-         if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Heap.descr2, 0 ))
-             || !have_descr) {
-            VG_(deleteXA)( xe->XE.Heap.descr2 );
-            xe->XE.Heap.descr2 = NULL;
-         }
-
-         /* If Dwarf3 info produced nothing useful, see at least if
-            we can fish something useful out of the ELF symbol info. */
-         if (!have_descr) {
-            const HChar *name;
-            if (VG_(get_datasym_and_offset)(
-                   ep, xe->XE.Heap.addr, &name,
-                   &xe->XE.Heap.datasymoff )
-               ) {
-              xe->XE.Heap.datasym =
-                 VG_(strdup)("pc.update_extra.Heap.datasym", name);
-            }
-         }
-         break;
-      }
-      case XE_Arith:
-         break;
-      case XE_SysParam:
-         break;
-      default:
-         VG_(tool_panic)("update_extra");
-   }
-   return sizeof(XError);
-}
-
-Bool pc_is_recognised_suppression ( const HChar* name, Supp *su )
-{
-   SuppKind skind;
-
-   if      (VG_STREQ(name, "SorG"))     skind = XS_SorG;
-   else if (VG_STREQ(name, "Heap"))     skind = XS_Heap;
-   else if (VG_STREQ(name, "Arith"))    skind = XS_Arith;
-   else if (VG_STREQ(name, "SysParam")) skind = XS_SysParam;
-   else
-      return False;
-
-   VG_(set_supp_kind)(su, skind);
-   return True;
-}
-
-Bool pc_read_extra_suppression_info ( Int fd, HChar** bufpp, 
-                                      SizeT* nBufp, Int* lineno,
-                                      Supp* su )
-{
-   Bool eof;
-   if (VG_(get_supp_kind)(su) == XS_SysParam) {
-      eof = VG_(get_line) ( fd, bufpp, nBufp, lineno );
-      if (eof) return False;
-      VG_(set_supp_string)(su, VG_(strdup)("pc.common.presi.1", *bufpp));
-   }
-   return True;
-}
-
-Bool pc_error_matches_suppression (const Error* err, const Supp* su)
-{
-   ErrorKind ekind = VG_(get_error_kind)(err);
-   switch (VG_(get_supp_kind)(su)) {
-      case XS_SorG:     return ekind == XE_SorG;
-      case XS_Heap:     return ekind == XE_Heap;
-      case XS_Arith:    return ekind == XE_Arith;
-      case XS_SysParam: return ekind == XE_SysParam;
-      default:
-         VG_(printf)("Error:\n"
-                     "  unknown suppression type %d\n",
-                     VG_(get_supp_kind)(su));
-         VG_(tool_panic)("unknown suppression type in "
-                         "pc_error_matches_suppression");
-   }
-}
-
-const HChar* pc_get_error_name ( const Error* err )
-{
-   XError *xe = (XError*)VG_(get_error_extra)(err);
-   tl_assert(xe);
-   switch (xe->tag) {
-      case XE_SorG:     return "SorG";
-      case XE_Heap:     return "Heap";
-      case XE_Arith:    return "Arith";
-      case XE_SysParam: return "SysParam";
-      default:          VG_(tool_panic)("get_error_name: unexpected type");
-   }
-}
-
-SizeT pc_get_extra_suppression_info ( const Error* err,
-                                      /*OUT*/HChar* buf, Int nBuf )
-{
-   ErrorKind ekind = VG_(get_error_kind)(err);
-   tl_assert(buf);
-   tl_assert(nBuf >= 1);
-
-   if (XE_SysParam == ekind) {
-      const HChar* errstr = VG_(get_error_string)(err);
-      tl_assert(errstr);
-      return VG_(snprintf)(buf, nBuf, "%s", errstr);
-   } else {
-      buf[0] = '\0';
-      return 0;
-   }
-}
-
-SizeT pc_print_extra_suppression_use ( const Supp* su,
-                                       /*OUT*/HChar* buf, Int nBuf )
-{
-   tl_assert(nBuf >= 1);
-   buf[0] = '\0';
-   return 0;
-}
-
-void pc_update_extra_suppression_use (const Error* err, const Supp* su)
-{
-   return;
-}
-
-/*--------------------------------------------------------------------*/
-/*--- end                                              pc_common.c ---*/
-/*--------------------------------------------------------------------*/
diff --git a/exp-sgcheck/pc_common.h b/exp-sgcheck/pc_common.h
deleted file mode 100644 (file)
index 5a9e149..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Ptrcheck: a pointer-use checker.                             ---*/
-/*--- Exports for stuff shared between sg_ and h_ subtools.        ---*/
-/*---                                                  pc_common.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Ptrcheck, a Valgrind tool for checking pointer
-   use in programs.
-
-   Copyright (C) 2008-2017 OpenWorks Ltd
-      info@open-works.co.uk
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef __PC_COMMON_H
-
-#define __PC_COMMON_H
-
-typedef  struct _Seg  Seg;   /* abstract every except in h_main.c */
-
-void sg_record_error_SorG ( ThreadId tid,
-                            Addr addr, SSizeT sszB,
-                            HChar* expect, HChar* actual, HChar* delta );
-
-void h_record_heap_error( Addr a, SizeT size, Seg* vseg, Bool is_write );
-
-void h_record_arith_error( Seg* seg1, Seg* seg2, HChar* opname );
-
-void h_record_sysparam_error( ThreadId tid, CorePart part, const HChar* s,
-                              Addr lo, Addr hi, Seg* seglo, Seg* seghi );
-
-Bool pc_eq_Error           ( VgRes res, const Error* e1, const Error* e2 );
-void pc_before_pp_Error    ( const Error* err );
-void pc_pp_Error           ( const Error* err );
-UInt pc_update_Error_extra ( const Error* err );
-Bool pc_is_recognised_suppression ( const HChar* name, Supp *su );
-Bool pc_read_extra_suppression_info ( Int fd, HChar** bufpp, 
-                                      SizeT* nBufp, Int* lineno, Supp* su );
-Bool pc_error_matches_suppression (const Error* err, const Supp* su);
-const HChar* pc_get_error_name ( const Error* err );
-SizeT pc_get_extra_suppression_info ( const Error* err,
-                                     /*OUT*/HChar* buf, Int nBuf );
-SizeT pc_print_extra_suppression_use ( const Supp* su,
-                                      /*OUT*/HChar* buf, Int nBuf );
-void pc_update_extra_suppression_use (const Error* err, const Supp* su);
-
-extern Bool h_clo_partial_loads_ok;
-/* extern Bool h_clo_lossage_check; */
-extern Bool sg_clo_enable_sg_checks;
-
-Bool pc_process_cmd_line_options(const HChar* arg);
-void pc_print_usage(void);
-void pc_print_debug_usage(void);
-
-
-#endif
-
-/*--------------------------------------------------------------------*/
-/*--- end                                              pc_common.h ---*/
-/*--------------------------------------------------------------------*/
diff --git a/exp-sgcheck/pc_main.c b/exp-sgcheck/pc_main.c
deleted file mode 100644 (file)
index fc13d6a..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Ptrcheck: a pointer-use checker.                             ---*/
-/*--- This file coordinates the h_ and sg_ subtools.               ---*/
-/*---                                                    pc_main.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Ptrcheck, a Valgrind tool for checking pointer
-   use in programs.
-
-   Copyright (C) 2008-2017 OpenWorks Ltd
-      info@open-works.co.uk
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-   The GNU General Public License is contained in the file COPYING.
-
-   Neither the names of the U.S. Department of Energy nor the
-   University of California nor the names of its contributors may be
-   used to endorse or promote products derived from this software
-   without prior written permission.
-*/
-
-#include "pub_tool_basics.h"
-#include "pub_tool_libcassert.h"
-#include "pub_tool_libcprint.h"
-#include "pub_tool_execontext.h"
-#include "pub_tool_tooliface.h"
-#include "pub_tool_options.h"
-
-#include "sg_main.h"
-#include "pc_common.h"
-#include "h_main.h"
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// main                                                     //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-static void pc_pre_clo_init(void)
-{
-#if defined(VGO_darwin)
-   // This makes the (all-failing) regtests run much faster.
-   VG_(printf)("SGCheck doesn't work on Darwin yet, sorry.\n");
-   VG_(exit)(1);
-#endif
-#if defined(VGA_s390x)
-   /* fixs390: to be done. */
-   VG_(printf)("SGCheck doesn't work on s390x yet, sorry.\n");
-   VG_(exit)(1);
-#endif
-#if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
-   VG_(printf)("SGCheck doesn't work on PPC yet, sorry.\n");
-   VG_(exit)(1);
-#endif
-#if defined(VGA_arm) || defined(VGA_arm64)
-   VG_(printf)("SGCheck doesn't work on ARM yet, sorry.\n");
-   VG_(exit)(1);
-#endif
-#if defined(VGA_mips32) || defined(VGA_mips64)
-   VG_(printf)("SGCheck doesn't work on MIPS yet, sorry.\n");
-   VG_(exit)(1);
-#endif
-
-   // Can't change the name until we change the names in suppressions
-   // too.
-   VG_(details_name)            ("exp-sgcheck");
-   VG_(details_version)         (NULL);
-   VG_(details_description)     ("a stack and global array "
-                                 "overrun detector");
-   VG_(details_copyright_author)(
-      "Copyright (C) 2003-2017, and GNU GPL'd, by OpenWorks Ltd et al.");
-   VG_(details_bug_reports_to)  (VG_BUGS_TO);
-   VG_(details_avg_translation_sizeB) ( 496 );
-
-   VG_(basic_tool_funcs)        (sg_post_clo_init,
-                                 h_instrument,
-                                 sg_fini);
-
-   VG_(needs_malloc_replacement)( h_replace_malloc,
-                                  h_replace___builtin_new,
-                                  h_replace___builtin_vec_new,
-                                  h_replace_memalign,
-                                  h_replace_calloc,
-                                  h_replace_free,
-                                  h_replace___builtin_delete,
-                                  h_replace___builtin_vec_delete,
-                                  h_replace_realloc,
-                                  h_replace_malloc_usable_size,
-                                  0 /* no need for client heap redzones */ );
-
-   VG_(needs_var_info)          ();
-
-   VG_(needs_core_errors)       ();
-   VG_(needs_tool_errors)       (pc_eq_Error,
-                                 pc_before_pp_Error,
-                                 pc_pp_Error,
-                                 True,/*show TIDs for errors*/
-                                 pc_update_Error_extra,
-                                 pc_is_recognised_suppression,
-                                 pc_read_extra_suppression_info,
-                                 pc_error_matches_suppression,
-                                 pc_get_error_name,
-                                 pc_get_extra_suppression_info,
-                                 pc_print_extra_suppression_use,
-                                 pc_update_extra_suppression_use);
-
-   VG_(needs_xml_output)        ();
-
-   //VG_(needs_syscall_wrapper)( h_pre_syscall,
-   //                            h_post_syscall );
-
-   VG_(needs_command_line_options)( pc_process_cmd_line_options,
-                                    pc_print_usage,
-                                    pc_print_debug_usage );
-
-   VG_(track_die_mem_stack)        ( sg_die_mem_stack );
-   VG_(track_pre_thread_ll_create) ( sg_pre_thread_ll_create );
-   VG_(track_pre_thread_first_insn)( sg_pre_thread_first_insn );
-
-   VG_(track_new_mem_mmap)         ( sg_new_mem_mmap );
-   VG_(track_new_mem_startup)      ( sg_new_mem_startup);
-   VG_(track_die_mem_munmap)       ( sg_die_mem_munmap );
-
-   /* Really we ought to give handlers for these, to
-      check that syscalls don't read across array boundaries. */
-   /*
-   VG_(track_pre_mem_read)         ( NULL );
-   VG_(track_pre_mem_read_asciiz)  ( NULL );
-   VG_(track_pre_mem_write)        ( NULL );
-   */
-
-   sg_pre_clo_init();
-
-   VG_(clo_vex_control).iropt_unroll_thresh = 0;
-   VG_(clo_vex_control).guest_chase = False;
-}
-
-VG_DETERMINE_INTERFACE_VERSION(pc_pre_clo_init)
-
-
-/*--------------------------------------------------------------------*/
-/*--- end                                                pc_main.c ---*/
-/*--------------------------------------------------------------------*/
diff --git a/exp-sgcheck/sg_main.c b/exp-sgcheck/sg_main.c
deleted file mode 100644 (file)
index 92018e4..0000000
+++ /dev/null
@@ -1,2569 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Ptrcheck: a pointer-use checker.                             ---*/
-/*--- This file checks stack and global array accesses.            ---*/
-/*---                                                    sg_main.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Ptrcheck, a Valgrind tool for checking pointer
-   use in programs.
-
-   Copyright (C) 2008-2017 OpenWorks Ltd
-      info@open-works.co.uk
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-   The GNU General Public License is contained in the file COPYING.
-
-   Neither the names of the U.S. Department of Energy nor the
-   University of California nor the names of its contributors may be
-   used to endorse or promote products derived from this software
-   without prior written permission.
-*/
-
-#include "pub_tool_basics.h"
-#include "pub_tool_libcbase.h"
-#include "pub_tool_libcassert.h"
-#include "pub_tool_libcprint.h"
-#include "pub_tool_tooliface.h"
-#include "pub_tool_wordfm.h"
-#include "pub_tool_xarray.h"
-#include "pub_tool_threadstate.h"
-#include "pub_tool_mallocfree.h"
-#include "pub_tool_machine.h"
-#include "pub_tool_debuginfo.h"
-#include "pub_tool_options.h"
-
-#include "pc_common.h"
-
-#include "sg_main.h"      // self
-
-
-static
-void preen_global_Invars ( Addr a, SizeT len ); /*fwds*/
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// Basic Stuff                                              //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-static inline Bool is_sane_TId ( ThreadId tid )
-{
-   return tid >= 0 && tid < VG_N_THREADS
-          && tid != VG_INVALID_THREADID;
-}
-
-static void* sg_malloc ( const HChar* cc, SizeT n ) {
-   void* p;
-   tl_assert(n > 0);
-   p = VG_(malloc)( cc, n );
-   return p;
-}
-
-static void sg_free ( void* p ) {
-   tl_assert(p);
-   VG_(free)(p);
-}
-
-
-/* Compare the intervals [a1,a1+n1) and [a2,a2+n2).  Return -1 if the
-   first interval is lower, 1 if the first interval is higher, and 0
-   if there is any overlap.  Redundant paranoia with casting is there
-   following what looked distinctly like a bug in gcc-4.1.2, in which
-   some of the comparisons were done signedly instead of
-   unsignedly. */
-inline
-static Word cmp_nonempty_intervals ( Addr a1, SizeT n1, 
-                                     Addr a2, SizeT n2 ) {
-   UWord a1w = (UWord)a1;
-   UWord n1w = (UWord)n1;
-   UWord a2w = (UWord)a2;
-   UWord n2w = (UWord)n2;
-   tl_assert(n1w > 0 && n2w > 0);
-   if (a1w + n1w <= a2w) return -1L;
-   if (a2w + n2w <= a1w) return 1L;
-   return 0;
-}
-
-/* Return true iff [aSmall,aSmall+nSmall) is entirely contained
-   within [aBig,aBig+nBig). */
-inline
-static Bool is_subinterval_of ( Addr aBig, SizeT nBig,
-                                Addr aSmall, SizeT nSmall ) {
-   tl_assert(nBig > 0 && nSmall > 0);
-   return aBig <= aSmall && aSmall + nSmall <= aBig + nBig;
-}
-
-inline
-static Addr Addr__min ( Addr a1, Addr a2 ) {
-   return a1 < a2 ? a1 : a2;
-}
-
-inline
-static Addr Addr__max ( Addr a1, Addr a2 ) {
-   return a1 < a2 ? a2 : a1;
-}
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// StackBlocks Persistent Cache                             //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-/* We maintain a set of XArray* of StackBlocks.  These are never
-   freed.  When a new StackBlock vector is acquired from
-   VG_(di_get_local_blocks_at_ip), we compare it to the existing set.
-   If not present, it is added.  If present, the just-acquired one is
-   freed and the copy used.
-
-   This simplifies storage management elsewhere.  It allows us to
-   assume that a pointer to an XArray* of StackBlock is valid forever.
-   It also means there are no duplicates anywhere, which could be
-   important from a space point of view for programs that generate a
-   lot of translations, or where translations are frequently discarded
-   and re-made.
-
-   Note that we normalise the arrays by sorting the elements according
-   to an arbitrary total order, so as to avoid the situation that two
-   vectors describe the same set of variables but are not structurally
-   identical. */
-
-static inline Bool StackBlock__sane ( const StackBlock* fb )
-{
-   if (fb->name[ sizeof(fb->name)-1 ] != 0)
-      return False;
-   if (fb->spRel != False && fb->spRel != True)
-      return False;
-   if (fb->isVec != False && fb->isVec != True)
-      return False;
-   return True;
-}
-
-/* Generate an arbitrary total ordering on StackBlocks. */
-static Word StackBlock__cmp ( const StackBlock* fb1, const StackBlock* fb2 )
-{
-   Word r;
-   tl_assert(StackBlock__sane(fb1));
-   tl_assert(StackBlock__sane(fb2));
-   /* Hopefully the .base test hits most of the time.  For the blocks
-      associated with any particular instruction, if the .base values
-      are the same then probably it doesn't make sense for the other
-      fields to be different.  But this is supposed to be a completely
-      general structural total order, so we have to compare everything
-      anyway. */
-   if (fb1->base < fb2->base) return -1;
-   if (fb1->base > fb2->base) return 1;
-   /* compare sizes */
-   if (fb1->szB < fb2->szB) return -1;
-   if (fb1->szB > fb2->szB) return 1;
-   /* compare sp/fp flag */
-   if (fb1->spRel < fb2->spRel) return -1;
-   if (fb1->spRel > fb2->spRel) return 1;
-   /* compare is/is-not array-typed flag */
-   if (fb1->isVec < fb2->isVec) return -1;
-   if (fb1->isVec > fb2->isVec) return 1;
-   /* compare the name */
-   r = (Word)VG_(strcmp)(fb1->name, fb2->name);
-   return r;
-}
-
-/* Returns True if all fields except .szB are the same.  szBs may or
-   may not be the same; they are simply not consulted. */
-static Bool StackBlock__all_fields_except_szB_are_equal ( 
-               StackBlock* fb1,
-               StackBlock* fb2 
-            )
-{
-   tl_assert(StackBlock__sane(fb1));
-   tl_assert(StackBlock__sane(fb2));
-   return fb1->base == fb2->base
-          && fb1->spRel == fb2->spRel
-          && fb1->isVec == fb2->isVec
-          && 0 == VG_(strcmp)(fb1->name, fb2->name);
-}
-
-
-/* Generate an arbitrary total ordering on vectors of StackBlocks. */
-static Word StackBlocks__cmp ( XArray* fb1s, XArray* fb2s )
-{
-   Word i, r, n1, n2;
-   n1 = VG_(sizeXA)( fb1s );
-   n2 = VG_(sizeXA)( fb2s );
-   if (n1 < n2) return -1;
-   if (n1 > n2) return 1;
-   for (i = 0; i < n1; i++) {
-      StackBlock *fb1, *fb2;
-      fb1 = VG_(indexXA)( fb1s, i );
-      fb2 = VG_(indexXA)( fb2s, i );
-      r = StackBlock__cmp( fb1, fb2 );
-      if (r != 0) return r;
-   }
-   tl_assert(i == n1 && i == n2);
-   return 0;
-}
-
-static void pp_StackBlocks ( XArray* sbs )
-{
-   Word i, n = VG_(sizeXA)( sbs );
-   VG_(message)(Vg_DebugMsg, "<<< STACKBLOCKS\n" );
-   for (i = 0; i < n; i++) {
-      StackBlock* sb = (StackBlock*)VG_(indexXA)( sbs, i );
-      VG_(message)(Vg_DebugMsg,
-         "   StackBlock{ off %ld szB %lu spRel:%c isVec:%c \"%s\" }\n",
-         sb->base, sb->szB, sb->spRel ? 'Y' : 'N',
-         sb->isVec ? 'Y' : 'N', &sb->name[0] 
-      );
-   }
-   VG_(message)(Vg_DebugMsg, ">>> STACKBLOCKS\n" );
-}
-
-
-/* ---------- The StackBlock vector cache ---------- */
-
-static WordFM* /* XArray* of StackBlock -> nothing */
-       frameBlocks_set = NULL;
-
-static void init_StackBlocks_set ( void )
-{
-   tl_assert(!frameBlocks_set);
-   frameBlocks_set
-      = VG_(newFM)( sg_malloc, "di.sg_main.iSBs.1", sg_free, 
-                    (Word(*)(UWord,UWord))StackBlocks__cmp );
-   tl_assert(frameBlocks_set);
-}
-
-/* Find the given StackBlock-vector in our collection thereof.  If
-   found, deallocate the supplied one, and return the address of the
-   copy.  If not found, add the supplied one to our collection and
-   return its address. */
-static XArray* /* of StackBlock */
-       StackBlocks__find_and_dealloc__or_add
-          ( XArray* /* of StackBlock */ orig )
-{
-   UWord key, val;
-
-   /* First, normalise, as per comments above. */
-   VG_(setCmpFnXA)( orig, (XACmpFn_t)StackBlock__cmp );
-   VG_(sortXA)( orig );
-
-   /* Now get rid of any exact duplicates. */
-  nuke_dups:
-   { Word r, w, nEQ, n = VG_(sizeXA)( orig );
-     if (n >= 2) {
-        w = 0;
-        nEQ = 0;
-        for (r = 0; r < n; r++) {
-           if (r+1 < n) {
-              StackBlock* pR0 = VG_(indexXA)( orig, r+0 );
-              StackBlock* pR1 = VG_(indexXA)( orig, r+1 );
-              Word c = StackBlock__cmp(pR0,pR1);
-              tl_assert(c == -1 || c == 0);
-              if (c == 0) { nEQ++; continue; }
-           }
-           if (w != r) {
-              StackBlock* pW = VG_(indexXA)( orig, w );
-              StackBlock* pR = VG_(indexXA)( orig, r );
-              *pW = *pR;
-           }
-           w++;
-        }
-        tl_assert(r == n);
-        tl_assert(w + nEQ == n);
-        if (w < n) {
-           VG_(dropTailXA)( orig, n-w );
-        }
-        if (0) VG_(printf)("delta %ld\n", n-w);
-     }
-   }
-
-   /* Deal with the following strangeness, where two otherwise
-      identical blocks are claimed to have different sizes.  In which
-      case we use the larger size. */
-   /* StackBlock{ off 16 szB 66 spRel:Y isVec:Y "sz" }
-      StackBlock{ off 16 szB 130 spRel:Y isVec:Y "sz" }
-      StackBlock{ off 208 szB 16 spRel:Y isVec:Y "ar" }
-   */
-   { Word i, n = VG_(sizeXA)( orig );
-     if (n >= 2) {
-        for (i = 0; i < n-1; i++) {
-           StackBlock* sb0 = VG_(indexXA)( orig, i+0 );
-           StackBlock* sb1 = VG_(indexXA)( orig, i+1 );
-           if (StackBlock__all_fields_except_szB_are_equal(sb0, sb1)) {
-              /* They can't be identical because the previous tidying
-                 pass would have removed the duplicates.  And they
-                 can't be > because the earlier sorting pass would
-                 have ordered otherwise-identical descriptors
-                 according to < on .szB fields.  Hence: */
-              tl_assert(sb0->szB < sb1->szB);
-              sb0->szB = sb1->szB;
-              /* This makes the blocks identical, at the size of the
-                 larger one.  Rather than go to all the hassle of
-                 sliding the rest down, simply go back to the
-                 remove-duplicates stage.  The assertion guarantees
-                 that we eventually make progress, since the rm-dups
-                 stage will get rid of one of the blocks.  This is
-                 expected to happen only exceedingly rarely. */
-              tl_assert(StackBlock__cmp(sb0,sb1) == 0);
-              goto nuke_dups;
-           }
-        }
-     }
-   }
-
-   /* If there are any blocks which overlap and have the same
-      fpRel-ness, junk the whole descriptor; it's obviously bogus.
-      Icc11 certainly generates bogus info from time to time.
-
-      This check is pretty weak; really we ought to have a stronger
-      sanity check. */
-   { Word i, n = VG_(sizeXA)( orig );
-     static Int moans = 3;
-     for (i = 0; i < n-1; i++) {
-       StackBlock* sb1 = (StackBlock*)VG_(indexXA)( orig, i );
-       StackBlock* sb2 = (StackBlock*)VG_(indexXA)( orig, i+1 );
-       if (sb1->spRel == sb2->spRel
-           && (sb1->base >= sb2->base
-               || sb1->base + sb1->szB > sb2->base)) {
-          if (moans > 0 && !VG_(clo_xml)) {
-             moans--;
-             VG_(message)(Vg_UserMsg, "Warning: bogus DWARF3 info: "
-                                      "overlapping stack blocks\n");
-             if (VG_(clo_verbosity) >= 2)
-                pp_StackBlocks(orig);
-             if (moans == 0)
-                VG_(message)(Vg_UserMsg, "Further instances of this "
-                                         "message will not be shown\n" );
-          }
-          VG_(dropTailXA)( orig, VG_(sizeXA)( orig ));
-          break;
-       }
-     }
-   }
-
-   /* Now, do we have it already? */
-   if (VG_(lookupFM)( frameBlocks_set, &key, &val, (UWord)orig )) {
-      /* yes */
-      XArray* res;
-      tl_assert(val == 0);
-      tl_assert(key != (UWord)orig);
-      VG_(deleteXA)(orig);
-      res = (XArray*)key;
-      return res;
-   } else {
-      /* no */
-      VG_(addToFM)( frameBlocks_set, (UWord)orig, 0 );
-      return orig;
-   }
-}
-
-/* Top level function for getting the StackBlock vector for a given
-   instruction.  It is guaranteed that the returned pointer will be
-   valid for the entire rest of the run, and also that the addresses
-   of the individual elements of the array will not change. */
-
-static XArray* /* of StackBlock */ get_StackBlocks_for_IP ( Addr ip )
-{
-   XArray* blocks = VG_(di_get_stack_blocks_at_ip)( ip, True/*arrays only*/ );
-   tl_assert(blocks);
-   return StackBlocks__find_and_dealloc__or_add( blocks );
-}
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// GlobalBlocks Persistent Cache                            //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-/* Generate an arbitrary total ordering on GlobalBlocks. */
-static Word GlobalBlock__cmp ( GlobalBlock* gb1, GlobalBlock* gb2 )
-{
-   Word r;
-   /* compare addrs */
-   if (gb1->addr < gb2->addr) return -1;
-   if (gb1->addr > gb2->addr) return 1;
-   /* compare sizes */
-   if (gb1->szB < gb2->szB) return -1;
-   if (gb1->szB > gb2->szB) return 1;
-   /* compare is/is-not array-typed flag */
-   if (gb1->isVec < gb2->isVec) return -1;
-   if (gb1->isVec > gb2->isVec) return 1;
-   /* compare the name */
-   r = (Word)VG_(strcmp)(gb1->name, gb2->name);
-   if (r != 0) return r;
-   /* compare the soname */
-   r = (Word)VG_(strcmp)(gb1->soname, gb2->soname);
-   return r;
-}
-
-static WordFM* /* GlobalBlock* -> nothing */
-       globalBlock_set = NULL;
-
-static void init_GlobalBlock_set ( void )
-{
-   tl_assert(!globalBlock_set);
-    globalBlock_set
-       = VG_(newFM)( sg_malloc, "di.sg_main.iGBs.1", sg_free, 
-                     (Word(*)(UWord,UWord))GlobalBlock__cmp );
-   tl_assert(globalBlock_set);
-}
-
-
-/* Top level function for making GlobalBlocks persistent.  Call here
-   with a non-persistent version, and the returned one is guaranteed
-   to be valid for the entire rest of the run.  The supplied one is
-   copied, not stored, so can be freed after the call. */
-
-static GlobalBlock* get_persistent_GlobalBlock ( GlobalBlock* orig )
-{
-   UWord key, val;
-   /* Now, do we have it already? */
-   if (VG_(lookupFM)( globalBlock_set, &key, &val, (UWord)orig )) {
-      /* yes, return the copy */
-      GlobalBlock* res;
-      tl_assert(val == 0);
-      res = (GlobalBlock*)key;
-      tl_assert(res != orig);
-      return res;
-   } else {
-      /* no.  clone it, store the clone and return the clone's
-         address. */
-      GlobalBlock* clone = sg_malloc( "di.sg_main.gpGB.1",
-                                      sizeof(GlobalBlock) );
-      tl_assert(clone);
-      *clone = *orig;
-      VG_(addToFM)( globalBlock_set, (UWord)clone, 0 );
-      return clone;
-   }
-}
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// Interval tree of StackTreeBlock                          //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-/* A node in a stack interval tree.  Zero length intervals (.szB == 0)
-   are not allowed.
-
-   A stack interval tree is a (WordFM StackTreeNode* void).  There is
-   one stack interval tree for each thread.
-*/
-typedef
-   struct {
-      Addr        addr;
-      SizeT       szB;   /* copied from .descr->szB */
-      StackBlock* descr; /* it's an instance of this block */
-      UWord       depth; /* depth of stack at time block was pushed */
-   }
-   StackTreeNode;
-
-static void pp_StackTree ( WordFM* sitree, const HChar* who )
-{
-   UWord keyW, valW;
-   VG_(printf)("<<< BEGIN pp_StackTree %s\n", who );
-   VG_(initIterFM)( sitree );
-   while (VG_(nextIterFM)( sitree, &keyW, &valW )) {
-      StackTreeNode* nd = (StackTreeNode*)keyW;
-      VG_(printf)("  [%#lx,+%lu) descr=%p %s %lu\n", nd->addr, nd->szB,
-                  nd->descr, nd->descr->name, nd->descr->szB);
-   }
-   VG_(printf)(">>> END   pp_StackTree %s\n", who );
-}
-
-/* Interval comparison function for StackTreeNode */
-static Word cmp_intervals_StackTreeNode ( StackTreeNode* sn1,
-                                          StackTreeNode* sn2 )
-{
-   return cmp_nonempty_intervals(sn1->addr, sn1->szB,
-                                 sn2->addr, sn2->szB);
-}
-
-/* Find the node holding 'a', if any. */
-static StackTreeNode* find_StackTreeNode ( WordFM* sitree, Addr a )
-{
-   UWord keyW, valW;
-   StackTreeNode key;
-   tl_assert(sitree);
-   key.addr = a;
-   key.szB  = 1;
-   if (VG_(lookupFM)( sitree, &keyW, &valW, (UWord)&key )) {
-      StackTreeNode* res = (StackTreeNode*)keyW;
-      tl_assert(valW == 0);
-      tl_assert(res != &key);
-      return res;
-   } else {
-      return NULL;
-   }
-}
-
-/* Note that the supplied XArray of FrameBlock must have been
-   made persistent already. */
-__attribute__((noinline))
-static void add_blocks_to_StackTree (
-               /*MOD*/WordFM* sitree,
-               XArray* /* FrameBlock */ descrs,
-               XArray* /* Addr */ bases,
-               UWord depth
-            )
-{
-   Bool debug = (Bool)0;
-   Word i, nDescrs, nBases;
-
-   nDescrs = VG_(sizeXA)( descrs ),
-   nBases = VG_(sizeXA)( bases );
-   tl_assert(nDescrs == nBases);
-
-   if (nDescrs == 0) return;
-
-   tl_assert(sitree);
-   if (debug) {
-      VG_(printf)("\ndepth = %lu\n", depth);
-      pp_StackTree( sitree, "add_blocks_to_StackTree-pre" );
-      pp_StackBlocks(descrs);
-   }
-
-   for (i = 0; i < nDescrs; i++) {
-      Bool already_present;
-      StackTreeNode* nyu;
-      Addr        addr  = *(Addr*)VG_(indexXA)( bases, i );
-      StackBlock* descr = (StackBlock*)VG_(indexXA)( descrs, i );
-      tl_assert(descr->szB > 0);
-      nyu = sg_malloc( "di.sg_main.abtST.1", sizeof(StackTreeNode) );
-      nyu->addr  = addr;
-      nyu->szB   = descr->szB;
-      nyu->descr = descr;
-      nyu->depth = depth;
-      if (debug) VG_(printf)("ADD %#lx %lu\n", addr, descr->szB);
-      already_present = VG_(addToFM)( sitree, (UWord)nyu, 0 );
-      /* The interval can't already be there; else we have
-         overlapping stack blocks. */
-      tl_assert(!already_present);
-      if (debug) {
-         pp_StackTree( sitree, "add_blocks_to_StackTree-step" );
-      }
-   }
-   if (debug) {
-      pp_StackTree( sitree, "add_blocks_to_StackTree-post" );
-      VG_(printf)("\n");
-   }
-}
-
-static void del_blocks_from_StackTree ( /*MOD*/WordFM* sitree,
-                                        XArray* /* Addr */ bases ) 
-{
-   UWord oldK, oldV;
-   Word i, nBases = VG_(sizeXA)( bases );
-   for (i = 0; i < nBases; i++) {
-      Bool b;
-      Addr addr = *(Addr*)VG_(indexXA)( bases, i );
-      StackTreeNode* nd = find_StackTreeNode(sitree, addr);
-      /* The interval must be there; we added it earlier when
-         the associated frame was created. */
-      tl_assert(nd);
-      b = VG_(delFromFM)( sitree, &oldK, &oldV, (UWord)nd );
-      /* we just found the block! */
-      tl_assert(b);
-      tl_assert(oldV == 0);
-      tl_assert(nd == (StackTreeNode*)oldK);
-      sg_free(nd);
-   }
-}
-
-
-static void delete_StackTree__kFin ( UWord keyW ) {
-   StackTreeNode* nd = (StackTreeNode*)keyW;
-   tl_assert(nd);
-   sg_free(nd);
-}
-static void delete_StackTree__vFin ( UWord valW ) {
-   tl_assert(valW == 0);
-}
-static void delete_StackTree ( WordFM* sitree )
-{
-   VG_(deleteFM)( sitree,
-                 delete_StackTree__kFin, delete_StackTree__vFin );
-}
-
-static WordFM* new_StackTree ( void ) {
-   return VG_(newFM)( sg_malloc, "di.sg_main.nST.1", sg_free,
-                      (Word(*)(UWord,UWord))cmp_intervals_StackTreeNode );
-}
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// Interval tree of GlobalTreeBlock                         //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-/* A node in a global interval tree.  Zero length intervals 
-   (.szB == 0) are not allowed.
-
-   A global interval tree is a (WordFM GlobalTreeNode* void).  There
-   is one global interval tree for the entire process.
-*/
-typedef
-   struct {
-      Addr         addr; /* copied from .descr->addr */
-      SizeT        szB; /* copied from .descr->szB */
-      GlobalBlock* descr; /* it's this block */
-   }
-   GlobalTreeNode;
-
-static void GlobalTreeNode__pp ( GlobalTreeNode* nd ) {
-   tl_assert(nd->descr);
-   VG_(printf)("GTNode [%#lx,+%lu) %s", 
-               nd->addr, nd->szB, nd->descr->name);
-}
-
-static void GlobalTree__pp ( WordFM* /* of (GlobalTreeNode,void) */ gitree,
-                             const HChar* who )
-{
-   UWord keyW, valW;
-   GlobalTreeNode* nd;
-   VG_(printf)("<<< GlobalBlockTree (%s)\n", who);
-   VG_(initIterFM)( gitree );
-   while (VG_(nextIterFM)( gitree, &keyW, &valW )) {
-      tl_assert(valW == 0);
-      nd = (GlobalTreeNode*)keyW;
-      VG_(printf)("  ");
-      GlobalTreeNode__pp(nd);
-      VG_(printf)("\n");
-   }
-   VG_(doneIterFM)( gitree );
-   VG_(printf)(">>>\n");
-}
-
-/* Interval comparison function for GlobalTreeNode */
-static Word cmp_intervals_GlobalTreeNode ( GlobalTreeNode* gn1,
-                                           GlobalTreeNode* gn2 )
-{
-   return cmp_nonempty_intervals( gn1->addr, gn1->szB,
-                                  gn2->addr, gn2->szB );
-}
-
-/* Find the node holding 'a', if any. */
-static GlobalTreeNode* find_GlobalTreeNode ( WordFM* gitree, Addr a )
-{
-   UWord keyW, valW;
-   GlobalTreeNode key;
-   key.addr = a;
-   key.szB  = 1;
-   if (VG_(lookupFM)( gitree, &keyW, &valW, (UWord)&key )) {
-      GlobalTreeNode* res = (GlobalTreeNode*)keyW;
-      tl_assert(valW == 0);
-      tl_assert(res != &key);
-      return res;
-   } else {
-      return NULL;
-   }
-}
-
-/* Note that the supplied GlobalBlock must have been made persistent
-   already. */
-static void add_block_to_GlobalTree (
-               /*MOD*/WordFM* gitree,
-               GlobalBlock* descr
-            )
-{
-   Bool already_present;
-   GlobalTreeNode *nyu, *nd;
-   UWord keyW, valW;
-   static Int moans = 3;
-
-   tl_assert(descr->szB > 0);
-   nyu = sg_malloc( "di.sg_main.abtG.1", sizeof(GlobalTreeNode) );
-   nyu->addr  = descr->addr;
-   nyu->szB   = descr->szB;
-   nyu->descr = descr;
-
-   /* Basically it's an error to add a global block to the tree that
-      is already in the tree.  However, detect and ignore attempts to
-      insert exact duplicates; they do appear for some reason
-      (possible a bug in m_debuginfo?) */
-   already_present = VG_(lookupFM)( gitree, &keyW, &valW, (UWord)nyu );
-   if (already_present) {
-      tl_assert(valW == 0);
-      nd = (GlobalTreeNode*)keyW;
-      tl_assert(nd);
-      tl_assert(nd != nyu);
-      tl_assert(nd->descr);
-      tl_assert(nyu->descr);
-      if (nd->addr == nyu->addr && nd->szB == nyu->szB
-          /* && 0 == VG_(strcmp)(nd->descr->name, nyu->descr->name) */
-          /* Although it seems reasonable to demand that duplicate
-             blocks have identical names, that is too strict.  For
-             example, reading debuginfo from glibc produces two
-             otherwise identical blocks with names "tzname" and
-             "__tzname".  A constraint of the form "must be identical,
-             or one must be a substring of the other" would fix that.
-             However, such trickery is scuppered by the fact that we
-             truncate all variable names to 15 characters to make
-             storage management simpler, hence giving pairs like
-             "__EI___pthread_" (truncated) vs "__pthread_keys".  So
-             it's simplest just to skip the name comparison
-             completely. */
-          && 0 == VG_(strcmp)(nd->descr->soname, nyu->descr->soname)) {
-         /* exact duplicate; ignore it */
-         sg_free(nyu);
-         return;
-      }
-      /* else fall through; the assertion below will catch it */
-   }
-
-   already_present = VG_(addToFM)( gitree, (UWord)nyu, 0 );
-   /* The interval can't already be there; else we have
-      overlapping global blocks. */
-   /* Unfortunately (25 Jan 09) at least icc11 has been seen to
-      generate overlapping block descriptions in the Dwarf3; clearly
-      bogus. */
-   if (already_present && moans > 0 && !VG_(clo_xml)) {
-      moans--;
-      VG_(message)(Vg_UserMsg, "Warning: bogus DWARF3 info: "
-                               "overlapping global blocks\n");
-      if (VG_(clo_verbosity) >= 2) {
-         GlobalTree__pp( gitree,
-                         "add_block_to_GlobalTree: non-exact duplicate" );
-         VG_(printf)("Overlapping block: ");
-         GlobalTreeNode__pp(nyu);
-         VG_(printf)("\n");
-      }
-      if (moans == 0)
-         VG_(message)(Vg_UserMsg, "Further instances of this "
-                                  "message will not be shown\n" );
-   }
-   /* tl_assert(!already_present); */
-}
-
-static Bool del_GlobalTree_range ( /*MOD*/WordFM* gitree,
-                                   Addr a, SizeT szB )
-{
-   /* One easy way to do this: look up [a,a+szB) in the tree.  That
-      will either succeed, producing a block which intersects that
-      range, in which case we delete it and repeat; or it will fail,
-      in which case there are no blocks intersecting the range, and we
-      can bring the process to a halt. */
-   UWord keyW, valW, oldK, oldV;
-   GlobalTreeNode key, *nd;
-   Bool b, anyFound;
-
-   tl_assert(szB > 0);
-
-   anyFound = False;
-
-   key.addr = a;
-   key.szB  = szB;
-
-   while (VG_(lookupFM)( gitree, &keyW, &valW, (UWord)&key )) {
-      anyFound = True;
-      nd = (GlobalTreeNode*)keyW;
-      tl_assert(valW == 0);
-      tl_assert(nd != &key);
-      tl_assert(cmp_nonempty_intervals(a, szB, nd->addr, nd->szB) == 0);
-
-      b = VG_(delFromFM)( gitree, &oldK, &oldV, (UWord)&key );
-      tl_assert(b);
-      tl_assert(oldV == 0);
-      tl_assert(oldK == keyW); /* check we deleted the node we just found */
-   }
-
-   return anyFound;
-}
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// Invar                                                    //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-/* An invariant, as resulting from watching the destination of a
-   memory referencing instruction.  Initially is Inv_Unset until the
-   instruction makes a first access. */
-
-typedef
-   enum {
-      Inv_Unset=1,  /* not established yet */
-      Inv_Unknown,  /* unknown location */
-      Inv_Stack0,   /* array-typed stack block in innermost frame */
-      Inv_StackN,   /* array-typed stack block in non-innermost frame */
-      Inv_Global,   /* array-typed global block */
-   }
-   InvarTag;
-
-typedef
-   struct {
-      InvarTag tag;
-      union {
-         struct {
-         } Unset;
-         struct {
-         } Unknown;
-         struct {
-            Addr  addr;
-            SizeT szB;
-            StackBlock* descr;
-         } Stack0; /* innermost stack frame */
-         struct {
-            /* Pointer to a node in the interval tree for
-              this thread. */
-            StackTreeNode* nd;
-         } StackN; /* non-innermost stack frame */
-         struct {
-           /* Pointer to a GlobalBlock in the interval tree of
-              global blocks. */
-           GlobalTreeNode* nd;
-         } Global;
-      }
-      Inv;
-   }
-   Invar;
-
-/* Partial debugging printing for an Invar. */
-static void pp_Invar ( Invar* i )
-{
-   switch (i->tag) {
-      case Inv_Unset: 
-         VG_(printf)("Unset");
-         break;
-      case Inv_Unknown:
-         VG_(printf)("Unknown");
-         break;
-      case Inv_Stack0:
-         VG_(printf)("Stack0 [%#lx,+%lu)",
-                     i->Inv.Stack0.addr, i->Inv.Stack0.szB);
-         break;
-      case Inv_StackN:
-         VG_(printf)("StackN [%#lx,+%lu)",
-                     i->Inv.StackN.nd->addr, i->Inv.StackN.nd->szB);
-         break;
-      case Inv_Global:
-         VG_(printf)("Global [%#lx,+%lu)",
-                     i->Inv.Global.nd->addr, i->Inv.Global.nd->szB);
-         break;
-      default:
-         tl_assert(0);
-   }
-}
-
-/* Compare two Invars for equality. */
-static Bool eq_Invar ( Invar* i1, Invar* i2 )
-{
-   if (i1->tag != i2->tag)
-      return False;
-   switch (i1->tag) {
-      case Inv_Unset:
-         return True;
-      case Inv_Unknown:
-         return True;
-      case Inv_Stack0:
-         return i1->Inv.Stack0.addr == i2->Inv.Stack0.addr
-                && i1->Inv.Stack0.szB == i2->Inv.Stack0.szB;
-      case Inv_StackN:
-         return i1->Inv.StackN.nd == i2->Inv.StackN.nd;
-      case Inv_Global:
-         return i1->Inv.Global.nd == i2->Inv.Global.nd;
-      default:
-         tl_assert(0);
-   }
-   /*NOTREACHED*/
-   tl_assert(0);
-}
-
-/* Generate a piece of text showing 'ea' is relative to 'invar', if
-   known.  If unknown, generate an empty string.  'buf' must be at
-   least 32 bytes in size.  Also return the absolute value of the
-   delta, if known, or zero if not known.
-*/
-static void gen_delta_str ( /*OUT*/HChar* buf,
-                            /*OUT*/UWord* absDelta,
-                            Invar* inv, Addr ea )
-{
-   Addr  block = 0;
-   SizeT szB   = 0;
-
-   buf[0] = 0;
-   *absDelta = 0;
-
-   switch (inv->tag) {
-      case Inv_Unknown:
-      case Inv_Unset:
-         return; /* unknown */
-      case Inv_Stack0:
-         block = inv->Inv.Stack0.addr;
-         szB   = inv->Inv.Stack0.szB;
-         break;
-      case Inv_StackN:
-         block = inv->Inv.StackN.nd->addr;
-         szB   = inv->Inv.StackN.nd->szB;
-         break;
-      case Inv_Global:
-         block = inv->Inv.Global.nd->addr;
-         szB = inv->Inv.Global.nd->szB;
-         break;
-      default:
-         tl_assert(0);
-   }
-   tl_assert(szB > 0);
-   if (ea < block) {
-      *absDelta = block - ea;
-      VG_(sprintf)(buf, "%'lu before", *absDelta);
-   }
-   else if (ea >= block + szB) {
-      *absDelta = ea - (block + szB);
-      VG_(sprintf)(buf, "%'lu after", *absDelta);
-   }
-   else {
-     // Leave *absDelta at zero.
-     VG_(sprintf)(buf, "%'lu inside", ea - block);
-   }
-}
-
-
-/* Print selected parts of an Invar, suitable for use in error
-   messages. */
-static void show_Invar( HChar* buf, Word nBuf, Invar* inv, Word depth )
-{
-   const HChar* str;
-   tl_assert(nBuf >= 128);
-   buf[0] = 0;
-   switch (inv->tag) {
-      case Inv_Unknown:
-         VG_(sprintf)(buf, "%s", "unknown");
-         break;
-      case Inv_Stack0:
-         str = "array";
-         VG_(sprintf)(buf, "stack %s \"%s\" of size %'lu in this frame",
-                      str, inv->Inv.Stack0.descr->name,
-                      inv->Inv.Stack0.szB );
-         break;
-      case Inv_StackN:
-         str = "array";
-         VG_(sprintf)(buf, "stack %s \"%s\" of size %'lu in frame %lu back from here",
-                      str, inv->Inv.StackN.nd->descr->name,
-                           inv->Inv.StackN.nd->descr->szB,
-                           depth - inv->Inv.StackN.nd->depth );
-         break;
-      case Inv_Global:
-         str = "array";
-         VG_(sprintf)(buf, "global %s \"%s\" of size %'lu in object with soname \"%s\"",
-                      str, inv->Inv.Global.nd->descr->name,
-                           inv->Inv.Global.nd->descr->szB,
-                           inv->Inv.Global.nd->descr->soname );
-         break;
-      case Inv_Unset:
-         VG_(sprintf)(buf, "%s", "Unset!");
-         break;
-      default:
-         tl_assert(0);
-   }
-}
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// our globals                                              //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-//////////////////////////////////////////////////////////////
-///
-
-#define N_QCACHE 16
-
-/* Powers of two only, else the result will be chaos */
-#define QCACHE_ADVANCE_EVERY 16
-
-/* Per-thread query cache.  Note that the invar can only be Inv_StackN
-   (but not Inv_Stack0), Inv_Global or Inv_Unknown. */
-typedef
-   struct {
-      Addr  addr;
-      SizeT szB;
-      Invar inv;
-   }
-   QCElem;
-
-typedef
-   struct {
-      Word   nInUse;
-      QCElem elems[N_QCACHE];
-   }
-   QCache;
-
-static void QCache__invalidate ( QCache* qc ) {
-   tl_assert(qc->nInUse >= 0);
-   qc->nInUse = 0;
-}
-
-static void QCache__pp ( QCache* qc, const HChar* who )
-{
-   Word i;
-   VG_(printf)("<<< QCache with %ld elements (%s)\n", qc->nInUse, who);
-   for (i = 0; i < qc->nInUse; i++) {
-      VG_(printf)("  [%#lx,+%#lx) ", qc->elems[i].addr, qc->elems[i].szB);
-      pp_Invar(&qc->elems[i].inv);
-      VG_(printf)("\n");
-   }
-   VG_(printf)(">>>\n");
-}
-
-static ULong stats__qcache_queries = 0;
-static ULong stats__qcache_misses  = 0;
-static ULong stats__qcache_probes  = 0;
-
-///
-//////////////////////////////////////////////////////////////
-
-/* Each thread has:
-   * a shadow stack of StackFrames, which is a double-linked list
-   * an stack block interval tree
-*/
-static  struct _StackFrame**         shadowStacks;
-
-static  WordFM** /* StackTreeNode */ siTrees;
-
-static  QCache*                      qcaches;
-
-
-/* Additionally, there is one global variable interval tree
-   for the entire process.
-*/
-static WordFM* /* GlobalTreeNode */ giTree;
-
-
-static void invalidate_all_QCaches ( void )
-{
-   Word i;
-   for (i = 0; i < VG_N_THREADS; i++) {
-      QCache__invalidate( &qcaches[i] );
-   }
-}
-
-static void ourGlobals_init ( void )
-{
-   Word i;
-
-   shadowStacks = sg_malloc( "di.sg_main.oGi.2",
-                             VG_N_THREADS * sizeof shadowStacks[0] );
-   siTrees = sg_malloc( "di.sg_main.oGi.3", VG_N_THREADS * sizeof siTrees[0] );
-   qcaches = sg_malloc( "di.sg_main.oGi.4", VG_N_THREADS * sizeof qcaches[0] );
-
-   for (i = 0; i < VG_N_THREADS; i++) {
-      shadowStacks[i] = NULL;
-      siTrees[i] = NULL;
-      qcaches[i] = (QCache){};
-   }
-   invalidate_all_QCaches();
-   giTree = VG_(newFM)( sg_malloc, "di.sg_main.oGi.1", sg_free, 
-                        (Word(*)(UWord,UWord))cmp_intervals_GlobalTreeNode );
-}
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// Handle global variable load/unload events                //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-static void acquire_globals ( ULong di_handle )
-{
-   Word n, i;
-   XArray* /* of GlobalBlock */ gbs;
-   if (0) VG_(printf)("ACQUIRE GLOBALS %llu\n", di_handle );
-   gbs = VG_(di_get_global_blocks_from_dihandle)
-            (di_handle, True/*arrays only*/);
-   if (0) VG_(printf)("   GOT %ld globals\n", VG_(sizeXA)( gbs ));
-
-   n = VG_(sizeXA)( gbs );
-   for (i = 0; i < n; i++) {
-      GlobalBlock* gbp;
-      GlobalBlock* gb = VG_(indexXA)( gbs, i );
-      if (0) VG_(printf)("   new Global size %2lu at %#lx:  %s %s\n", 
-                         gb->szB, gb->addr, gb->soname, gb->name );
-      tl_assert(gb->szB > 0);
-      /* Make a persistent copy of each GlobalBlock, and add it
-         to the tree. */
-      gbp = get_persistent_GlobalBlock( gb );
-      add_block_to_GlobalTree( giTree, gbp );
-   }
-
-   VG_(deleteXA)( gbs );
-}
-
-
-/* We only intercept these two because we need to see any di_handles
-   that might arise from the mappings/allocations. */
-void sg_new_mem_mmap( Addr a, SizeT len,
-                      Bool rr, Bool ww, Bool xx, ULong di_handle )
-{
-   if (di_handle > 0)
-      acquire_globals(di_handle);
-}
-void sg_new_mem_startup( Addr a, SizeT len,
-                         Bool rr, Bool ww, Bool xx, ULong di_handle )
-{
-   if (di_handle > 0)
-      acquire_globals(di_handle);
-}
-void sg_die_mem_munmap ( Addr a, SizeT len )
-{
-   Bool debug = (Bool)0;
-   Bool overlap = False;
-
-   if (debug) VG_(printf)("MUNMAP %#lx %lu\n", a, len );
-
-   if (len == 0)
-      return;
-
-   overlap = del_GlobalTree_range(giTree, a, len);
-
-   { /* redundant sanity check */
-     UWord keyW, valW;
-     VG_(initIterFM)( giTree );
-     while (VG_(nextIterFM)( giTree, &keyW, &valW )) {
-       GlobalTreeNode* nd = (GlobalTreeNode*)keyW;
-        tl_assert(valW == 0);
-        tl_assert(nd->szB > 0);
-        tl_assert(nd->addr + nd->szB <= a
-                  || a + len <= nd->addr);
-     }
-     VG_(doneIterFM)( giTree );
-   }
-
-   if (!overlap)
-      return;
-
-   /* Ok, the range contained some blocks.  Therefore we'll need to
-      visit all the Invars in all the thread shadow stacks, and
-      convert all Inv_Global entries that intersect [a,a+len) to
-      Inv_Unknown. */
-   tl_assert(len > 0);
-   preen_global_Invars( a, len );
-   invalidate_all_QCaches();
-}
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// StackFrame                                               //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-static ULong stats__total_accesses   = 0;
-static ULong stats__classify_Stack0  = 0;
-static ULong stats__classify_StackN  = 0;
-static ULong stats__classify_Global  = 0;
-static ULong stats__classify_Unknown = 0;
-static ULong stats__Invars_preened   = 0;
-static ULong stats__Invars_changed   = 0;
-static ULong stats__t_i_b_empty      = 0;
-static ULong stats__htab_fast        = 0;
-static ULong stats__htab_searches    = 0;
-static ULong stats__htab_probes      = 0;
-static ULong stats__htab_resizes     = 0;
-
-
-/* A dynamic instance of an instruction */
-typedef
-   struct {
-      /* IMMUTABLE */
-      Addr    insn_addr; /* NB! zero means 'not in use' */
-      XArray* blocks; /* XArray* of StackBlock, or NULL if none */
-      /* MUTABLE */
-      Invar invar;
-   }
-   IInstance;
-
-
-#define N_HTAB_FIXED 64
-
-typedef
-   struct _StackFrame {
-      /* The sp when the frame was created, so we know when to get rid
-         of it. */
-      Addr creation_sp;
-      /* The stack frames for a thread are arranged as a doubly linked
-         list.  Obviously the outermost frame in the stack has .outer
-         as NULL and the innermost in theory has .inner as NULL.
-         However, when a function returns, we don't delete the
-         just-vacated StackFrame.  Instead, it is retained in the list
-         and will be re-used when the next call happens.  This is so
-         as to avoid constantly having to dynamically allocate and
-         deallocate frames. */
-      struct _StackFrame* inner;
-      struct _StackFrame* outer;
-      Word depth; /* 0 for outermost; increases inwards */
-      /* Information for each memory referencing instruction, for this
-         instantiation of the function.  The iinstances array is
-         operated as a simple linear-probe hash table, which is
-         dynamically expanded as necessary.  Once critical thing is
-         that an IInstance with a .insn_addr of zero is interpreted to
-         mean that hash table slot is unused.  This means we can't
-         store an IInstance for address zero. */
-      /* Note that htab initially points to htab_fixed.  If htab_fixed
-         turns out not to be big enough then htab is made to point to
-         dynamically allocated memory.  But it's often the case that
-         htab_fixed is big enough, so this optimisation saves a huge
-         number of sg_malloc/sg_free call pairs. */
-      IInstance* htab;
-      UWord      htab_size; /* size of hash table, MAY ONLY BE A POWER OF 2 */
-      UWord      htab_used; /* number of hash table slots currently in use */
-      /* If this frame is currently making a call, then the following
-         are relevant. */
-      Addr sp_at_call;
-      Addr fp_at_call;
-      XArray* /* of Addr */ blocks_added_by_call;
-      /* See comment just above */
-      IInstance htab_fixed[N_HTAB_FIXED];
-   }
-   StackFrame;
-
-
-
-
-
-/* Move this somewhere else? */
-/* Visit all Invars in the entire system.  If 'isHeap' is True, change
-   all Inv_Heap Invars that intersect [a,a+len) to Inv_Unknown.  If
-   'isHeap' is False, do the same but to the Inv_Global{S,V} Invars
-   instead. */
-
-__attribute__((noinline))
-static void preen_global_Invar ( Invar* inv, Addr a, SizeT len )
-{
-   stats__Invars_preened++;
-   tl_assert(len > 0);
-   tl_assert(inv);
-   switch (inv->tag) {
-      case Inv_Global:
-         tl_assert(inv->Inv.Global.nd);
-         tl_assert(inv->Inv.Global.nd->szB > 0);
-         if (0) VG_(printf)("preen_Invar Global %#lx %lu\n",
-                            inv->Inv.Global.nd->addr,
-                            inv->Inv.Global.nd->szB);
-         if (0 == cmp_nonempty_intervals(a, len, inv->Inv.Global.nd->addr,
-                                                 inv->Inv.Global.nd->szB)) {
-            inv->tag = Inv_Unknown;
-            stats__Invars_changed++;
-         }
-         break;
-      case Inv_Stack0:
-      case Inv_StackN:
-      case Inv_Unknown:
-         break;
-      case Inv_Unset: /* this should never happen */
-         /* fallthrough */
-      default:
-         tl_assert(0);
-   }
-}
-
-__attribute__((noinline))
-static void preen_global_Invars ( Addr a, SizeT len )
-{
-   Int         i;
-   UWord       u;
-   StackFrame* frame;
-   tl_assert(len > 0);
-   for (i = 0; i < VG_N_THREADS; i++) {
-      frame = shadowStacks[i];
-      if (!frame)
-         continue; /* no frames for this thread */
-      /* start from the innermost frame */
-      while (frame->inner)
-         frame = frame->inner;
-      tl_assert(frame->outer);
-      /* work through the frames from innermost to outermost.  The
-         order isn't important; we just need to ensure we visit each
-         frame once (including those which are not actually active,
-         more 'inner' than the 'innermost active frame', viz, just
-         hanging around waiting to be used, when the current innermost
-         active frame makes more calls.  See comments on definition of
-         struct _StackFrame. */
-      for (; frame; frame = frame->outer) {
-         UWord xx = 0; /* sanity check only; count of used htab entries */
-         if (!frame->htab)
-            continue; /* frame not in use.  See shadowStack_unwind(). */
-         for (u = 0; u < frame->htab_size; u++) {
-            IInstance* ii = &frame->htab[u];
-            if (ii->insn_addr == 0)
-               continue; /* not in use */
-            if (0) { pp_Invar(&ii->invar); VG_(printf)(" x\n"); }
-            preen_global_Invar( &ii->invar, a, len );
-            xx++;           
-         }
-         tl_assert(xx == frame->htab_used);
-      }
-   }
-}
-
-
-/* XXX this should be >> 2 on ppc32/64 since the bottom two bits
-   of the ip are guaranteed to be zero */
-inline static UWord compute_II_hash ( Addr ip, UWord htab_size ) {
-   return (ip >> 0) & (htab_size - 1);
-}
-
-__attribute__((noinline))
-static void initialise_II_hash_table ( StackFrame* sf )
-{
-   UWord i;
-   sf->htab_size = N_HTAB_FIXED; /* initial hash table size */
-   sf->htab = &sf->htab_fixed[0];
-   tl_assert(sf->htab);
-   sf->htab_used = 0;
-   for (i = 0; i < sf->htab_size; i++)
-      sf->htab[i].insn_addr = 0; /* NOT IN USE */
-}
-
-
-__attribute__((noinline))
-static void resize_II_hash_table ( StackFrame* sf )
-{
-   UWord     i, j, ix, old_size, new_size;
-   IInstance *old_htab, *new_htab, *old;
-
-   tl_assert(sf && sf->htab);
-   old_size = sf->htab_size;
-   new_size = 2 * old_size;
-   old_htab = sf->htab;
-   new_htab = sg_malloc( "di.sg_main.rIht.1",
-                         new_size * sizeof(IInstance) );
-   for (i = 0; i < new_size; i++) {
-      new_htab[i].insn_addr = 0; /* NOT IN USE */
-   }
-   for (i = 0; i < old_size; i++) {
-      old = &old_htab[i];
-      if (old->insn_addr == 0 /* NOT IN USE */)
-         continue;
-      ix = compute_II_hash(old->insn_addr, new_size);
-      /* find out where to put this, in the new table */
-      j = new_size;
-      while (1) {
-         if (new_htab[ix].insn_addr == 0)
-            break;
-         /* This can't ever happen, because it would mean the new
-            table is full; that isn't allowed -- even the old table is
-            only allowed to become half full. */
-         tl_assert(j > 0);
-         j--;
-         ix++; if (ix == new_size) ix = 0;
-      }
-      /* copy the old entry to this location */
-      tl_assert(ix < new_size);
-      tl_assert(new_htab[ix].insn_addr == 0);
-      new_htab[ix] = *old;
-      tl_assert(new_htab[ix].insn_addr != 0);
-   }
-   /* all entries copied; free old table. */
-   if (old_htab != &sf->htab_fixed[0])
-      sg_free(old_htab);
-   sf->htab = new_htab;
-   sf->htab_size = new_size;
-   /* check sf->htab_used is correct.  Optional and a bit expensive
-      but anyway: */
-   j = 0;
-   for (i = 0; i < new_size; i++) {
-      if (new_htab[i].insn_addr != 0) {
-         j++;
-      }
-   }
-   tl_assert(j == sf->htab_used);
-   if (0) VG_(printf)("resized tab for SF %p to %lu\n", sf, new_size);
-}
-
-
-__attribute__((noinline))
-static IInstance* find_or_create_IInstance_SLOW (
-                     StackFrame* sf, 
-                     Addr ip,
-                     XArray* /* StackBlock */ ip_frameblocks
-                  )
-{
-   UWord i, ix;
-
-   stats__htab_searches++;
-
-   tl_assert(sf);
-   tl_assert(sf->htab);
-
-   /* Make sure the table loading doesn't get too high. */
-   if (UNLIKELY(2 * sf->htab_used >= 1 * sf->htab_size)) {
-      stats__htab_resizes++;
-      resize_II_hash_table(sf);
-   }
-   tl_assert(2 * sf->htab_used <= sf->htab_size);
-  
-   ix = compute_II_hash(ip, sf->htab_size);
-   i = sf->htab_size;
-   while (1) {
-      stats__htab_probes++;
-      /* Note that because of the way the fast-case handler works,
-         these two tests are actually redundant in the first iteration
-         of this loop.  (Except they aren't redundant if the code just
-         above resized the table first. :-) */
-      if (sf->htab[ix].insn_addr == ip)
-         return &sf->htab[ix];
-      if (sf->htab[ix].insn_addr == 0)
-         break;
-      /* If i ever gets to zero and we have found neither what we're
-         looking for nor an empty slot, the table must be full.  Which
-         isn't possible -- we monitor the load factor to ensure it
-         doesn't get above say 50%; if that ever does happen the table
-         is resized. */
-      tl_assert(i > 0);
-      i--;
-      ix++;
-      if (ix == sf->htab_size) ix = 0;
-   }
-
-   /* So now we've found a free slot at ix, and we can use that. */
-   tl_assert(sf->htab[ix].insn_addr == 0);
-
-   /* Add a new record in this slot. */
-   tl_assert(ip != 0); /* CAN'T REPRESENT THIS */
-   sf->htab[ix].insn_addr = ip;
-   sf->htab[ix].blocks    = ip_frameblocks;
-   sf->htab[ix].invar.tag = Inv_Unset;
-   sf->htab_used++;
-   return &sf->htab[ix];
-}
-
-
-inline
-static IInstance* find_or_create_IInstance (
-                     StackFrame* sf, 
-                     Addr ip,
-                     XArray* /* StackBlock */ ip_frameblocks
-                  )
-{
-   UWord ix = compute_II_hash(ip, sf->htab_size);
-   /* Is it in the first slot we come to? */
-   if (LIKELY(sf->htab[ix].insn_addr == ip)) {
-      stats__htab_fast++;
-      return &sf->htab[ix];
-   }
-   /* If the first slot we come to is empty, bag it. */
-   if (LIKELY(sf->htab[ix].insn_addr == 0)) {
-      stats__htab_fast++;
-      tl_assert(ip != 0);
-      sf->htab[ix].insn_addr = ip;
-      sf->htab[ix].blocks    = ip_frameblocks;
-      sf->htab[ix].invar.tag = Inv_Unset;
-      sf->htab_used++;
-      return &sf->htab[ix];
-   }
-   /* Otherwise we hand off to the slow case, which searches other
-      slots, and optionally resizes the table if necessary. */
-   return find_or_create_IInstance_SLOW( sf, ip, ip_frameblocks );
-}
-
-
-__attribute__((noinline))
-static Addr calculate_StackBlock_EA ( StackBlock* descr,
-                                      Addr sp, Addr fp ) {
-   UWord w1 = (UWord)descr->base;
-   UWord w2 = (UWord)(descr->spRel ? sp : fp);
-   UWord ea = w1 + w2;
-   return ea;
-}
-
-/* Given an array of StackBlocks, return an array of Addrs, holding
-   their effective addresses.  Caller deallocates result array. */
-__attribute__((noinline))
-static XArray* /* Addr */ calculate_StackBlock_EAs (
-                             XArray* /* StackBlock */ blocks,
-                             Addr sp, Addr fp
-                          )
-{
-   XArray* res;
-   Word i, n = VG_(sizeXA)( blocks );
-   tl_assert(n > 0);
-   res = VG_(newXA)( sg_malloc, "di.sg_main.cSBE.1", sg_free, sizeof(Addr) );
-   for (i = 0; i < n; i++) {
-      StackBlock* blk = VG_(indexXA)( blocks, i );
-      Addr ea = calculate_StackBlock_EA( blk, sp, fp );
-      VG_(addToXA)( res, &ea );
-   }
-   return res;
-}
-
-
-/* Try to classify the block into which a memory access falls, and
-   write the result in 'inv'.  This writes all relevant fields of
-   'inv'. */
-__attribute__((noinline)) 
-static void classify_address ( /*OUT*/Invar* inv,
-                               ThreadId tid,
-                               Addr ea, Addr sp, Addr fp,
-                               UWord szB,
-                               XArray* /* of StackBlock */ thisInstrBlocks )
-{
-   tl_assert(szB > 0);
-   /* First, look in the stack blocks accessible in this instruction's
-      frame. */
-   { 
-     Word i, nBlocks = VG_(sizeXA)( thisInstrBlocks );
-     if (nBlocks == 0) stats__t_i_b_empty++;
-     for (i = 0; i < nBlocks; i++) {
-        StackBlock* descr = VG_(indexXA)( thisInstrBlocks, i );
-        Addr bea = calculate_StackBlock_EA( descr, sp, fp );
-        if (bea <= ea && ea + szB <= bea + descr->szB) {
-           /* found it */
-           inv->tag = Inv_Stack0;
-           inv->Inv.Stack0.addr  = bea;
-           inv->Inv.Stack0.szB   = descr->szB;
-           inv->Inv.Stack0.descr = descr;
-           stats__classify_Stack0++;
-           return;
-        }
-     }
-   }
-   /* Look in this thread's query cache */
-   { Word i;
-     QCache* cache = &qcaches[tid];
-     static UWord ctr = 0;
-     stats__qcache_queries++;
-     for (i = 0; i < cache->nInUse; i++) {
-        if (0) /* expensive in a loop like this */
-               tl_assert(cache->elems[i].addr + cache->elems[i].szB != 0);
-        stats__qcache_probes++;
-        if (is_subinterval_of(cache->elems[i].addr,
-                              cache->elems[i].szB, ea, szB)) {
-           if (i > 0
-               && (ctr++ & (QCACHE_ADVANCE_EVERY-1)) == 0) {
-              QCElem tmp;
-              tmp = cache->elems[i-1];
-              cache->elems[i-1] = cache->elems[i];
-              cache->elems[i] = tmp;
-              i--;
-           }
-           *inv = cache->elems[i].inv;
-           return;
-        }
-     }
-     stats__qcache_misses++;
-   }
-   /* Ok, so it's not a block in the top frame.  Perhaps it's a block
-      in some calling frame?  Consult this thread's stack-block
-      interval tree to find out. */
-   { StackTreeNode* nd = find_StackTreeNode( siTrees[tid], ea );
-     /* We know that [ea,ea+1) is in the block, but we need to
-        restrict to the case where the whole access falls within
-        it. */
-     if (nd && !is_subinterval_of(nd->addr, nd->szB, ea, szB)) {
-        nd = NULL;
-     }
-     if (nd) {
-        /* found it */
-        inv->tag = Inv_StackN;
-        inv->Inv.StackN.nd = nd;
-        stats__classify_StackN++;
-        goto out;
-     }
-   }
-   /* Not in a stack block.  Try the global pool. */
-   { GlobalTreeNode* nd = find_GlobalTreeNode(giTree, ea);
-     /* We know that [ea,ea+1) is in the block, but we need to
-        restrict to the case where the whole access falls within
-        it. */
-     if (nd && !is_subinterval_of(nd->addr, nd->szB, ea, szB)) {
-        nd = NULL;
-     }
-     if (nd) {
-        /* found it */
-        inv->tag = Inv_Global;
-        inv->Inv.Global.nd = nd;
-        stats__classify_Global++;
-        goto out;
-     }
-   }
-   /* No idea - give up. */
-   inv->tag = Inv_Unknown;
-   stats__classify_Unknown++;
-
-   /* Update the cache */
-  out:
-   { Addr    toadd_addr = 0;
-     SizeT   toadd_szB  = 0;
-     QCache* cache      = &qcaches[tid];
-
-     static UWord ctr = 0;
-     Bool show = False;
-     if (0 && 0 == (ctr++ & 0x1FFFFF)) show = True;
-
-     if (show) QCache__pp(cache, "before upd");
-
-     switch (inv->tag) {
-        case Inv_Global:
-           toadd_addr = inv->Inv.Global.nd->addr;
-           toadd_szB  = inv->Inv.Global.nd->szB;
-           break;
-        case Inv_StackN:
-           toadd_addr = inv->Inv.StackN.nd->addr;
-           toadd_szB  = inv->Inv.StackN.nd->szB;
-           break;
-        case Inv_Unknown: {
-           /* This is more complex.  We need to figure out the
-              intersection of the "holes" in the global and stack
-              interval trees into which [ea,ea+szB) falls.  This is
-              further complicated by the fact that [ea,ea+szB) might
-              not fall cleanly into a hole; it may instead fall across
-              the boundary of a stack or global block.  In that case
-              we just ignore it and don't update the cache, since we
-              have no way to represent this situation precisely. */
-           StackTreeNode  sNegInf, sPosInf, sKey, *sLB, *sUB;
-           GlobalTreeNode gNegInf, gPosInf, gKey, *gLB, *gUB;
-           Addr gMin, gMax, sMin, sMax, uMin, uMax;
-           Bool sOK, gOK;
-           sNegInf.addr = 0;
-           sNegInf.szB  = 1;
-           sPosInf.addr = ~(UWord)0;
-           sPosInf.szB  = 1;
-           gNegInf.addr = 0;
-           gNegInf.szB  = 1;
-           gPosInf.addr = ~(UWord)0;
-           gPosInf.szB  = 1;
-           sKey.addr = ea;
-           sKey.szB  = szB;
-           gKey.addr = ea;
-           gKey.szB  = szB;
-           if (0) VG_(printf)("Tree sizes %lu %lu\n",
-                              VG_(sizeFM)(siTrees[tid]), VG_(sizeFM)(giTree));
-           sOK = VG_(findBoundsFM)( siTrees[tid], 
-                                    (UWord*)&sLB,    NULL/*unused*/,
-                                    (UWord*)&sUB,    NULL/*unused*/,
-                                    (UWord)&sNegInf, 0/*unused*/,
-                                    (UWord)&sPosInf, 0/*unused*/,
-                                    (UWord)&sKey );
-           gOK = VG_(findBoundsFM)( giTree,
-                                    (UWord*)&gLB,    NULL/*unused*/,
-                                    (UWord*)&gUB,    NULL/*unused*/,
-                                    (UWord)&gNegInf, 0/*unused*/,
-                                    (UWord)&gPosInf, 0/*unused*/,
-                                    (UWord)&gKey );
-           if (!(sOK && gOK)) {
-              /* If this happens, then [ea,ea+szB) partially overlaps
-                 a heap or stack block.  We can't represent that, so
-                 just forget it (should be very rare).  However, do
-                 maximum sanity checks first.  In such a
-                 partial overlap case, it can't be the case that both
-                 [ea] and [ea+szB-1] overlap the same block, since if
-                 that were indeed the case then it wouldn't be a
-                 partial overlap; rather it would simply fall inside
-                 that block entirely and we shouldn't be inside this
-                 conditional at all. */
-              if (!sOK) {
-                 StackTreeNode *ndFirst, *ndLast;
-                 ndFirst = find_StackTreeNode( siTrees[tid], ea );
-                 ndLast  = find_StackTreeNode( siTrees[tid], ea+szB-1 );
-                 /* if both ends of the range fall inside a block,
-                    they can't be in the same block. */
-                 if (ndFirst && ndLast)
-                    tl_assert(ndFirst != ndLast);
-                 /* for each end of the range, if it is in a block,
-                    the range as a whole can't be entirely within the
-                    block. */
-                 if (ndFirst)
-                    tl_assert(!is_subinterval_of(ndFirst->addr,
-                                                 ndFirst->szB, ea, szB));
-                 if (ndLast)
-                    tl_assert(!is_subinterval_of(ndLast->addr,
-                                                 ndLast->szB, ea, szB));
-              }
-              if (!gOK) {
-                 GlobalTreeNode *ndFirst, *ndLast;
-                 ndFirst = find_GlobalTreeNode( giTree, ea );
-                 ndLast  = find_GlobalTreeNode( giTree, ea+szB-1 );
-                 /* if both ends of the range fall inside a block,
-                    they can't be in the same block. */
-                 if (ndFirst && ndLast)
-                    tl_assert(ndFirst != ndLast);
-                 /* for each end of the range, if it is in a block,
-                    the range as a whole can't be entirely within the
-                    block. */
-                 if (ndFirst)
-                    tl_assert(!is_subinterval_of(ndFirst->addr,
-                                                 ndFirst->szB, ea, szB));
-                 if (ndLast)
-                    tl_assert(!is_subinterval_of(ndLast->addr,
-                                                 ndLast->szB, ea, szB));
-              }
-              if (0) VG_(printf)("overlapping blocks in cache\n");
-              return;
-           }
-           sMin = sLB == &sNegInf  ? 0         : (sLB->addr + sLB->szB);
-           sMax = sUB == &sPosInf  ? ~(UWord)0 : (sUB->addr - 1);
-           gMin = gLB == &gNegInf  ? 0         : (gLB->addr + gLB->szB);
-           gMax = gUB == &gPosInf  ? ~(UWord)0 : (gUB->addr - 1);
-           if (0) VG_(printf)("sMin %lx sMax %lx gMin %lx gMax %lx\n",
-                              sMin, sMax, gMin, gMax);
-           /* [sMin,sMax] and [gMin,gMax] must both contain
-              [ea,ea+szB) (right?)  That implies they must overlap at
-              at least over [ea,ea+szB). */
-           tl_assert(sMin <= ea && ea+szB-1 <= sMax);
-           tl_assert(gMin <= ea && ea+szB-1 <= gMax);
-           /* So now compute their intersection. */
-           uMin = Addr__max( sMin, gMin );
-           uMax = Addr__min( sMax, gMax );
-           if (0) VG_(printf)("uMin %lx uMax %lx\n", uMin, uMax);
-           tl_assert(uMin <= uMax);
-           tl_assert(uMin <= ea && ea+szB-1 <= uMax);
-           /* Finally, we can park [uMin,uMax] in the cache.  However,
-              if uMax is ~0, we can't represent the difference; hence
-              fudge uMax. */
-           if (uMin < uMax && uMax == ~(UWord)0)
-              uMax--;
-           toadd_addr = uMin;
-           toadd_szB  = uMax - uMin + 1;
-           break;
-        }
-        default:
-           /* We should only be caching info for the above 3 cases */
-          tl_assert(0);
-     } /* switch (inv->tag) */
-
-     { /* and actually add this to the cache, finally */
-       Word i;
-       Word ip = cache->nInUse / 2; /* doesn't seem critical */
-
-       if (cache->nInUse < N_QCACHE)
-          cache->nInUse++;
-       for (i = cache->nInUse-1; i > ip; i--) {
-          cache->elems[i] = cache->elems[i-1];
-       }
-
-       tl_assert(toadd_szB > 0);
-       cache->elems[ip].addr = toadd_addr;
-       cache->elems[ip].szB  = toadd_szB;
-       cache->elems[ip].inv  = *inv;
-     }
-
-     if (show) QCache__pp(cache, "after upd");
-
-   }
-}
-
-
-/* CALLED FROM GENERATED CODE */
-static 
-VG_REGPARM(3)
-void helperc__mem_access ( /* Known only at run time: */
-                           Addr ea, Addr sp, Addr fp,
-                           /* Known at translation time: */
-                           Word sszB, Addr ip, XArray* ip_frameBlocks )
-{
-   UWord szB;
-   IInstance* iinstance;
-   Invar* inv;
-   Invar new_inv;
-   ThreadId tid = VG_(get_running_tid)();
-   StackFrame* frame;
-   HChar bufE[160], bufA[160], bufD[32];
-
-   stats__total_accesses++;
-
-   tl_assert(is_sane_TId(tid));
-   frame = shadowStacks[tid];
-   tl_assert(frame);
-
-   /* Find the instance info for this instruction. */
-   tl_assert(ip_frameBlocks);
-   iinstance = find_or_create_IInstance( frame, ip, ip_frameBlocks );
-   tl_assert(iinstance);
-   tl_assert(iinstance->blocks == ip_frameBlocks);
-
-   szB = (sszB < 0) ? (-sszB) : sszB;
-   tl_assert(szB > 0);
-
-   inv = &iinstance->invar;
-
-   /* Deal with first uses of instruction instances. */
-   if (inv->tag == Inv_Unset) {
-      /* This is the first use of this instance of the instruction, so
-         we can't make any check; we merely record what we saw, so we
-         can compare it against what happens for 2nd and subsequent
-         accesses. */
-      classify_address( inv,
-                        tid, ea, sp, fp, szB, iinstance->blocks );
-      tl_assert(inv->tag != Inv_Unset);
-      return;
-   }
-
-   /* So generate an Invar and see if it's different from what
-      we had before. */
-   classify_address( &new_inv,
-                     tid, ea, sp, fp, szB, iinstance->blocks );
-   tl_assert(new_inv.tag != Inv_Unset);
-
-   /* Did we see something different from before?  If no, then there's
-      no error. */
-   tl_assert(inv->tag != Inv_Unset);
-
-   if (LIKELY(eq_Invar(&new_inv, inv)))
-      return;
-
-   VG_(memset)(bufE, 0, sizeof(bufE));
-   show_Invar( bufE, sizeof(bufE)-1, inv, frame->depth );
-
-   VG_(memset)(bufA, 0, sizeof(bufA));
-   show_Invar( bufA, sizeof(bufA)-1, &new_inv, frame->depth );
-
-   VG_(memset)(bufD, 0, sizeof(bufD));
-   UWord absDelta;
-   gen_delta_str( bufD, &absDelta, inv, ea );
-
-   if (absDelta < 1024)
-      sg_record_error_SorG( tid, ea, sszB, bufE, bufA, bufD );
-
-   /* And now install the new observation as "standard", so as to
-      make future error messages make more sense. */
-   *inv = new_inv;
-}
-
-
-////////////////////////////////////////
-/* Primary push-a-new-frame routine.  Called indirectly from
-   generated code. */
-
-static UWord stats__max_sitree_size = 0;
-static UWord stats__max_gitree_size = 0;
-
-static
-void shadowStack_new_frame ( ThreadId tid,
-                             Addr     sp_at_call_insn,
-                             Addr     sp_post_call_insn,
-                             Addr     fp_at_call_insn,
-                             Addr     ip_post_call_insn,
-                             XArray*  descrs_at_call_insn )
-{
-   StackFrame *callee, *caller;
-   tl_assert(is_sane_TId(tid));
-
-   caller = shadowStacks[tid];
-   tl_assert(caller);
-
-   if (caller->outer) { /* "this is not the outermost frame" */
-      tl_assert(caller->outer->inner == caller);
-      tl_assert(caller->outer->depth >= 0);
-      tl_assert(1 + caller->outer->depth == caller->depth);
-   } else {
-      tl_assert(caller->depth == 0);
-   }
-
-   caller->sp_at_call = sp_at_call_insn;
-   caller->fp_at_call = fp_at_call_insn;
-
-   if (descrs_at_call_insn) {
-      tl_assert( VG_(sizeXA)(descrs_at_call_insn) > 0 );
-      caller->blocks_added_by_call
-         = calculate_StackBlock_EAs( descrs_at_call_insn,
-                                     sp_at_call_insn, fp_at_call_insn );
-      if (caller->blocks_added_by_call)
-         add_blocks_to_StackTree( siTrees[tid], 
-                                  descrs_at_call_insn,
-                                  caller->blocks_added_by_call,
-                                  caller->depth /* stack depth at which
-                                                   these blocks are
-                                                   considered to exist*/ );
-      if (1) {
-         UWord s  = VG_(sizeFM)( siTrees[tid] );
-         UWord g  = VG_(sizeFM)( giTree );
-         Bool  sb = s > stats__max_sitree_size;
-         Bool  gb = g > stats__max_gitree_size;
-         if (sb) stats__max_sitree_size = s;
-         if (gb) stats__max_gitree_size = g;
-         if (0 && (sb || gb))
-            VG_(message)(Vg_DebugMsg, 
-                         "exp-sgcheck: new max tree sizes: "
-                         "StackTree %lu, GlobalTree %lu\n",
-                         stats__max_sitree_size, stats__max_gitree_size );
-      }
-   } else {
-      caller->blocks_added_by_call = NULL;
-   }
-
-   /* caller->blocks_added_by_call is used again (and then freed) when
-      this frame is removed from the stack. */
-
-   if (caller->inner) {
-      callee = caller->inner;
-   } else {
-      callee = sg_malloc("di.sg_main.sSnf.1", sizeof(StackFrame));
-      VG_(memset)(callee, 0, sizeof(StackFrame));
-      callee->outer = caller;
-      caller->inner = callee;
-      callee->depth = 1 + caller->depth;
-      tl_assert(callee->inner == NULL);
-   }
-
-   /* This sets up .htab, .htab_size and .htab_used */
-   initialise_II_hash_table( callee );
-
-   callee->creation_sp    = sp_post_call_insn;
-   callee->sp_at_call     = 0; // not actually required ..
-   callee->fp_at_call     = 0; // .. these 3 initialisations are ..
-   callee->blocks_added_by_call = NULL; // .. just for cleanness
-
-   /* record the new running stack frame */
-   shadowStacks[tid] = callee;
-
-   /* and this thread's query cache is now invalid */
-   QCache__invalidate( &qcaches[tid] );
-
-   if (0)
-   { Word d = callee->depth;
-     const HChar *fnname;
-     Bool ok;
-     Addr ip = ip_post_call_insn;
-     DiEpoch ep = VG_(current_DiEpoch)();
-     ok = VG_(get_fnname_w_offset)( ep, ip, &fnname );
-     while (d > 0) {
-        VG_(printf)(" ");
-        d--;
-     }
-     VG_(printf)("> %s %#lx\n", ok ? fnname : "???", ip);
-   }
-}
-
-/* CALLED FROM GENERATED CODE */
-static
-VG_REGPARM(3)
-void helperc__new_frame ( Addr sp_post_call_insn,
-                          Addr fp_at_call_insn,
-                          Addr ip_post_call_insn,
-                          XArray* blocks_at_call_insn,
-                          Word sp_adjust )
-{
-   ThreadId tid = VG_(get_running_tid)();
-   Addr     sp_at_call_insn = sp_post_call_insn + sp_adjust;
-   shadowStack_new_frame( tid,
-                          sp_at_call_insn,
-                          sp_post_call_insn,
-                          fp_at_call_insn,
-                          ip_post_call_insn,
-                          blocks_at_call_insn );
-}
-
-
-////////////////////////////////////////
-/* Primary remove-frame(s) routine.  Called indirectly from
-   generated code. */
-
-__attribute__((noinline))
-static void shadowStack_unwind ( ThreadId tid, Addr sp_now )
-{
-   StackFrame *innermost, *innermostOrig;
-   tl_assert(is_sane_TId(tid));
-   innermost = shadowStacks[tid];
-   tl_assert(innermost);
-   innermostOrig = innermost;
-   //VG_(printf)("UNWIND sp_new = %p\n", sp_now);
-   while (1) {
-      if (!innermost->outer)
-         break;
-      if (innermost->inner)
-         tl_assert(innermost->inner->outer == innermost);
-      tl_assert(innermost->outer->inner == innermost);
-      tl_assert(innermost->blocks_added_by_call == NULL);
-      if (sp_now <= innermost->creation_sp) break;
-      //VG_(printf)("UNWIND     dump %p\n", innermost->creation_sp);
-      tl_assert(innermost->htab);
-      if (innermost->htab != &innermost->htab_fixed[0])
-         sg_free(innermost->htab);
-      /* be on the safe side */
-      innermost->creation_sp = 0;
-      innermost->htab = NULL;
-      innermost->htab_size = 0;
-      innermost->htab_used = 0;
-      innermost->sp_at_call = 0;
-      innermost->fp_at_call = 0;
-      innermost->blocks_added_by_call = NULL;
-      innermost = innermost->outer;
-
-      /* So now we're "back" in the calling frame.  Remove from this
-         thread's stack-interval-tree, the blocks added at the time of
-         the call. */
-
-      if (innermost->outer) { /* not at the outermost frame */
-         if (innermost->blocks_added_by_call == NULL) {
-         } else {
-            del_blocks_from_StackTree( siTrees[tid],
-                                       innermost->blocks_added_by_call );
-            VG_(deleteXA)( innermost->blocks_added_by_call );
-            innermost->blocks_added_by_call = NULL;
-         }
-      }
-      /* That completes the required tidying of the interval tree
-         associated with the frame we just removed. */
-
-      if (0) {
-         Word d = innermost->depth;
-         while (d > 0) {
-            VG_(printf)(" ");
-            d--;
-         }
-         VG_(printf)("X\n");
-      }
-
-   }
-
-   tl_assert(innermost);
-
-   if (innermost != innermostOrig) {
-      shadowStacks[tid] = innermost;
-      /* this thread's query cache is now invalid */
-      QCache__invalidate( &qcaches[tid] );
-   }
-}
-
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// Instrumentation                                          //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-/* What does instrumentation need to do?
-
-   - at each Call transfer, generate a call to shadowStack_new_frame
-     do this by manually inspecting the IR
-
-   - at each sp change, if the sp change is negative, 
-     call shadowStack_unwind
-     do this by asking for SP-change analysis
-
-   - for each memory referencing instruction,
-     call helperc__mem_access
-*/
-
-/* A complication: sg_ instrumentation and h_ instrumentation need to
-   be interleaved.  Since the latter is a lot more complex than the
-   former, we split the sg_ instrumentation here into four functions
-   and let the h_ instrumenter call the four functions as it goes.
-   Hence the h_ instrumenter drives the sg_ instrumenter.
-
-   To make this viable, the sg_ instrumenter carries what running
-   state it needs in 'struct _SGEnv'.  This is exported only
-   abstractly from this file.
-*/
-
-struct _SGEnv {
-   /* the current insn's IP */
-   Addr curr_IP;
-   /* whether the above is actually known */
-   Bool curr_IP_known;
-   /* if we find a mem ref, is it the first for this insn?  Used for
-      detecting insns which make more than one memory ref, a situation
-      we basically can't really handle properly; and so we ignore all
-      but the first ref. */
-   Bool firstRef;
-   /* READONLY */
-   IRTemp (*newIRTemp_cb)(IRType,void*);
-   void* newIRTemp_opaque;
-};
-
-
-/* --- Helper fns for instrumentation --- */
-
-static IRTemp gen_Get_SP ( struct _SGEnv*  sge,
-                           IRSB*           bbOut,
-                           const VexGuestLayout* layout,
-                           Int             hWordTy_szB )
-{
-   IRExpr* sp_expr;
-   IRTemp  sp_temp;
-   IRType  sp_type;
-   /* This in effect forces the host and guest word sizes to be the
-      same. */
-   tl_assert(hWordTy_szB == layout->sizeof_SP);
-   sp_type = layout->sizeof_SP == 8 ? Ity_I64 : Ity_I32;
-   sp_expr = IRExpr_Get( layout->offset_SP, sp_type );
-   sp_temp = sge->newIRTemp_cb( sp_type, sge->newIRTemp_opaque );
-   addStmtToIRSB( bbOut, IRStmt_WrTmp( sp_temp, sp_expr ) );
-   return sp_temp;
-}
-
-static IRTemp gen_Get_FP ( struct _SGEnv*  sge,
-                           IRSB*           bbOut,
-                           const VexGuestLayout* layout,
-                           Int             hWordTy_szB )
-{
-   IRExpr* fp_expr;
-   IRTemp  fp_temp;
-   IRType  fp_type;
-   /* This in effect forces the host and guest word sizes to be the
-      same. */
-   tl_assert(hWordTy_szB == layout->sizeof_SP);
-   fp_type = layout->sizeof_FP == 8 ? Ity_I64 : Ity_I32;
-   fp_expr = IRExpr_Get( layout->offset_FP, fp_type );
-   fp_temp = sge->newIRTemp_cb( fp_type, sge->newIRTemp_opaque );
-   addStmtToIRSB( bbOut, IRStmt_WrTmp( fp_temp, fp_expr ) );
-   return fp_temp;
-}
-
-static void instrument_mem_access ( struct _SGEnv* sge,
-                                    IRSB*   bbOut, 
-                                    IRExpr* addr,
-                                    Int     szB,
-                                    Bool    isStore,
-                                    Int     hWordTy_szB,
-                                    Addr    curr_IP,
-                                    const VexGuestLayout* layout )
-{
-   IRType  tyAddr      = Ity_INVALID;
-   XArray* frameBlocks = NULL;
-
-   tl_assert(isIRAtom(addr));
-   tl_assert(hWordTy_szB == 4 || hWordTy_szB == 8);
-
-   tyAddr = typeOfIRExpr( bbOut->tyenv, addr );
-   tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
-
-#if defined(VGA_x86)
-   { UChar* p = (UChar*)curr_IP;
-     // pop %ebp; RET
-     if (p[0] == 0xc3 && p[-1] == 0x5d) return;
-     // pop %ebp; RET $imm16
-     if (p[0] == 0xc2 && p[-1] == 0x5d) return;
-     // PUSH %EBP; mov %esp,%ebp
-     if (p[0] == 0x55 && p[1] == 0x89 && p[2] == 0xe5) return;
-   }
-#endif
-
-   /* First off, find or create the StackBlocks for this instruction. */
-   frameBlocks = get_StackBlocks_for_IP( curr_IP );
-   tl_assert(frameBlocks);
-   //if (VG_(sizeXA)( frameBlocks ) == 0)
-   //   frameBlocks = NULL;
-
-   /* Generate a call to "helperc__mem_access", passing:
-         addr current_SP current_FP szB curr_IP frameBlocks
-   */
-   { IRTemp t_SP = gen_Get_SP( sge, bbOut, layout, hWordTy_szB );
-     IRTemp t_FP = gen_Get_FP( sge, bbOut, layout, hWordTy_szB );
-     IRExpr** args
-        = mkIRExprVec_6( addr,
-                         IRExpr_RdTmp(t_SP),
-                         IRExpr_RdTmp(t_FP),
-                         mkIRExpr_HWord( isStore ? (-szB) : szB ),
-                         mkIRExpr_HWord( curr_IP ),
-                         mkIRExpr_HWord( (HWord)frameBlocks ) );
-     IRDirty* di
-        = unsafeIRDirty_0_N( 3/*regparms*/, 
-                             "helperc__mem_access", 
-                            VG_(fnptr_to_fnentry)( &helperc__mem_access ),
-                             args );
-
-     addStmtToIRSB( bbOut, IRStmt_Dirty(di) );
-   }
-}
-
-
-/* --- Instrumentation main (4 fns) --- */
-
-struct _SGEnv * sg_instrument_init ( IRTemp (*newIRTemp_cb)(IRType,void*),
-                                     void* newIRTemp_opaque )
-{
-   struct _SGEnv * env = sg_malloc("di.sg_main.sii.1",
-                                   sizeof(struct _SGEnv));
-   tl_assert(env);
-   env->curr_IP          = 0;
-   env->curr_IP_known    = False;
-   env->firstRef         = True;
-   env->newIRTemp_cb     = newIRTemp_cb;
-   env->newIRTemp_opaque = newIRTemp_opaque;
-   return env;
-}
-
-void sg_instrument_fini ( struct _SGEnv * env )
-{
-   sg_free(env);
-}
-
-/* Add instrumentation for 'st' to 'sbOut', and possibly modify 'env'
-   as required.  This must be called before 'st' itself is added to
-   'sbOut'. */
-void sg_instrument_IRStmt ( /*MOD*/struct _SGEnv * env, 
-                            /*MOD*/IRSB* sbOut,
-                            IRStmt* st,
-                            const VexGuestLayout* layout,
-                            IRType gWordTy, IRType hWordTy )
-{
-   if (!sg_clo_enable_sg_checks)
-      return;
-
-   tl_assert(st);
-   tl_assert(isFlatIRStmt(st));
-   switch (st->tag) {
-      case Ist_NoOp:
-      case Ist_AbiHint:
-      case Ist_Put:
-      case Ist_PutI:
-      case Ist_MBE:
-         /* None of these can contain any memory references. */
-         break;
-
-      case Ist_Exit:
-         tl_assert(st->Ist.Exit.jk != Ijk_Call);
-         /* else we must deal with a conditional call */
-         break;
-
-      case Ist_IMark:
-         env->curr_IP_known = True;
-         env->curr_IP       = st->Ist.IMark.addr;
-         env->firstRef      = True;
-         break;
-
-      case Ist_Store:
-         tl_assert(env->curr_IP_known);
-         if (env->firstRef) {
-            instrument_mem_access( 
-               env, sbOut, 
-               st->Ist.Store.addr, 
-               sizeofIRType(typeOfIRExpr(sbOut->tyenv, st->Ist.Store.data)),
-               True/*isStore*/,
-               sizeofIRType(hWordTy),
-               env->curr_IP, layout
-            );
-            env->firstRef = False;
-         }
-         break;
-
-      case Ist_WrTmp: {
-         IRExpr* data = st->Ist.WrTmp.data;
-         if (data->tag == Iex_Load) {
-            tl_assert(env->curr_IP_known);
-            if (env->firstRef) {
-               instrument_mem_access(
-                  env, sbOut,
-                  data->Iex.Load.addr,
-                  sizeofIRType(data->Iex.Load.ty),
-                  False/*!isStore*/,
-                  sizeofIRType(hWordTy),
-                  env->curr_IP, layout
-               );
-               env->firstRef = False;
-            }
-         }
-         break;
-      }
-
-      case Ist_Dirty: {
-         Int      dataSize;
-         IRDirty* d = st->Ist.Dirty.details;
-         if (d->mFx != Ifx_None) {
-            /* This dirty helper accesses memory.  Collect the
-               details. */
-            tl_assert(env->curr_IP_known);
-            if (env->firstRef) {
-               tl_assert(d->mAddr != NULL);
-               tl_assert(d->mSize != 0);
-               dataSize = d->mSize;
-               if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
-                  instrument_mem_access( 
-                     env, sbOut, d->mAddr, dataSize, False/*!isStore*/,
-                     sizeofIRType(hWordTy), env->curr_IP, layout
-                  );
-               }
-               if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
-                  instrument_mem_access( 
-                     env, sbOut, d->mAddr, dataSize, True/*isStore*/,
-                     sizeofIRType(hWordTy), env->curr_IP, layout
-                  );
-               }
-               env->firstRef = False;
-            }
-         } else {
-            tl_assert(d->mAddr == NULL);
-            tl_assert(d->mSize == 0);
-         }
-         break;
-      }
-
-      case Ist_CAS: {
-         /* We treat it as a read and a write of the location.  I
-            think that is the same behaviour as it was before IRCAS
-            was introduced, since prior to that point, the Vex front
-            ends would translate a lock-prefixed instruction into a
-            (normal) read followed by a (normal) write. */
-         if (env->firstRef) {
-            Int    dataSize;
-            IRCAS* cas = st->Ist.CAS.details;
-            tl_assert(cas->addr != NULL);
-            tl_assert(cas->dataLo != NULL);
-            dataSize = sizeofIRType(typeOfIRExpr(sbOut->tyenv, cas->dataLo));
-            if (cas->dataHi != NULL)
-               dataSize *= 2; /* since it's a doubleword-CAS */
-            instrument_mem_access(
-               env, sbOut, cas->addr, dataSize, False/*!isStore*/,
-               sizeofIRType(hWordTy), env->curr_IP, layout
-            );
-            instrument_mem_access(
-               env, sbOut, cas->addr, dataSize, True/*isStore*/,
-               sizeofIRType(hWordTy), env->curr_IP, layout
-            );
-            env->firstRef = False;
-         }
-         break;
-      }
-
-      case Ist_LoadG: {
-         IRLoadG* lg       = st->Ist.LoadG.details;
-         IRType   type     = Ity_INVALID; /* loaded type */
-         IRType   typeWide = Ity_INVALID; /* after implicit widening */
-         IRExpr*  addr     = lg->addr;
-         typeOfIRLoadGOp(lg->cvt, &typeWide, &type);
-         tl_assert(type != Ity_INVALID);
-         instrument_mem_access(
-            env, sbOut, addr, sizeofIRType(type), False/*isStore*/,
-            sizeofIRType(hWordTy), env->curr_IP, layout
-         );
-         break;
-      }
-
-      default:
-         tl_assert(0);
-
-   } /* switch (st->tag) */
-}
-
-
-/* Add instrumentation for the final jump of an IRSB 'sbOut', and
-   possibly modify 'env' as required.  This must be the last
-   instrumentation statement in the block. */
-void sg_instrument_final_jump ( /*MOD*/struct _SGEnv * env, 
-                                /*MOD*/IRSB* sbOut,
-                                IRExpr* next,
-                                IRJumpKind jumpkind,
-                                const VexGuestLayout* layout,
-                                IRType gWordTy, IRType hWordTy )
-{
-   if (!sg_clo_enable_sg_checks)
-      return;
-
-   if (jumpkind == Ijk_Call) {
-      // Assumes x86 or amd64
-      IRTemp   sp_post_call_insn, fp_post_call_insn;
-      XArray*  frameBlocks;
-      IRExpr** args;
-      IRDirty* di;
-      sp_post_call_insn
-         = gen_Get_SP( env, sbOut, layout, sizeofIRType(hWordTy) );
-      fp_post_call_insn
-         = gen_Get_FP( env, sbOut, layout, sizeofIRType(hWordTy) );
-      tl_assert(env->curr_IP_known);
-      frameBlocks = get_StackBlocks_for_IP( env->curr_IP );
-      tl_assert(frameBlocks);
-      if (VG_(sizeXA)(frameBlocks) == 0)
-         frameBlocks = NULL;
-      args
-         = mkIRExprVec_5(
-              IRExpr_RdTmp(sp_post_call_insn),
-              IRExpr_RdTmp(fp_post_call_insn), 
-                         /* assume the call doesn't change FP */
-              next,
-              mkIRExpr_HWord( (HWord)frameBlocks ),
-              mkIRExpr_HWord( sizeofIRType(gWordTy) )
-           );
-      di = unsafeIRDirty_0_N(
-              3/*regparms*/,
-              "helperc__new_frame",
-              VG_(fnptr_to_fnentry)( &helperc__new_frame ),
-              args ); 
-      addStmtToIRSB( sbOut, IRStmt_Dirty(di) );
-   }
-}
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// end Instrumentation                                      //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// misc                                                     //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-/* Make a new empty stack frame that is suitable for being the
-   outermost frame in a stack.  It has a creation_sp of effectively
-   infinity, so it can never be removed. */
-static StackFrame* new_root_StackFrame ( void )
-{
-   StackFrame* sframe = sg_malloc("di.sg_main.nrS.1", sizeof(StackFrame));
-   VG_(memset)( sframe, 0, sizeof(*sframe) );
-   sframe->creation_sp = ~0UL;
-
-   /* This sets up .htab, .htab_size and .htab_used */
-   initialise_II_hash_table( sframe );
-
-   /* ->depth, ->outer, ->inner are 0, NULL, NULL */
-
-   return sframe;
-}
-
-/* Primary routine for setting up the shadow stack for a new thread.
-   Note that this is used to create not only child thread stacks, but
-   the root thread's stack too.  We create a new stack with
-   .creation_sp set to infinity, so that the outermost frame can never
-   be removed (by shadowStack_unwind).  The core calls this function
-   as soon as a thread is created.  We cannot yet get its SP value,
-   since that may not yet be set. */
-static void shadowStack_thread_create ( ThreadId parent, ThreadId child )
-{
-   tl_assert(is_sane_TId(child));
-   if (parent == VG_INVALID_THREADID) {
-      /* creating the main thread's stack */
-   } else {
-      tl_assert(is_sane_TId(parent));
-      tl_assert(parent != child);
-      tl_assert(shadowStacks[parent] != NULL);
-      tl_assert(siTrees[parent] != NULL);
-   }
-
-   /* Create the child's stack.  Bear in mind we may be re-using
-      it. */
-   if (shadowStacks[child] == NULL) {
-      /* First use of this stack.  Just allocate an initial frame. */
-      tl_assert(siTrees[child] == NULL);
-   } else {
-      StackFrame *frame, *frame2;
-      /* re-using a stack. */
-      /* get rid of the interval tree */
-      tl_assert(siTrees[child] != NULL);
-      delete_StackTree( siTrees[child] );
-      siTrees[child] = NULL;
-      /* Throw away all existing frames. */
-      frame = shadowStacks[child];
-      while (frame->outer)
-         frame = frame->outer;
-      tl_assert(frame->depth == 0);
-      while (frame) {
-         frame2 = frame->inner;
-         if (frame2) tl_assert(1 + frame->depth == frame2->depth);
-         sg_free(frame);
-         frame = frame2;
-      }
-      shadowStacks[child] = NULL;
-   }
-
-   tl_assert(shadowStacks[child] == NULL);
-   tl_assert(siTrees[child] == NULL);
-
-   /* Set up the initial stack frame. */
-   shadowStacks[child] = new_root_StackFrame();
-
-   /* and set up the child's stack block interval tree. */
-   siTrees[child] = new_StackTree();
-}
-
-/* Once a thread is ready to go, the core calls here.  We take the
-   opportunity to push a second frame on its stack, with the
-   presumably valid SP value that is going to be used for the thread's
-   startup.  Hence we should always wind up with a valid outermost
-   frame for the thread. */
-static void shadowStack_set_initial_SP ( ThreadId tid )
-{
-   StackFrame* sf;
-   tl_assert(is_sane_TId(tid));
-   sf = shadowStacks[tid];
-   tl_assert(sf != NULL);
-   tl_assert(sf->outer == NULL);
-   tl_assert(sf->inner == NULL);
-   tl_assert(sf->creation_sp == ~0UL);
-   shadowStack_new_frame( tid, 0, VG_(get_SP)(tid),
-                               0, VG_(get_IP)(tid), NULL );
-}
-
-
-//////////////////////////////////////////////////////////////
-//                                                          //
-// main-ish                                                 //
-//                                                          //
-//////////////////////////////////////////////////////////////
-
-/* CALLED indirectly FROM GENERATED CODE.  Calls here are created by
-   sp-change analysis, as requested in pc_pre_clo_int(). */
-void sg_die_mem_stack ( Addr old_SP, SizeT len ) {
-   ThreadId  tid = VG_(get_running_tid)();
-   shadowStack_unwind( tid, old_SP+len );
-}
-
-void sg_pre_clo_init ( void ) {
-   ourGlobals_init();
-   init_StackBlocks_set();
-   init_GlobalBlock_set();
-}
-
-void sg_post_clo_init ( void ) {
-}
-
-void sg_pre_thread_ll_create ( ThreadId parent, ThreadId child ) {
-   shadowStack_thread_create(parent, child);
-}
-
-void sg_pre_thread_first_insn ( ThreadId tid ) {
-   shadowStack_set_initial_SP(tid);
-}
-
-void sg_fini(Int exitcode)
-{
-   if (VG_(clo_stats)) {
-      VG_(message)(Vg_DebugMsg,
-         " sg_:  %'llu total accesses, of which:\n", stats__total_accesses);
-      VG_(message)(Vg_DebugMsg,
-         " sg_:     stack0: %'12llu classify\n",
-         stats__classify_Stack0);
-      VG_(message)(Vg_DebugMsg,
-         " sg_:     stackN: %'12llu classify\n",
-         stats__classify_StackN);
-      VG_(message)(Vg_DebugMsg,
-         " sg_:     global: %'12llu classify\n",
-         stats__classify_Global);
-      VG_(message)(Vg_DebugMsg,
-         " sg_:    unknown: %'12llu classify\n",
-         stats__classify_Unknown);
-      VG_(message)(Vg_DebugMsg,
-         " sg_:  %'llu Invars preened, of which %'llu changed\n",
-         stats__Invars_preened, stats__Invars_changed);
-      VG_(message)(Vg_DebugMsg,
-         " sg_:   t_i_b_MT: %'12llu\n", stats__t_i_b_empty);
-      VG_(message)(Vg_DebugMsg, 
-         " sg_:     qcache: %'llu searches, %'llu probes, %'llu misses\n",
-         stats__qcache_queries, stats__qcache_probes, stats__qcache_misses);
-      VG_(message)(Vg_DebugMsg, 
-         " sg_:  htab-fast: %'llu hits\n",
-         stats__htab_fast);
-      VG_(message)(Vg_DebugMsg, 
-         " sg_:  htab-slow: %'llu searches, %'llu probes, %'llu resizes\n",
-         stats__htab_searches, stats__htab_probes, stats__htab_resizes);
-   }
-}
-
-
-/*--------------------------------------------------------------------*/
-/*--- end                                                sg_main.c ---*/
-/*--------------------------------------------------------------------*/
diff --git a/exp-sgcheck/sg_main.h b/exp-sgcheck/sg_main.h
deleted file mode 100644 (file)
index 1425932..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Ptrcheck: a pointer-use checker.                             ---*/
-/*--- Exports for stack and global access checking.                ---*/
-/*---                                                    sg_main.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Ptrcheck, a Valgrind tool for checking pointer
-   use in programs.
-
-   Copyright (C) 2008-2017 OpenWorks Ltd
-      info@open-works.co.uk
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef __SG_MAIN_H
-
-#define __SG_MAIN_H
-
-void sg_pre_clo_init ( void );
-void sg_post_clo_init ( void );
-void sg_fini(Int exitcode);
-
-void sg_die_mem_stack ( Addr old_SP, SizeT len );
-void sg_pre_thread_ll_create ( ThreadId parent, ThreadId child );
-void sg_pre_thread_first_insn ( ThreadId tid );
-
-void sg_new_mem_mmap( Addr a, SizeT len,
-                      Bool rr, Bool ww, Bool xx, ULong di_handle );
-void sg_new_mem_startup( Addr a, SizeT len,
-                         Bool rr, Bool ww, Bool xx, ULong di_handle );
-void sg_die_mem_munmap ( Addr a, SizeT len );
-
-/* These really ought to be moved elsewhere, so that we don't have to
-   include this file in h_main.c.  See comments in sg_main.c and
-   h_main.c for what this is about. */
-
-struct _SGEnv;  /* abstract export */
-
-struct _SGEnv* sg_instrument_init ( IRTemp (*newIRTemp_cb)(IRType,void*),
-                                    void* newIRTemp_opaque );
-
-void sg_instrument_fini ( struct _SGEnv * env );
-
-void sg_instrument_IRStmt ( /*MOD*/struct _SGEnv * env, 
-                            /*MOD*/IRSB* sbOut,
-                            IRStmt* st,
-                            const VexGuestLayout* layout,
-                            IRType gWordTy, IRType hWordTy );
-
-void sg_instrument_final_jump ( /*MOD*/struct _SGEnv * env, 
-                                /*MOD*/IRSB* sbOut,
-                                IRExpr* next,
-                                IRJumpKind jumpkind,
-                                const VexGuestLayout* layout,
-                                IRType gWordTy, IRType hWordTy );
-#endif
-
-/*--------------------------------------------------------------------*/
-/*--- end                                                sg_main.h ---*/
-/*--------------------------------------------------------------------*/
diff --git a/exp-sgcheck/tests/Makefile.am b/exp-sgcheck/tests/Makefile.am
deleted file mode 100644 (file)
index fadf0e1..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-
-include $(top_srcdir)/Makefile.tool-tests.am
-
-dist_noinst_SCRIPTS = filter_stderr filter_add filter_suppgen
-
-EXTRA_DIST = \
-       is_arch_supported \
-       bad_percentify.vgtest bad_percentify.c \
-       bad_percentify.stdout.exp bad_percentify.stderr.exp-glibc28-amd64 \
-       globalerr.vgtest globalerr.stdout.exp \
-       globalerr.stderr.exp-glibc28-amd64 \
-       globalerr.stderr.exp-gcc491-amd64 \
-       hackedbz2.vgtest hackedbz2.stdout.exp \
-       hackedbz2.stderr.exp-glibc28-amd64 \
-       hsg.vgtest hsg.stdout.exp hsg.stderr.exp \
-       preen_invars.vgtest preen_invars.stdout.exp \
-       preen_invars.stderr.exp-glibc28-amd64 \
-       stackerr.vgtest stackerr.stdout.exp \
-       stackerr.stderr.exp-glibc28-amd64 stackerr.stderr.exp-glibc27-x86
-
-check_PROGRAMS = \
-       bad_percentify \
-       globalerr hackedbz2 \
-       hsg \
-       preen_invars preen_invars_so.so \
-       stackerr
-
-# DDD: not sure if these ones should work on Darwin or not... if not, should
-# be moved into x86-linux/.
-#if ! VGCONF_OS_IS_DARWIN
-#   check_PROGRAMS += \
-#      ccc
-#endif
-
-
-AM_CFLAGS   += $(AM_FLAG_M3264_PRI)
-AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
-
-# To make it a bit more realistic, build hackedbz2.c with at 
-# least some optimisation.
-hackedbz2_CFLAGS       = $(AM_CFLAGS) -O -Wno-inline
-
-globalerr_CFLAGS        = $(AM_CFLAGS) @FLAG_W_NO_UNINITIALIZED@
-# C ones
-#pth_create_LDADD      = -lpthread
-
-# C++ ones
-#ccc_SOURCES           = ccc.cpp
-
-# Build shared object for preen_invars
-preen_invars_DEPENDENCIES      = preen_invars_so.so
-if VGCONF_OS_IS_DARWIN
- preen_invars_LDADD            = -ldl
- preen_invars_LDFLAGS          = $(AM_FLAG_M3264_PRI)
-else
- preen_invars_LDADD            = -ldl
- preen_invars_LDFLAGS          = $(AM_FLAG_M3264_PRI) \
-                               -Wl,-rpath,$(top_builddir)/memcheck/tests
-endif
-
-preen_invars_so_so_CFLAGS       = $(AM_CFLAGS) -fpic
-if VGCONF_OS_IS_DARWIN
- preen_invars_so_so_LDFLAGS     = -fpic $(AM_FLAG_M3264_PRI) -dynamic \
-                                       -dynamiclib -all_load
-else
- preen_invars_so_so_LDFLAGS     = -fpic $(AM_FLAG_M3264_PRI) -shared \
-                                       -Wl,-soname -Wl,preen_invars_so.so
-endif
-
diff --git a/exp-sgcheck/tests/bad_percentify.c b/exp-sgcheck/tests/bad_percentify.c
deleted file mode 100644 (file)
index 360cd0d..0000000
+++ /dev/null
@@ -1,647 +0,0 @@
-
-/* This demonstrates a stack overrun bug that exp-ptrcheck found while
-   running Valgrind itself (self hosting).  As at 12 Sept 08 this bug
-   is still in Valgrind. */
-
-#include <stdio.h>
-#include <assert.h>
-#include <stdarg.h>
-
-typedef  unsigned long long int  ULong;
-typedef    signed long long int  Long;
-typedef  unsigned int            UInt;
-typedef  signed int              Int;
-typedef  signed char             Char;
-typedef  char                    HChar;
-typedef unsigned long            UWord;
-typedef   signed long            Word;
-
-
-
-typedef  unsigned char  Bool;
-#define  True   ((Bool)1)
-#define  False  ((Bool)0)
-
-#define VG_(_str) VG_##_str
-
-
-/* ---------------------------------------------------------------------
-   vg_sprintf, copied from m_libcprint.c
-   ------------------------------------------------------------------ */
-UInt
-VG_(debugLog_vprintf) ( 
-   void(*send)(HChar,void*), 
-   void* send_arg2,
-   const HChar* format, 
-   va_list vargs
-                        );
-
-/* ---------------------------------------------------------------------
-   printf() and friends
-   ------------------------------------------------------------------ */
-typedef
-   struct { Int fd; Bool is_socket; }
-   OutputSink;
-
-
-OutputSink VG_(log_output_sink) = {  2, False }; /* 2 = stderr */
-/* Do the low-level send of a message to the logging sink. */
-static
-void send_bytes_to_logging_sink ( OutputSink* sink, HChar* msg, Int nbytes )
-{
-   fwrite(msg, 1, nbytes, stdout);
-   fflush(stdout);
-}
-
-
-/* --------- printf --------- */
-
-typedef 
-   struct {
-      HChar       buf[512];
-      Int         buf_used;
-      OutputSink* sink;
-   } 
-   printf_buf_t;
-
-// Adds a single char to the buffer.  When the buffer gets sufficiently
-// full, we write its contents to the logging sink.
-static void add_to__printf_buf ( HChar c, void *p )
-{
-   printf_buf_t *b = (printf_buf_t *)p;
-   
-   if (b->buf_used > sizeof(b->buf) - 2 ) {
-      send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
-      b->buf_used = 0;
-   }
-   b->buf[b->buf_used++] = c;
-   b->buf[b->buf_used]   = 0;
-   assert(b->buf_used < sizeof(b->buf));
-}
-
-__attribute__((noinline))
-static UInt vprintf_to_buf ( printf_buf_t* b,
-                             const HChar *format, va_list vargs )
-{
-   UInt ret = 0;
-   if (b->sink->fd >= 0 || b->sink->fd == -2) {
-      ret = VG_(debugLog_vprintf) 
-               ( add_to__printf_buf, b, format, vargs );
-   }
-   return ret;
-}
-
-__attribute__((noinline))
-static UInt vprintf_WRK ( OutputSink* sink,
-                          const HChar *format, va_list vargs )
-{
-   printf_buf_t myprintf_buf
-      = { "", 0, sink };
-   UInt ret;
-   ret = vprintf_to_buf(&myprintf_buf, format, vargs);
-   // Write out any chars left in the buffer.
-   if (myprintf_buf.buf_used > 0) {
-      send_bytes_to_logging_sink( myprintf_buf.sink,
-                                  myprintf_buf.buf,
-                                  myprintf_buf.buf_used );
-   }
-   return ret;
-}
-
-__attribute__((noinline))
-UInt VG_(vprintf) ( const HChar *format, va_list vargs )
-{
-   return vprintf_WRK( &VG_(log_output_sink), format, vargs );
-}
-
-__attribute__((noinline))
-UInt VG_(printf) ( const HChar *format, ... )
-{
-   UInt ret;
-   va_list vargs;
-   va_start(vargs, format);
-   ret = VG_(vprintf)(format, vargs);
-   va_end(vargs);
-   return ret;
-}
-
-static Bool toBool ( Int x ) {
-   Int r = (x == 0) ? False : True;
-   return (Bool)r;
-}
-
-__attribute__((noinline))
-static Int local_strlen ( const HChar* str )
-{
-   Int i = 0;
-   while (str[i] != 0) i++;
-   return i;
-}
-
-__attribute__((noinline))
-static HChar local_toupper ( HChar c )
-{
-   if (c >= 'a' && c <= 'z')
-      return c + ('A' - 'a'); 
-   else
-      return c;
-}
-
-
-/*------------------------------------------------------------*/
-/*--- A simple, generic, vprintf implementation.           ---*/
-/*------------------------------------------------------------*/
-
-/* -----------------------------------------------
-   Distantly derived from:
-
-      vprintf replacement for Checker.
-      Copyright 1993, 1994, 1995 Tristan Gingold
-      Written September 1993 Tristan Gingold
-      Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
-
-   (Checker itself was GPL'd.)
-   ----------------------------------------------- */
-
-/* Some flags.  */
-#define VG_MSG_SIGNED    1 /* The value is signed. */
-#define VG_MSG_ZJUSTIFY  2 /* Must justify with '0'. */
-#define VG_MSG_LJUSTIFY  4 /* Must justify on the left. */
-#define VG_MSG_PAREN     8 /* Parenthesize if present (for %y) */
-#define VG_MSG_COMMA    16 /* Add commas to numbers (for %d, %u) */
-#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
-
-/* Copy a string into the buffer. */
-static __attribute__((noinline))
-UInt myvprintf_str ( void(*send)(HChar,void*),
-                     void* send_arg2,
-                     Int flags, 
-                     Int width, 
-                     HChar* str, 
-                     Bool capitalise )
-{
-#  define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
-   UInt ret = 0;
-   Int i, extra;
-   Int len = local_strlen(str);
-
-   if (width == 0) {
-      ret += len;
-      for (i = 0; i < len; i++)
-          send(MAYBE_TOUPPER(str[i]), send_arg2);
-      return ret;
-   }
-
-   if (len > width) {
-      ret += width;
-      for (i = 0; i < width; i++)
-         send(MAYBE_TOUPPER(str[i]), send_arg2);
-      return ret;
-   }
-
-   extra = width - len;
-   if (flags & VG_MSG_LJUSTIFY) {
-      ret += extra;
-      for (i = 0; i < extra; i++)
-         send(' ', send_arg2);
-   }
-   ret += len;
-   for (i = 0; i < len; i++)
-      send(MAYBE_TOUPPER(str[i]), send_arg2);
-   if (!(flags & VG_MSG_LJUSTIFY)) {
-      ret += extra;
-      for (i = 0; i < extra; i++)
-         send(' ', send_arg2);
-   }
-
-#  undef MAYBE_TOUPPER
-   return ret;
-}
-
-
-/* Copy a string into the buffer, escaping bad XML chars. */
-static 
-UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
-                                    void* send_arg2,
-                                    HChar* str )
-{
-   UInt   ret = 0;
-   Int    i;
-   Int    len = local_strlen(str);
-   HChar* alt;
-
-   for (i = 0; i < len; i++) {
-      switch (str[i]) {
-         case '&': alt = "&amp;"; break;
-         case '<': alt = "&lt;"; break;
-         case '>': alt = "&gt;"; break;
-         default:  alt = NULL;
-      }
-
-      if (alt) {
-         while (*alt) {
-            send(*alt, send_arg2);
-            ret++;
-            alt++;
-         }
-      } else {
-         send(str[i], send_arg2);
-         ret++;
-      }
-   }
-
-   return ret;
-}
-
-
-/* Write P into the buffer according to these args:
- *  If SIGN is true, p is a signed.
- *  BASE is the base.
- *  If WITH_ZERO is true, '0' must be added.
- *  WIDTH is the width of the field.
- */
-static 
-UInt myvprintf_int64 ( void(*send)(HChar,void*), 
-                       void* send_arg2,
-                       Int flags, 
-                       Int base, 
-                       Int width, 
-                       Bool capitalised,
-                       ULong p )
-{
-   HChar  buf[40];
-   Int    ind = 0;
-   Int    i, nc = 0;
-   Bool   neg = False;
-   HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
-   UInt   ret = 0;
-
-   if (base < 2 || base > 16)
-      return ret;
-   if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
-      p   = - (Long)p;
-      neg = True;
-   }
-
-   if (p == 0)
-      buf[ind++] = '0';
-   else {
-      while (p > 0) {
-         if (flags & VG_MSG_COMMA && 10 == base &&
-             0 == (ind-nc) % 3 && 0 != ind) 
-         {
-            buf[ind++] = ',';
-            nc++;
-         }
-         buf[ind++] = digits[p % base];
-         p /= base;
-      }
-   }
-
-   if (neg)
-      buf[ind++] = '-';
-
-   if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
-      for(; ind < width; ind++) {
-         /* assert(ind < 39); */
-         if (ind > 39) {
-            buf[39] = 0;
-            break;
-         }
-         buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
-      }
-   }
-
-   /* Reverse copy to buffer.  */
-   ret += ind;
-   for (i = ind -1; i >= 0; i--) {
-      send(buf[i], send_arg2);
-   }
-   if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
-      for(; ind < width; ind++) {
-         ret++;
-         /* Never pad with zeroes on RHS -- changes the value! */
-         send(' ', send_arg2);
-      }
-   }
-   return ret;
-}
-
-
-/* A simple vprintf().  */
-/* EXPORTED */
-__attribute__((noinline))
-UInt
-VG_(debugLog_vprintf) ( 
-   void(*send)(HChar,void*), 
-   void* send_arg2,
-   const HChar* format, 
-   va_list vargs
-)
-{
-   UInt ret = 0;
-   Int  i;
-   Int  flags;
-   Int  width;
-   Int  n_ls = 0;
-   Bool is_long, caps;
-
-   /* We assume that vargs has already been initialised by the 
-      caller, using va_start, and that the caller will similarly
-      clean up with va_end.
-   */
-
-   for (i = 0; format[i] != 0; i++) {
-      if (format[i] != '%') {
-         send(format[i], send_arg2);
-         ret++;
-         continue;
-      }
-      i++;
-      /* A '%' has been found.  Ignore a trailing %. */
-      if (format[i] == 0)
-         break;
-      if (format[i] == '%') {
-         /* '%%' is replaced by '%'. */
-         send('%', send_arg2);
-         ret++;
-         continue;
-      }
-      flags = 0;
-      n_ls  = 0;
-      width = 0; /* length of the field. */
-      while (1) {
-         switch (format[i]) {
-         case '(':
-            flags |= VG_MSG_PAREN;
-            break;
-         case ',':
-         case '\'':
-            /* If ',' or '\'' follows '%', commas will be inserted. */
-            flags |= VG_MSG_COMMA;
-            break;
-         case '-':
-            /* If '-' follows '%', justify on the left. */
-            flags |= VG_MSG_LJUSTIFY;
-            break;
-         case '0':
-            /* If '0' follows '%', pads will be inserted. */
-            flags |= VG_MSG_ZJUSTIFY;
-            break;
-         case '#':
-            /* If '#' follows '%', alternative format will be used. */
-            flags |= VG_MSG_ALTFORMAT;
-            break;
-         default:
-            goto parse_fieldwidth;
-         }
-         i++;
-      }
-     parse_fieldwidth:
-      /* Compute the field length. */
-      while (format[i] >= '0' && format[i] <= '9') {
-         width *= 10;
-         width += format[i++] - '0';
-      }
-      while (format[i] == 'l') {
-         i++;
-         n_ls++;
-      }
-
-      //   %d means print a 32-bit integer.
-      //  %ld means print a word-size integer.
-      // %lld means print a 64-bit integer.
-      if      (0 == n_ls) { is_long = False; }
-      else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
-      else                { is_long = True; }
-
-      switch (format[i]) {
-         case 'o': /* %o */
-            if (flags & VG_MSG_ALTFORMAT) {
-               ret += 2;
-               send('0',send_arg2);
-            }
-            if (is_long)
-               ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
-                                      (ULong)(va_arg (vargs, ULong)));
-            else
-               ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
-                                      (ULong)(va_arg (vargs, UInt)));
-            break;
-         case 'd': /* %d */
-            flags |= VG_MSG_SIGNED;
-            if (is_long)
-               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
-                                      (ULong)(va_arg (vargs, Long)));
-            else
-               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
-                                      (ULong)(va_arg (vargs, Int)));
-            break;
-         case 'u': /* %u */
-            if (is_long)
-               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
-                                      (ULong)(va_arg (vargs, ULong)));
-            else
-               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
-                                      (ULong)(va_arg (vargs, UInt)));
-            break;
-         case 'p':
-            if (format[i+1] == 'S') {
-               i++;
-               /* %pS, like %s but escaping chars for XML safety */
-               /* Note: simplistic; ignores field width and flags */
-               char *str = va_arg (vargs, char *);
-               if (str == (char*) 0)
-                  str = "(null)";
-               ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
-            } else {
-               /* %p */
-               ret += 2;
-               send('0',send_arg2);
-               send('x',send_arg2);
-               ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
-                                      (ULong)((UWord)va_arg (vargs, void *)));
-            }
-            break;
-         case 'x': /* %x */
-         case 'X': /* %X */
-            caps = toBool(format[i] == 'X');
-            if (flags & VG_MSG_ALTFORMAT) {
-               ret += 2;
-               send('0',send_arg2);
-               send('x',send_arg2);
-            }
-            if (is_long)
-               ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
-                                      (ULong)(va_arg (vargs, ULong)));
-            else
-               ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
-                                      (ULong)(va_arg (vargs, UInt)));
-            break;
-         case 'c': /* %c */
-            ret++;
-            send(va_arg (vargs, int), send_arg2);
-            break;
-         case 's': case 'S': { /* %s */
-            char *str = va_arg (vargs, char *);
-            if (str == (char*) 0) str = "(null)";
-            ret += myvprintf_str(send, send_arg2, 
-                                 flags, width, str, format[i]=='S');
-            break;
-         }
-
-//         case 'y': { /* %y - print symbol */
-//            Addr a = va_arg(vargs, Addr);
-//
-//
-//
-//            HChar *name;
-//           if (VG_(get_fnname_w_offset)(a, &name)) {
-//               HChar buf[1 + VG_strlen(name) + 1 + 1];
-//              if (flags & VG_MSG_PAREN) {
-//                  VG_(sprintf)(str, "(%s)", name):
-//              } else {
-//                  VG_(sprintf)(str, "%s", name):
-//               }
-//              ret += myvprintf_str(send, flags, width, buf, 0);
-//           }
-//            break;
-//         }
-         default:
-            break;
-      }
-   }
-   return ret;
-}
-
-
-static void add_to__sprintf_buf ( HChar c, void *p )
-{
-   HChar** b = p;
-   *(*b)++ = c;
-}
-
-UInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs )
-{
-   Int ret;
-   HChar* sprintf_ptr = buf;
-
-   ret = VG_(debugLog_vprintf) 
-            ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
-   add_to__sprintf_buf('\0', &sprintf_ptr);
-
-   assert(local_strlen(buf) == ret);
-
-   return ret;
-}
-
-UInt VG_(sprintf) ( HChar* buf, const HChar *format, ... )
-{
-   UInt ret;
-   va_list vargs;
-   va_start(vargs,format);
-   ret = VG_(vsprintf)(buf, format, vargs);
-   va_end(vargs);
-   return ret;
-}
-
-
-
-/* ---------------------------------------------------------------------
-   percentify()
-   ------------------------------------------------------------------ */
-
-/* This part excerpted from coregrind/m_libcbase.c */
-
-// Percentify n/m with d decimal places.  Includes the '%' symbol at the end.
-// Right justifies in 'buf'.
-__attribute__((noinline))
-void VG_percentify(ULong n, ULong m, UInt d, Int n_buf, HChar buf[]) 
-{
-   Int i, len, space;
-   ULong p1;
-   HChar fmt[32];
-
-   if (m == 0) {
-      // Have to generate the format string in order to be flexible about
-      // the width of the field.
-      VG_(sprintf)(fmt, "%%-%ds", n_buf);
-      // fmt is now "%<n_buf>s" where <d> is 1,2,3...
-      VG_(sprintf)(buf, fmt, "--%");
-      return;
-   }
-   
-   p1 = (100*n) / m;
-    
-   if (d == 0) {
-      VG_(sprintf)(buf, "%lld%%", p1);
-   } else {
-      ULong p2;
-      UInt  ex;
-      switch (d) {
-      case 1: ex = 10;    break;
-      case 2: ex = 100;   break;
-      case 3: ex = 1000;  break;
-      default: assert(0);
-      /* was: VG_(tool_panic)("Currently can only handle 3 decimal places"); */
-      }
-      p2 = ((100*n*ex) / m) % ex;
-      // Have to generate the format string in order to be flexible about
-      // the width of the post-decimal-point part.
-      VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
-      // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
-      VG_(sprintf)(buf, fmt, p1, p2);
-   }
-
-   len = local_strlen(buf);
-   space = n_buf - len;
-   if (space < 0) space = 0;     /* Allow for v. small field_width */
-   i = len;
-
-   /* Right justify in field */
-   for (     ; i >= 0;    i--)  buf[i + space] = buf[i];
-   for (i = 0; i < space; i++)  buf[i] = ' ';
-}
-
-
-/*------------------------------------------------------------*/
-/*--- Stats                                                ---*/
-/*------------------------------------------------------------*/
-
-/* This part excerpted from coregrind/m_translate.c */
-
-static UInt n_SP_updates_fast            = 0;
-static UInt n_SP_updates_generic_known   = 0;
-static UInt n_SP_updates_generic_unknown = 0;
-
-__attribute__((noinline))
-void VG_print_translation_stats ( void )
-{
-   HChar buf[6];
-   UInt n_SP_updates = n_SP_updates_fast + n_SP_updates_generic_known
-                                         + n_SP_updates_generic_unknown;
-   VG_percentify(n_SP_updates_fast, n_SP_updates, 1, 6, buf);
-   VG_(printf)(
-      "translate:            fast SP updates identified: %'u (%s)\n",
-      n_SP_updates_fast, buf );
-
-   VG_percentify(n_SP_updates_generic_known, n_SP_updates, 1, 6, buf);
-   VG_(printf)(
-      "translate:   generic_known SP updates identified: %'u (%s)\n",
-      n_SP_updates_generic_known, buf );
-
-   VG_percentify(n_SP_updates_generic_unknown, n_SP_updates, 1, 6, buf);
-   VG_(printf)(
-      "translate: generic_unknown SP updates identified: %'u (%s)\n",
-      n_SP_updates_generic_unknown, buf );
-}
-
-
-
-int main ( void )
-{
-  VG_print_translation_stats();
-  return 0;
-}
diff --git a/exp-sgcheck/tests/bad_percentify.stderr.exp-glibc28-amd64 b/exp-sgcheck/tests/bad_percentify.stderr.exp-glibc28-amd64
deleted file mode 100644 (file)
index 8ce7904..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-
-Invalid read of size 1
-   at 0x........: local_strlen (bad_percentify.c:138)
-   by 0x........: VG_vsprintf (bad_percentify.c:535)
-   by 0x........: VG_sprintf (bad_percentify.c:545)
-   by 0x........: VG_percentify (bad_percentify.c:572)
-   by 0x........: VG_print_translation_stats (bad_percentify.c:625)
-   by 0x........: main (bad_percentify.c:645)
- Address 0x........ expected vs actual:
- Expected: stack array "buf" of size 6 in frame 4 back from here
- Actual:   unknown
- Actual:   is 0 after Expected
-
-Invalid read of size 1
-   at 0x........: local_strlen (bad_percentify.c:138)
-   by 0x........: myvprintf_str (bad_percentify.c:187)
-   by 0x........: VG_debugLog_vprintf (bad_percentify.c:490)
-   by 0x........: vprintf_to_buf (bad_percentify.c:89)
-   by 0x........: vprintf_WRK (bad_percentify.c:102)
-   by 0x........: VG_vprintf (bad_percentify.c:115)
-   by 0x........: VG_printf (bad_percentify.c:124)
-   by 0x........: VG_print_translation_stats (bad_percentify.c:626)
-   by 0x........: main (bad_percentify.c:645)
- Address 0x........ expected vs actual:
- Expected: stack array "buf" of size 6 in frame 7 back from here
- Actual:   unknown
- Actual:   is 0 after Expected
-
-
-ERROR SUMMARY: 6 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/exp-sgcheck/tests/bad_percentify.stdout.exp b/exp-sgcheck/tests/bad_percentify.stdout.exp
deleted file mode 100644 (file)
index a4ab2ff..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-translate:            fast SP updates identified: 0 (   --%)
-translate:   generic_known SP updates identified: 0 (   --%)
-translate: generic_unknown SP updates identified: 0 (   --%)
diff --git a/exp-sgcheck/tests/bad_percentify.vgtest b/exp-sgcheck/tests/bad_percentify.vgtest
deleted file mode 100644 (file)
index a0e50bf..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
-prog: bad_percentify
diff --git a/exp-sgcheck/tests/filter_add b/exp-sgcheck/tests/filter_add
deleted file mode 100755 (executable)
index ad8fbbc..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#! /bin/sh
-
-dir=`dirname $0`
-
-$dir/filter_stderr | 
-
-# Anonymise "before" distances (if greater than 9 bytes)
-sed "s/Address 0x........ is [0-9][0-9]\+ bytes /Address 0x........ is ... bytes /"
diff --git a/exp-sgcheck/tests/filter_stderr b/exp-sgcheck/tests/filter_stderr
deleted file mode 100755 (executable)
index 6b72919..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#! /bin/sh
-
-dir=`dirname $0`
-
-$dir/../../tests/filter_stderr_basic                    |
-
-# Anonymise addresses
-$dir/../../tests/filter_addresses                       |
-
-# Anonymise paths like "(in /foo/bar/libc-baz.so)"
-sed "s/(in \/.*libc.*)$/(in \/...libc...)/"             |
-sed "s/(in \/.*libpthread.*)$/(in \/...libpthread...)/"             |
-
-# Anonymise paths like "__libc_start_main (../foo/bar/libc-quux.c:129)"
-sed "s/__libc_\(.*\) (.*)$/__libc_\1 (...libc...)/" |
-
-# Remove preambly stuff; also postambly stuff
-sed \
--e "/^exp-sgcheck, a stack and global array overrun detector$/d" \
--e "/^NOTE: This is an Experimental-Class Valgrind Tool$/d"  \
--e "/^Copyright (C) 2003-201., and GNU GPL'd, by OpenWorks Ltd et al.$/d" \
--e "/^For lists of detected and suppressed errors, rerun with: -s$/d" |
-
-# Tidy up in cases where glibc (+ libdl + libpthread + ld) have
-# been built with debugging information, hence source locs are present.
-sed \
--e "s/ vfprintf (.*)/ .../" \
--e "s/ vsprintf (.*)/ .../" \
--e "s/ sprintf (.*)/ .../" \
--e "s/ printf (.*)/ .../" \
--e "s/ strdup (.*)/ .../" \
--e "s/(pthread_key_create.c:[0-9]*)/(in \/...libpthread...)/" \
--e "s/(genops.c:[0-9]*)/(in \/...libc...)/" \
--e "s/(syscall-template.S:[0-9]*)/(in \/...libc...)/" |
-
-# Anonymise line numbers in h_intercepts.c.
-sed "s/h_intercepts.c:[0-9]*/h_intercepts.c:.../" 
-
diff --git a/exp-sgcheck/tests/filter_suppgen b/exp-sgcheck/tests/filter_suppgen
deleted file mode 100755 (executable)
index 6a95de5..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-
-#! /bin/sh
-
-dir=`dirname $0`
-
-$dir/filter_stderr | 
-
-# Anonymise "obj:" path
-sed "s/obj:.*\/annelid\/tests\/supp/obj:*\/annelid\/tests\/supp/"
-
-
diff --git a/exp-sgcheck/tests/globalerr.c b/exp-sgcheck/tests/globalerr.c
deleted file mode 100644 (file)
index 5b42763..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-#include <stdio.h>
-
-short a[7];
-static short b[7];
-
-int main ( void )
-{
-  int i;
-  short sum;
-  for (i = 0; i < 7+1; i++) {
-     sum += a[i] * b[i];
-  }
-  return 1 & ((unsigned int)sum / 1000000);
-}
diff --git a/exp-sgcheck/tests/globalerr.stderr.exp-gcc491-amd64 b/exp-sgcheck/tests/globalerr.stderr.exp-gcc491-amd64
deleted file mode 100644 (file)
index b7df06c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-
-Invalid read of size 2
-   at 0x........: main (globalerr.c:12)
- Address 0x........ expected vs actual:
- Expected: global array "a" of size 14 in object with soname "NONE"
- Actual:   unknown
- Actual:   is 0 after Expected
-
-Invalid read of size 2
-   at 0x........: main (globalerr.c:12)
- Address 0x........ expected vs actual:
- Expected: global array "b" of size 14 in object with soname "NONE"
- Actual:   global array "a" of size 14 in object with soname "NONE"
- Actual:   is 0 after Expected
-
-
-ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/exp-sgcheck/tests/globalerr.stderr.exp-glibc28-amd64 b/exp-sgcheck/tests/globalerr.stderr.exp-glibc28-amd64
deleted file mode 100644 (file)
index 3e99037..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-
-Invalid read of size 2
-   at 0x........: main (globalerr.c:12)
- Address 0x........ expected vs actual:
- Expected: global array "a" of size 14 in object with soname "NONE"
- Actual:   unknown
- Actual:   is 0 after Expected
-
-Invalid read of size 2
-   at 0x........: main (globalerr.c:12)
- Address 0x........ expected vs actual:
- Expected: global array "b" of size 14 in object with soname "NONE"
- Actual:   unknown
- Actual:   is 0 after Expected
-
-
-ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/exp-sgcheck/tests/globalerr.stdout.exp b/exp-sgcheck/tests/globalerr.stdout.exp
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/exp-sgcheck/tests/globalerr.vgtest b/exp-sgcheck/tests/globalerr.vgtest
deleted file mode 100644 (file)
index 0f92ab3..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
-prog: globalerr
diff --git a/exp-sgcheck/tests/hackedbz2.c b/exp-sgcheck/tests/hackedbz2.c
deleted file mode 100644 (file)
index f012d7a..0000000
+++ /dev/null
@@ -1,6537 +0,0 @@
-
-/* This is a very slightly modified version of perf/bz2.c, with a
-   single change that causes it to overrun a global array by one byte.
-   The change in question is a change of the size of myprintf_buf from
-   1000 to 70, at line 1278.  ptrcheck should report exactly one
-   error, resulting from an out of range access to this array. */
-
-// This benchmark is basically bzip2 (mashed to be a single file)
-// compressing and decompressing some data.  It tests Valgrind's handling of
-// realistic and "difficult" (ie. lots of branches and memory accesses)
-// integer code.  Execution is spread out over quite a few basic blocks; 
-// --profile-flags indicates that to get to the top 90%th percentile of
-// dynamic BB counts requires considering the top 51 basic blocks
-
-// This program can be used both as part of the performance test
-// suite, in which case we want it to run for quite a while,
-// and as part of the regression (correctness) test suite, in
-// which case we want it to run quickly and be verbose.
-// So it does the latter iff given a command line arg.
-
-// Licensing: the code within is mostly taken from bzip2, which has a BSD
-// license.  There is a little code from VEX, which is licensed under GPLv2
-// And it's all written by Julian Seward.
-
-#define BZ_NO_STDIO
-
-
-/*-------------------------------------------------------------*/
-/*--- Private header file for the library.                  ---*/
-/*---                                       bzlib_private.h ---*/
-/*-------------------------------------------------------------*/
-
-/*--
-  This file is a part of bzip2 and/or libbzip2, a program and
-  library for lossless, block-sorting data compression.
-
-  Copyright (C) 1996-2004 Julian R Seward.  All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-
-  2. The origin of this software must not be misrepresented; you must 
-     not claim that you wrote the original software.  If you use this 
-     software in a product, an acknowledgment in the product 
-     documentation would be appreciated but is not required.
-
-  3. Altered source versions must be plainly marked as such, and must
-     not be misrepresented as being the original software.
-
-  4. The name of the author may not be used to endorse or promote 
-     products derived from this software without specific prior written 
-     permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
-  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-  Julian Seward, Cambridge, UK.
-  jseward@bzip.org
-  bzip2/libbzip2 version 1.0 of 21 March 2000
-
-  This program is based on (at least) the work of:
-     Mike Burrows
-     David Wheeler
-     Peter Fenwick
-     Alistair Moffat
-     Radford Neal
-     Ian H. Witten
-     Robert Sedgewick
-     Jon L. Bentley
-
-  For more information on these sources, see the manual.
---*/
-
-
-#ifndef _BZLIB_PRIVATE_H
-#define _BZLIB_PRIVATE_H
-
-#include <stdlib.h>
-
-#ifndef BZ_NO_STDIO
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#endif
-
-
-/*-------------------------------------------------------------*/
-/*--- Public header file for the library.                   ---*/
-/*---                                               bzlib.h ---*/
-/*-------------------------------------------------------------*/
-
-/*--
-  This file is a part of bzip2 and/or libbzip2, a program and
-  library for lossless, block-sorting data compression.
-
-  Copyright (C) 1996-2004 Julian R Seward.  All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-
-  2. The origin of this software must not be misrepresented; you must 
-     not claim that you wrote the original software.  If you use this 
-     software in a product, an acknowledgment in the product 
-     documentation would be appreciated but is not required.
-
-  3. Altered source versions must be plainly marked as such, and must
-     not be misrepresented as being the original software.
-
-  4. The name of the author may not be used to endorse or promote 
-     products derived from this software without specific prior written 
-     permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
-  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-  Julian Seward, Cambridge, UK.
-  jseward@bzip.org
-  bzip2/libbzip2 version 1.0 of 21 March 2000
-
-  This program is based on (at least) the work of:
-     Mike Burrows
-     David Wheeler
-     Peter Fenwick
-     Alistair Moffat
-     Radford Neal
-     Ian H. Witten
-     Robert Sedgewick
-     Jon L. Bentley
-
-  For more information on these sources, see the manual.
---*/
-
-
-#ifndef _BZLIB_H
-#define _BZLIB_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define BZ_RUN               0
-#define BZ_FLUSH             1
-#define BZ_FINISH            2
-
-#define BZ_OK                0
-#define BZ_RUN_OK            1
-#define BZ_FLUSH_OK          2
-#define BZ_FINISH_OK         3
-#define BZ_STREAM_END        4
-#define BZ_SEQUENCE_ERROR    (-1)
-#define BZ_PARAM_ERROR       (-2)
-#define BZ_MEM_ERROR         (-3)
-#define BZ_DATA_ERROR        (-4)
-#define BZ_DATA_ERROR_MAGIC  (-5)
-#define BZ_IO_ERROR          (-6)
-#define BZ_UNEXPECTED_EOF    (-7)
-#define BZ_OUTBUFF_FULL      (-8)
-#define BZ_CONFIG_ERROR      (-9)
-
-typedef 
-   struct {
-      char *next_in;
-      unsigned int avail_in;
-      unsigned int total_in_lo32;
-      unsigned int total_in_hi32;
-
-      char *next_out;
-      unsigned int avail_out;
-      unsigned int total_out_lo32;
-      unsigned int total_out_hi32;
-
-      void *state;
-
-      void *(*bzalloc)(void *,int,int);
-      void (*bzfree)(void *,void *);
-      void *opaque;
-   } 
-   bz_stream;
-
-
-#ifndef BZ_IMPORT
-#define BZ_EXPORT
-#endif
-
-#ifndef BZ_NO_STDIO
-/* Need a definitition for FILE */
-#include <stdio.h>
-#endif
-
-#ifdef _WIN32
-#   include <windows.h>
-#   ifdef small
-      /* windows.h define small to char */
-#      undef small
-#   endif
-#   ifdef BZ_EXPORT
-#   define BZ_API(func) WINAPI func
-#   define BZ_EXTERN extern
-#   else
-   /* import windows dll dynamically */
-#   define BZ_API(func) (WINAPI * func)
-#   define BZ_EXTERN
-#   endif
-#else
-#   define BZ_API(func) func
-#   define BZ_EXTERN extern
-#endif
-
-
-/*-- Core (low-level) library functions --*/
-
-BZ_EXTERN int BZ_API(BZ2_bzCompressInit) ( 
-      bz_stream* strm, 
-      int        blockSize100k, 
-      int        verbosity, 
-      int        workFactor 
-   );
-
-BZ_EXTERN int BZ_API(BZ2_bzCompress) ( 
-      bz_stream* strm, 
-      int action 
-   );
-
-BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( 
-      bz_stream* strm 
-   );
-
-BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( 
-      bz_stream *strm, 
-      int       verbosity, 
-      int       small
-   );
-
-BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( 
-      bz_stream* strm 
-   );
-
-BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) ( 
-      bz_stream *strm 
-   );
-
-
-
-/*-- High(er) level library functions --*/
-
-#ifndef BZ_NO_STDIO
-#define BZ_MAX_UNUSED 5000
-
-typedef void BZFILE;
-
-BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) ( 
-      int*  bzerror,   
-      FILE* f, 
-      int   verbosity, 
-      int   small,
-      void* unused,    
-      int   nUnused 
-   );
-
-BZ_EXTERN void BZ_API(BZ2_bzReadClose) ( 
-      int*    bzerror, 
-      BZFILE* b 
-   );
-
-BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) ( 
-      int*    bzerror, 
-      BZFILE* b, 
-      void**  unused,  
-      int*    nUnused 
-   );
-
-BZ_EXTERN int BZ_API(BZ2_bzRead) ( 
-      int*    bzerror, 
-      BZFILE* b, 
-      void*   buf, 
-      int     len 
-   );
-
-BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) ( 
-      int*  bzerror,      
-      FILE* f, 
-      int   blockSize100k, 
-      int   verbosity, 
-      int   workFactor 
-   );
-
-BZ_EXTERN void BZ_API(BZ2_bzWrite) ( 
-      int*    bzerror, 
-      BZFILE* b, 
-      void*   buf, 
-      int     len 
-   );
-
-BZ_EXTERN void BZ_API(BZ2_bzWriteClose) ( 
-      int*          bzerror, 
-      BZFILE*       b, 
-      int           abandon, 
-      unsigned int* nbytes_in, 
-      unsigned int* nbytes_out 
-   );
-
-BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) ( 
-      int*          bzerror, 
-      BZFILE*       b, 
-      int           abandon, 
-      unsigned int* nbytes_in_lo32, 
-      unsigned int* nbytes_in_hi32, 
-      unsigned int* nbytes_out_lo32, 
-      unsigned int* nbytes_out_hi32
-   );
-#endif
-
-
-/*-- Utility functions --*/
-
-BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) ( 
-      char*         dest, 
-      unsigned int* destLen,
-      char*         source, 
-      unsigned int  sourceLen,
-      int           blockSize100k, 
-      int           verbosity, 
-      int           workFactor 
-   );
-
-BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( 
-      char*         dest, 
-      unsigned int* destLen,
-      char*         source, 
-      unsigned int  sourceLen,
-      int           small, 
-      int           verbosity 
-   );
-
-
-/*--
-   Code contributed by Yoshioka Tsuneo
-   (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
-   to support better zlib compatibility.
-   This code is not _officially_ part of libbzip2 (yet);
-   I haven't tested it, documented it, or considered the
-   threading-safeness of it.
-   If this code breaks, please contact both Yoshioka and me.
---*/
-
-BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) (
-      void
-   );
-
-#ifndef BZ_NO_STDIO
-BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) (
-      const char *path,
-      const char *mode
-   );
-
-BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
-      int        fd,
-      const char *mode
-   );
-         
-BZ_EXTERN int BZ_API(BZ2_bzread) (
-      BZFILE* b, 
-      void* buf, 
-      int len 
-   );
-
-BZ_EXTERN int BZ_API(BZ2_bzwrite) (
-      BZFILE* b, 
-      void*   buf, 
-      int     len 
-   );
-
-BZ_EXTERN int BZ_API(BZ2_bzflush) (
-      BZFILE* b
-   );
-
-BZ_EXTERN void BZ_API(BZ2_bzclose) (
-      BZFILE* b
-   );
-
-BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
-      BZFILE *b, 
-      int    *errnum
-   );
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-/*-------------------------------------------------------------*/
-/*--- end                                           bzlib.h ---*/
-/*-------------------------------------------------------------*/
-
-
-
-
-/*-- General stuff. --*/
-
-#define BZ_VERSION  "1.0.3, 17-Oct-2004"
-
-typedef char            Char;
-typedef unsigned char   Bool;
-typedef unsigned char   UChar;
-typedef int             Int32;
-typedef unsigned int    UInt32;
-typedef short           Int16;
-typedef unsigned short  UInt16;
-
-#define True  ((Bool)1)
-#define False ((Bool)0)
-
-#ifndef __GNUC__
-#define __inline__  /* */
-#endif 
-
-#ifndef BZ_NO_STDIO
-extern void BZ2_bz__AssertH__fail ( int errcode );
-#define AssertH(cond,errcode) \
-   { if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); }
-#if BZ_DEBUG
-#define AssertD(cond,msg) \
-   { if (!(cond)) {       \
-      fprintf ( stderr,   \
-        "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\
-      exit(1); \
-   }}
-#else
-#define AssertD(cond,msg) /* */
-#endif
-#define VPrintf0(zf) \
-   fprintf(stderr,zf)
-#define VPrintf1(zf,za1) \
-   fprintf(stderr,zf,za1)
-#define VPrintf2(zf,za1,za2) \
-   fprintf(stderr,zf,za1,za2)
-#define VPrintf3(zf,za1,za2,za3) \
-   fprintf(stderr,zf,za1,za2,za3)
-#define VPrintf4(zf,za1,za2,za3,za4) \
-   fprintf(stderr,zf,za1,za2,za3,za4)
-#define VPrintf5(zf,za1,za2,za3,za4,za5) \
-   fprintf(stderr,zf,za1,za2,za3,za4,za5)
-#else
-extern void bz_internal_error ( int errcode );
-#define AssertH(cond,errcode) \
-   { if (!(cond)) bz_internal_error ( errcode ); }
-#define AssertD(cond,msg) /* */
-#define VPrintf0(zf) \
-   vex_printf(zf)
-#define VPrintf1(zf,za1) \
-   vex_printf(zf,za1)
-#define VPrintf2(zf,za1,za2) \
-   vex_printf(zf,za1,za2)
-#define VPrintf3(zf,za1,za2,za3) \
-   vex_printf(zf,za1,za2,za3)
-#define VPrintf4(zf,za1,za2,za3,za4) \
-   vex_printf(zf,za1,za2,za3,za4)
-#define VPrintf5(zf,za1,za2,za3,za4,za5) \
-   vex_printf(zf,za1,za2,za3,za4,za5)
-#endif
-
-
-#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1)
-#define BZFREE(ppp)  (strm->bzfree)(strm->opaque,(ppp))
-
-
-/*-- Header bytes. --*/
-
-#define BZ_HDR_B 0x42   /* 'B' */
-#define BZ_HDR_Z 0x5a   /* 'Z' */
-#define BZ_HDR_h 0x68   /* 'h' */
-#define BZ_HDR_0 0x30   /* '0' */
-  
-/*-- Constants for the back end. --*/
-
-#define BZ_MAX_ALPHA_SIZE 258
-#define BZ_MAX_CODE_LEN    23
-
-#define BZ_RUNA 0
-#define BZ_RUNB 1
-
-#define BZ_N_GROUPS 6
-#define BZ_G_SIZE   50
-#define BZ_N_ITERS  4
-
-#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
-
-
-
-/*-- Stuff for randomising repetitive blocks. --*/
-
-extern Int32 BZ2_rNums[512];
-
-#define BZ_RAND_DECLS                          \
-   Int32 rNToGo;                               \
-   Int32 rTPos                                 \
-
-#define BZ_RAND_INIT_MASK                      \
-   s->rNToGo = 0;                              \
-   s->rTPos  = 0                               \
-
-#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
-
-#define BZ_RAND_UPD_MASK                       \
-   if (s->rNToGo == 0) {                       \
-      s->rNToGo = BZ2_rNums[s->rTPos];         \
-      s->rTPos++;                              \
-      if (s->rTPos == 512) s->rTPos = 0;       \
-   }                                           \
-   s->rNToGo--;
-
-
-
-/*-- Stuff for doing CRCs. --*/
-
-extern UInt32 BZ2_crc32Table[256];
-
-#define BZ_INITIALISE_CRC(crcVar)              \
-{                                              \
-   crcVar = 0xffffffffL;                       \
-}
-
-#define BZ_FINALISE_CRC(crcVar)                \
-{                                              \
-   crcVar = ~(crcVar);                         \
-}
-
-#define BZ_UPDATE_CRC(crcVar,cha)              \
-{                                              \
-   crcVar = (crcVar << 8) ^                    \
-            BZ2_crc32Table[(crcVar >> 24) ^    \
-                           ((UChar)cha)];      \
-}
-
-
-
-/*-- States and modes for compression. --*/
-
-#define BZ_M_IDLE      1
-#define BZ_M_RUNNING   2
-#define BZ_M_FLUSHING  3
-#define BZ_M_FINISHING 4
-
-#define BZ_S_OUTPUT    1
-#define BZ_S_INPUT     2
-
-#define BZ_N_RADIX 2
-#define BZ_N_QSORT 12
-#define BZ_N_SHELL 18
-#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
-
-
-
-
-/*-- Structure holding all the compression-side stuff. --*/
-
-typedef
-   struct {
-      /* pointer back to the struct bz_stream */
-      bz_stream* strm;
-
-      /* mode this stream is in, and whether inputting */
-      /* or outputting data */
-      Int32    mode;
-      Int32    state;
-
-      /* remembers avail_in when flush/finish requested */
-      UInt32   avail_in_expect;
-
-      /* for doing the block sorting */
-      UInt32*  arr1;
-      UInt32*  arr2;
-      UInt32*  ftab;
-      Int32    origPtr;
-
-      /* aliases for arr1 and arr2 */
-      UInt32*  ptr;
-      UChar*   block;
-      UInt16*  mtfv;
-      UChar*   zbits;
-
-      /* for deciding when to use the fallback sorting algorithm */
-      Int32    workFactor;
-
-      /* run-length-encoding of the input */
-      UInt32   state_in_ch;
-      Int32    state_in_len;
-      BZ_RAND_DECLS;
-
-      /* input and output limits and current posns */
-      Int32    nblock;
-      Int32    nblockMAX;
-      Int32    numZ;
-      Int32    state_out_pos;
-
-      /* map of bytes used in block */
-      Int32    nInUse;
-      Bool     inUse[256];
-      UChar    unseqToSeq[256];
-
-      /* the buffer for bit stream creation */
-      UInt32   bsBuff;
-      Int32    bsLive;
-
-      /* block and combined CRCs */
-      UInt32   blockCRC;
-      UInt32   combinedCRC;
-
-      /* misc administratium */
-      Int32    verbosity;
-      Int32    blockNo;
-      Int32    blockSize100k;
-
-      /* stuff for coding the MTF values */
-      Int32    nMTF;
-      Int32    mtfFreq    [BZ_MAX_ALPHA_SIZE];
-      UChar    selector   [BZ_MAX_SELECTORS];
-      UChar    selectorMtf[BZ_MAX_SELECTORS];
-
-      UChar    len     [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
-      Int32    code    [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
-      Int32    rfreq   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
-      /* second dimension: only 3 needed; 4 makes index calculations faster */
-      UInt32   len_pack[BZ_MAX_ALPHA_SIZE][4];
-
-   }
-   EState;
-
-
-
-/*-- externs for compression. --*/
-
-extern void 
-BZ2_blockSort ( EState* );
-
-extern void 
-BZ2_compressBlock ( EState*, Bool );
-
-extern void 
-BZ2_bsInitWrite ( EState* );
-
-extern void 
-BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 );
-
-extern void 
-BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 );
-
-
-
-/*-- states for decompression. --*/
-
-#define BZ_X_IDLE        1
-#define BZ_X_OUTPUT      2
-
-#define BZ_X_MAGIC_1     10
-#define BZ_X_MAGIC_2     11
-#define BZ_X_MAGIC_3     12
-#define BZ_X_MAGIC_4     13
-#define BZ_X_BLKHDR_1    14
-#define BZ_X_BLKHDR_2    15
-#define BZ_X_BLKHDR_3    16
-#define BZ_X_BLKHDR_4    17
-#define BZ_X_BLKHDR_5    18
-#define BZ_X_BLKHDR_6    19
-#define BZ_X_BCRC_1      20
-#define BZ_X_BCRC_2      21
-#define BZ_X_BCRC_3      22
-#define BZ_X_BCRC_4      23
-#define BZ_X_RANDBIT     24
-#define BZ_X_ORIGPTR_1   25
-#define BZ_X_ORIGPTR_2   26
-#define BZ_X_ORIGPTR_3   27
-#define BZ_X_MAPPING_1   28
-#define BZ_X_MAPPING_2   29
-#define BZ_X_SELECTOR_1  30
-#define BZ_X_SELECTOR_2  31
-#define BZ_X_SELECTOR_3  32
-#define BZ_X_CODING_1    33
-#define BZ_X_CODING_2    34
-#define BZ_X_CODING_3    35
-#define BZ_X_MTF_1       36
-#define BZ_X_MTF_2       37
-#define BZ_X_MTF_3       38
-#define BZ_X_MTF_4       39
-#define BZ_X_MTF_5       40
-#define BZ_X_MTF_6       41
-#define BZ_X_ENDHDR_2    42
-#define BZ_X_ENDHDR_3    43
-#define BZ_X_ENDHDR_4    44
-#define BZ_X_ENDHDR_5    45
-#define BZ_X_ENDHDR_6    46
-#define BZ_X_CCRC_1      47
-#define BZ_X_CCRC_2      48
-#define BZ_X_CCRC_3      49
-#define BZ_X_CCRC_4      50
-
-
-
-/*-- Constants for the fast MTF decoder. --*/
-
-#define MTFA_SIZE 4096
-#define MTFL_SIZE 16
-
-
-
-/*-- Structure holding all the decompression-side stuff. --*/
-
-typedef
-   struct {
-      /* pointer back to the struct bz_stream */
-      bz_stream* strm;
-
-      /* state indicator for this stream */
-      Int32    state;
-
-      /* for doing the final run-length decoding */
-      UChar    state_out_ch;
-      Int32    state_out_len;
-      Bool     blockRandomised;
-      BZ_RAND_DECLS;
-
-      /* the buffer for bit stream reading */
-      UInt32   bsBuff;
-      Int32    bsLive;
-
-      /* misc administratium */
-      Int32    blockSize100k;
-      Bool     smallDecompress;
-      Int32    currBlockNo;
-      Int32    verbosity;
-
-      /* for undoing the Burrows-Wheeler transform */
-      Int32    origPtr;
-      UInt32   tPos;
-      Int32    k0;
-      Int32    unzftab[256];
-      Int32    nblock_used;
-      Int32    cftab[257];
-      Int32    cftabCopy[257];
-
-      /* for undoing the Burrows-Wheeler transform (FAST) */
-      UInt32   *tt;
-
-      /* for undoing the Burrows-Wheeler transform (SMALL) */
-      UInt16   *ll16;
-      UChar    *ll4;
-
-      /* stored and calculated CRCs */
-      UInt32   storedBlockCRC;
-      UInt32   storedCombinedCRC;
-      UInt32   calculatedBlockCRC;
-      UInt32   calculatedCombinedCRC;
-
-      /* map of bytes used in block */
-      Int32    nInUse;
-      Bool     inUse[256];
-      Bool     inUse16[16];
-      UChar    seqToUnseq[256];
-
-      /* for decoding the MTF values */
-      UChar    mtfa   [MTFA_SIZE];
-      Int32    mtfbase[256 / MTFL_SIZE];
-      UChar    selector   [BZ_MAX_SELECTORS];
-      UChar    selectorMtf[BZ_MAX_SELECTORS];
-      UChar    len  [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
-
-      Int32    limit  [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
-      Int32    base   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
-      Int32    perm   [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
-      Int32    minLens[BZ_N_GROUPS];
-
-      /* save area for scalars in the main decompress code */
-      Int32    save_i;
-      Int32    save_j;
-      Int32    save_t;
-      Int32    save_alphaSize;
-      Int32    save_nGroups;
-      Int32    save_nSelectors;
-      Int32    save_EOB;
-      Int32    save_groupNo;
-      Int32    save_groupPos;
-      Int32    save_nextSym;
-      Int32    save_nblockMAX;
-      Int32    save_nblock;
-      Int32    save_es;
-      Int32    save_N;
-      Int32    save_curr;
-      Int32    save_zt;
-      Int32    save_zn; 
-      Int32    save_zvec;
-      Int32    save_zj;
-      Int32    save_gSel;
-      Int32    save_gMinlen;
-      Int32*   save_gLimit;
-      Int32*   save_gBase;
-      Int32*   save_gPerm;
-
-   }
-   DState;
-
-
-
-/*-- Macros for decompression. --*/
-
-#define BZ_GET_FAST(cccc)                     \
-    s->tPos = s->tt[s->tPos];                 \
-    cccc = (UChar)(s->tPos & 0xff);           \
-    s->tPos >>= 8;
-
-#define BZ_GET_FAST_C(cccc)                   \
-    c_tPos = c_tt[c_tPos];                    \
-    cccc = (UChar)(c_tPos & 0xff);            \
-    c_tPos >>= 8;
-
-#define SET_LL4(i,n)                                          \
-   { if (((i) & 0x1) == 0)                                    \
-        s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else    \
-        s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4);  \
-   }
-
-#define GET_LL4(i)                             \
-   ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
-
-#define SET_LL(i,n)                          \
-   { s->ll16[i] = (UInt16)(n & 0x0000ffff);  \
-     SET_LL4(i, n >> 16);                    \
-   }
-
-#define GET_LL(i) \
-   (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
-
-#define BZ_GET_SMALL(cccc)                            \
-      cccc = BZ2_indexIntoF ( s->tPos, s->cftab );    \
-      s->tPos = GET_LL(s->tPos);
-
-
-/*-- externs for decompression. --*/
-
-extern Int32 
-BZ2_indexIntoF ( Int32, Int32* );
-
-extern Int32 
-BZ2_decompress ( DState* );
-
-extern void 
-BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
-                           Int32,  Int32, Int32 );
-
-
-#endif
-
-
-/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/
-
-#ifdef BZ_NO_STDIO
-#ifndef NULL
-#define NULL 0
-#endif
-#endif
-
-
-/*-------------------------------------------------------------*/
-/*--- end                                   bzlib_private.h ---*/
-/*-------------------------------------------------------------*/
-
-
-/* Something which has the same size as void* on the host.  That is,
-   it is 32 bits on a 32-bit host and 64 bits on a 64-bit host, and so
-   it can safely be coerced to and from a pointer type on the host
-   machine. */
-typedef  unsigned long HWord;
-typedef  char          HChar;
-typedef  signed int    Int;
-typedef  unsigned int  UInt;
-
-typedef    signed long long int   Long;
-typedef  unsigned long long int   ULong;
-
-
-/////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////
-
-static HWord (*serviceFn)(HWord,HWord) = 0;
-
-#if 0
-static char* my_strcpy ( char* dest, const char* src )
-{
-   char* dest_orig = dest;
-   while (*src) *dest++ = *src++;
-   *dest = 0;
-   return dest_orig;
-}
-
-static void* my_memcpy ( void *dest, const void *src, int sz )
-{
-   const char *s = (const char *)src;
-   char *d = (char *)dest;
-
-   while (sz--)
-      *d++ = *s++;
-
-   return dest;
-}
-
-static void* my_memmove( void *dst, const void *src, unsigned int len )
-{
-    register char *d;
-    register char *s;
-    if ( dst > src ) {
-        d = (char *)dst + len - 1;
-        s = (char *)src + len - 1;
-        while ( len >= 4 ) {
-            *d-- = *s--;
-            *d-- = *s--;
-            *d-- = *s--;
-            *d-- = *s--;
-            len -= 4;
-        }
-        while ( len-- ) {
-            *d-- = *s--;
-        }
-    } else if ( dst < src ) {
-        d = (char *)dst;
-        s = (char *)src;
-        while ( len >= 4 ) {
-            *d++ = *s++;
-            *d++ = *s++;
-            *d++ = *s++;
-            *d++ = *s++;
-            len -= 4;
-        }
-        while ( len-- ) {
-            *d++ = *s++;
-        }
-    }
-    return dst;
-}
-#endif
-
-char* my_strcat ( char* dest, const char* src )
-{
-   char* dest_orig = dest;
-   while (*dest) dest++;
-   while (*src) *dest++ = *src++;
-   *dest = 0;
-   return dest_orig;
-}
-
-
-/////////////////////////////////////////////////////////////////////
-
-static void vex_log_bytes ( char* p, int n )
-{
-   int i;
-   for (i = 0; i < n; i++)
-      (*serviceFn)( 1, (int)p[i] );
-}
-
-/*---------------------------------------------------------*/
-/*--- vex_printf                                        ---*/
-/*---------------------------------------------------------*/
-
-/* This should be the only <...> include in the entire VEX library.
-   New code for vex_util.c should go above this point. */
-#include <stdarg.h>
-
-static HChar vex_toupper ( HChar c )
-{
-   if (c >= 'a' && c <= 'z')
-      return c + ('A' - 'a');
-   else
-      return c;
-}
-/* Explicitly set noinline so the test can check it is in the backtrace. */
-static __attribute__(( noinline)) Int vex_strlen ( const HChar* str )
-{
-   Int i = 0;
-   while (str[i] != 0) i++;
-   return i;
-}
-
-Bool vex_streq ( const HChar* s1, const HChar* s2 )
-{
-   while (True) {
-      if (*s1 == 0 && *s2 == 0)
-         return True;
-      if (*s1 != *s2)
-         return False;
-      s1++;
-      s2++;
-   }
-}
-
-/* Some flags.  */
-#define VG_MSG_SIGNED    1 /* The value is signed. */
-#define VG_MSG_ZJUSTIFY  2 /* Must justify with '0'. */
-#define VG_MSG_LJUSTIFY  4 /* Must justify on the left. */
-#define VG_MSG_PAREN     8 /* Parenthesize if present (for %y) */
-#define VG_MSG_COMMA    16 /* Add commas to numbers (for %d, %u) */
-
-/* Copy a string into the buffer. */
-static UInt
-myvprintf_str ( void(*send)(HChar), Int flags, Int width, HChar* str, 
-                Bool capitalise )
-{
-#  define MAYBE_TOUPPER(ch) (capitalise ? vex_toupper(ch) : (ch))
-   UInt ret = 0;
-   Int i, extra;
-   Int len = vex_strlen(str);
-
-   if (width == 0) {
-      ret += len;
-      for (i = 0; i < len; i++)
-         send(MAYBE_TOUPPER(str[i]));
-      return ret;
-   }
-
-   if (len > width) {
-      ret += width;
-      for (i = 0; i < width; i++)
-         send(MAYBE_TOUPPER(str[i]));
-      return ret;
-   }
-
-   extra = width - len;
-   if (flags & VG_MSG_LJUSTIFY) {
-      ret += extra;
-      for (i = 0; i < extra; i++)
-         send(' ');
-   }
-   ret += len;
-   for (i = 0; i < len; i++)
-      send(MAYBE_TOUPPER(str[i]));
-   if (!(flags & VG_MSG_LJUSTIFY)) {
-      ret += extra;
-      for (i = 0; i < extra; i++)
-         send(' ');
-   }
-
-#  undef MAYBE_TOUPPER
-
-   return ret;
-}
-
-/* Write P into the buffer according to these args:
- *  If SIGN is true, p is a signed.
- *  BASE is the base.
- *  If WITH_ZERO is true, '0' must be added.
- *  WIDTH is the width of the field.
- */
-static UInt
-myvprintf_int64 ( void(*send)(HChar), Int flags, Int base, Int width, ULong pL)
-{
-   HChar buf[40];
-   Int   ind = 0;
-   Int   i, nc = 0;
-   Bool  neg = False;
-   HChar *digits = "0123456789ABCDEF";
-   UInt  ret = 0;
-   UInt  p = (UInt)pL;
-
-   if (base < 2 || base > 16)
-      return ret;
-   if ((flags & VG_MSG_SIGNED) && (Int)p < 0) {
-      p   = - (Int)p;
-      neg = True;
-   }
-
-   if (p == 0)
-      buf[ind++] = '0';
-   else {
-      while (p > 0) {
-         if ((flags & VG_MSG_COMMA) && 10 == base &&
-             0 == (ind-nc) % 3 && 0 != ind) 
-         {
-            buf[ind++] = ',';
-            nc++;
-         }
-         buf[ind++] = digits[p % base];
-         p /= base;
-      }
-   }
-
-   if (neg)
-      buf[ind++] = '-';
-
-   if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
-      for(; ind < width; ind++) {
-       //vassert(ind < 39);
-         buf[ind] = ((flags & VG_MSG_ZJUSTIFY) ? '0': ' ');
-      }
-   }
-
-   /* Reverse copy to buffer.  */
-   ret += ind;
-   for (i = ind -1; i >= 0; i--) {
-      send(buf[i]);
-   }
-   if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
-      for(; ind < width; ind++) {
-        ret++;
-         send(' ');  // Never pad with zeroes on RHS -- changes the value!
-      }
-   }
-   return ret;
-}
-
-
-/* A simple vprintf().  */
-static 
-UInt vprintf_wrk ( void(*send)(HChar), const HChar *format, va_list vargs )
-{
-   UInt ret = 0;
-   int i;
-   int flags;
-   int width;
-   Bool is_long;
-
-   /* We assume that vargs has already been initialised by the 
-      caller, using va_start, and that the caller will similarly
-      clean up with va_end.
-   */
-
-   for (i = 0; format[i] != 0; i++) {
-      if (format[i] != '%') {
-         send(format[i]);
-        ret++;
-         continue;
-      }
-      i++;
-      /* A '%' has been found.  Ignore a trailing %. */
-      if (format[i] == 0)
-         break;
-      if (format[i] == '%') {
-         /* `%%' is replaced by `%'. */
-         send('%');
-        ret++;
-         continue;
-      }
-      flags = 0;
-      is_long = False;
-      width = 0; /* length of the field. */
-      if (format[i] == '(') {
-        flags |= VG_MSG_PAREN;
-        i++;
-      }
-      /* If ',' follows '%', commas will be inserted. */
-      if (format[i] == ',') {
-         flags |= VG_MSG_COMMA;
-         i++;
-      }
-      /* If '-' follows '%', justify on the left. */
-      if (format[i] == '-') {
-         flags |= VG_MSG_LJUSTIFY;
-         i++;
-      }
-      /* If '0' follows '%', pads will be inserted. */
-      if (format[i] == '0') {
-         flags |= VG_MSG_ZJUSTIFY;
-         i++;
-      }
-      /* Compute the field length. */
-      while (format[i] >= '0' && format[i] <= '9') {
-         width *= 10;
-         width += format[i++] - '0';
-      }
-      while (format[i] == 'l') {
-         i++;
-         is_long = True;
-      }
-
-      switch (format[i]) {
-         case 'd': /* %d */
-            flags |= VG_MSG_SIGNED;
-            if (is_long)
-               ret += myvprintf_int64(send, flags, 10, width, 
-                                     (ULong)(va_arg (vargs, Long)));
-            else
-               ret += myvprintf_int64(send, flags, 10, width, 
-                                     (ULong)(va_arg (vargs, Int)));
-            break;
-         case 'u': /* %u */
-            if (is_long)
-               ret += myvprintf_int64(send, flags, 10, width, 
-                                     (ULong)(va_arg (vargs, ULong)));
-            else
-               ret += myvprintf_int64(send, flags, 10, width, 
-                                     (ULong)(va_arg (vargs, UInt)));
-            break;
-         case 'p': /* %p */
-           ret += 2;
-            send('0');
-            send('x');
-            ret += myvprintf_int64(send, flags, 16, width, 
-                                  (ULong)((HWord)va_arg (vargs, void *)));
-            break;
-         case 'x': /* %x */
-            if (is_long)
-               ret += myvprintf_int64(send, flags, 16, width, 
-                                     (ULong)(va_arg (vargs, ULong)));
-            else
-               ret += myvprintf_int64(send, flags, 16, width, 
-                                     (ULong)(va_arg (vargs, UInt)));
-            break;
-         case 'c': /* %c */
-           ret++;
-            send((va_arg (vargs, int)));
-            break;
-         case 's': case 'S': { /* %s */
-            char *str = va_arg (vargs, char *);
-            if (str == (char*) 0) str = "(null)";
-            ret += myvprintf_str(send, flags, width, str, 
-                                 (format[i]=='S'));
-            break;
-        }
-#        if 0
-        case 'y': { /* %y - print symbol */
-           Addr a = va_arg(vargs, Addr);
-
-
-
-            HChar *name;
-           if (VG_(get_fnname_w_offset)(a, &name)) {
-               HChar buf[1 + VG_strlen(name) + 1 + 1];
-              if (flags & VG_MSG_PAREN) {
-                  VG_(sprintf)(str, "(%s)", name):
-              } else {
-                  VG_(sprintf)(str, "%s", name):
-               }
-              ret += myvprintf_str(send, flags, width, buf, 0);
-           }
-           break;
-        }
-#        endif
-         default:
-            break;
-      }
-   }
-   return ret;
-}
-
-
-/* A general replacement for printf().  Note that only low-level 
-   debugging info should be sent via here.  The official route is to
-   to use vg_message().  This interface is deprecated.
-*/
-/* XXX re 930: make the buffer just to small (by 1 byte) to be OK
-   for this particular run. */
-static HChar myprintf_buf[1000   -930];
-static Int   n_myprintf_buf;
-
-static void add_to_myprintf_buf ( HChar c )
-{
-   if (c == '\n' || n_myprintf_buf >= 1000-10 /*paranoia*/ ) {
-      (*vex_log_bytes)( myprintf_buf, vex_strlen(myprintf_buf) );
-      n_myprintf_buf = 0;
-      myprintf_buf[n_myprintf_buf] = 0;      
-   }
-   myprintf_buf[n_myprintf_buf++] = c;
-   myprintf_buf[n_myprintf_buf] = 0;
-}
-
-static UInt vex_printf ( const char *format, ... )
-{
-   UInt ret;
-   va_list vargs;
-   va_start(vargs,format);
-   
-   n_myprintf_buf = 0;
-   myprintf_buf[n_myprintf_buf] = 0;      
-   ret = vprintf_wrk ( add_to_myprintf_buf, format, vargs );
-
-   if (n_myprintf_buf > 0) {
-      (*vex_log_bytes)( myprintf_buf, n_myprintf_buf );
-   }
-
-   va_end(vargs);
-
-   return ret;
-}
-
-/*---------------------------------------------------------------*/
-/*--- end                                          vex_util.c ---*/
-/*---------------------------------------------------------------*/
-
-
-/////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////
-
-
-/*-------------------------------------------------------------*/
-/*--- Decompression machinery                               ---*/
-/*---                                          decompress.c ---*/
-/*-------------------------------------------------------------*/
-
-/*--
-  This file is a part of bzip2 and/or libbzip2, a program and
-  library for lossless, block-sorting data compression.
-
-  Copyright (C) 1996-2004 Julian R Seward.  All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-
-  2. The origin of this software must not be misrepresented; you must 
-     not claim that you wrote the original software.  If you use this 
-     software in a product, an acknowledgment in the product 
-     documentation would be appreciated but is not required.
-
-  3. Altered source versions must be plainly marked as such, and must
-     not be misrepresented as being the original software.
-
-  4. The name of the author may not be used to endorse or promote 
-     products derived from this software without specific prior written 
-     permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
-  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-  Julian Seward, Cambridge, UK.
-  jseward@bzip.org
-  bzip2/libbzip2 version 1.0 of 21 March 2000
-
-  This program is based on (at least) the work of:
-     Mike Burrows
-     David Wheeler
-     Peter Fenwick
-     Alistair Moffat
-     Radford Neal
-     Ian H. Witten
-     Robert Sedgewick
-     Jon L. Bentley
-
-  For more information on these sources, see the manual.
---*/
-
-
-
-
-/*---------------------------------------------------*/
-static
-void makeMaps_d ( DState* s )
-{
-   Int32 i;
-   s->nInUse = 0;
-   for (i = 0; i < 256; i++)
-      if (s->inUse[i]) {
-         s->seqToUnseq[s->nInUse] = i;
-         s->nInUse++;
-      }
-}
-
-
-/*---------------------------------------------------*/
-#define RETURN(rrr)                               \
-   { retVal = rrr; goto save_state_and_return; };
-
-#define GET_BITS(lll,vvv,nnn)                     \
-   case lll: s->state = lll;                      \
-   while (True) {                                 \
-      if (s->bsLive >= nnn) {                     \
-         UInt32 v;                                \
-         v = (s->bsBuff >>                        \
-             (s->bsLive-nnn)) & ((1 << nnn)-1);   \
-         s->bsLive -= nnn;                        \
-         vvv = v;                                 \
-         break;                                   \
-      }                                           \
-      if (s->strm->avail_in == 0) RETURN(BZ_OK);  \
-      s->bsBuff                                   \
-         = (s->bsBuff << 8) |                     \
-           ((UInt32)                              \
-              (*((UChar*)(s->strm->next_in))));   \
-      s->bsLive += 8;                             \
-      s->strm->next_in++;                         \
-      s->strm->avail_in--;                        \
-      s->strm->total_in_lo32++;                   \
-      if (s->strm->total_in_lo32 == 0)            \
-         s->strm->total_in_hi32++;                \
-   }
-
-#define GET_UCHAR(lll,uuu)                        \
-   GET_BITS(lll,uuu,8)
-
-#define GET_BIT(lll,uuu)                          \
-   GET_BITS(lll,uuu,1)
-
-/*---------------------------------------------------*/
-#define GET_MTF_VAL(label1,label2,lval)           \
-{                                                 \
-   if (groupPos == 0) {                           \
-      groupNo++;                                  \
-      if (groupNo >= nSelectors)                  \
-         RETURN(BZ_DATA_ERROR);                   \
-      groupPos = BZ_G_SIZE;                       \
-      gSel = s->selector[groupNo];                \
-      gMinlen = s->minLens[gSel];                 \
-      gLimit = &(s->limit[gSel][0]);              \
-      gPerm = &(s->perm[gSel][0]);                \
-      gBase = &(s->base[gSel][0]);                \
-   }                                              \
-   groupPos--;                                    \
-   zn = gMinlen;                                  \
-   GET_BITS(label1, zvec, zn);                    \
-   while (1) {                                    \
-      if (zn > 20 /* the longest code */)         \
-         RETURN(BZ_DATA_ERROR);                   \
-      if (zvec <= gLimit[zn]) break;              \
-      zn++;                                       \
-      GET_BIT(label2, zj);                        \
-      zvec = (zvec << 1) | zj;                    \
-   };                                             \
-   if (zvec - gBase[zn] < 0                       \
-       || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE)  \
-      RETURN(BZ_DATA_ERROR);                      \
-   lval = gPerm[zvec - gBase[zn]];                \
-}
-
-
-
-/*---------------------------------------------------*/
-__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
-{
-   Int32 nb, na, mid;
-   nb = 0;
-   na = 256;
-   do {
-      mid = (nb + na) >> 1;
-      if (indx >= cftab[mid]) nb = mid; else na = mid;
-   }
-   while (na - nb != 1);
-   return nb;
-}
-
-/*---------------------------------------------------*/
-Int32 BZ2_decompress ( DState* s )
-{
-   UChar      uc;
-   Int32      retVal;
-   Int32      minLen, maxLen;
-   bz_stream* strm = s->strm;
-
-   /* stuff that needs to be saved/restored */
-   Int32  i;
-   Int32  j;
-   Int32  t;
-   Int32  alphaSize;
-   Int32  nGroups;
-   Int32  nSelectors;
-   Int32  EOB;
-   Int32  groupNo;
-   Int32  groupPos;
-   Int32  nextSym;
-   Int32  nblockMAX;
-   Int32  nblock;
-   Int32  es;
-   Int32  N;
-   Int32  curr;
-   Int32  zt;
-   Int32  zn; 
-   Int32  zvec;
-   Int32  zj;
-   Int32  gSel;
-   Int32  gMinlen;
-   Int32* gLimit;
-   Int32* gBase;
-   Int32* gPerm;
-
-   if (s->state == BZ_X_MAGIC_1) {
-      /*initialise the save area*/
-      s->save_i           = 0;
-      s->save_j           = 0;
-      s->save_t           = 0;
-      s->save_alphaSize   = 0;
-      s->save_nGroups     = 0;
-      s->save_nSelectors  = 0;
-      s->save_EOB         = 0;
-      s->save_groupNo     = 0;
-      s->save_groupPos    = 0;
-      s->save_nextSym     = 0;
-      s->save_nblockMAX   = 0;
-      s->save_nblock      = 0;
-      s->save_es          = 0;
-      s->save_N           = 0;
-      s->save_curr        = 0;
-      s->save_zt          = 0;
-      s->save_zn          = 0;
-      s->save_zvec        = 0;
-      s->save_zj          = 0;
-      s->save_gSel        = 0;
-      s->save_gMinlen     = 0;
-      s->save_gLimit      = NULL;
-      s->save_gBase       = NULL;
-      s->save_gPerm       = NULL;
-   }
-
-   /*restore from the save area*/
-   i           = s->save_i;
-   j           = s->save_j;
-   t           = s->save_t;
-   alphaSize   = s->save_alphaSize;
-   nGroups     = s->save_nGroups;
-   nSelectors  = s->save_nSelectors;
-   EOB         = s->save_EOB;
-   groupNo     = s->save_groupNo;
-   groupPos    = s->save_groupPos;
-   nextSym     = s->save_nextSym;
-   nblockMAX   = s->save_nblockMAX;
-   nblock      = s->save_nblock;
-   es          = s->save_es;
-   N           = s->save_N;
-   curr        = s->save_curr;
-   zt          = s->save_zt;
-   zn          = s->save_zn; 
-   zvec        = s->save_zvec;
-   zj          = s->save_zj;
-   gSel        = s->save_gSel;
-   gMinlen     = s->save_gMinlen;
-   gLimit      = s->save_gLimit;
-   gBase       = s->save_gBase;
-   gPerm       = s->save_gPerm;
-
-   retVal = BZ_OK;
-
-   switch (s->state) {
-
-      GET_UCHAR(BZ_X_MAGIC_1, uc);
-      if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC);
-
-      GET_UCHAR(BZ_X_MAGIC_2, uc);
-      if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC);
-
-      GET_UCHAR(BZ_X_MAGIC_3, uc)
-      if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC);
-
-      GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
-      if (s->blockSize100k < (BZ_HDR_0 + 1) || 
-          s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC);
-      s->blockSize100k -= BZ_HDR_0;
-
-      if (s->smallDecompress) {
-         s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
-         s->ll4  = BZALLOC( 
-                      ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) 
-                   );
-         if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
-      } else {
-         s->tt  = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
-         if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
-      }
-
-      GET_UCHAR(BZ_X_BLKHDR_1, uc);
-
-      if (uc == 0x17) goto endhdr_2;
-      if (uc != 0x31) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_BLKHDR_2, uc);
-      if (uc != 0x41) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_BLKHDR_3, uc);
-      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_BLKHDR_4, uc);
-      if (uc != 0x26) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_BLKHDR_5, uc);
-      if (uc != 0x53) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_BLKHDR_6, uc);
-      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
-
-      s->currBlockNo++;
-      if (s->verbosity >= 2)
-         VPrintf1 ( "\n    [%d: huff+mtf ", s->currBlockNo );
-      s->storedBlockCRC = 0;
-      GET_UCHAR(BZ_X_BCRC_1, uc);
-      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_BCRC_2, uc);
-      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_BCRC_3, uc);
-      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_BCRC_4, uc);
-      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
-
-      GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
-
-      s->origPtr = 0;
-      GET_UCHAR(BZ_X_ORIGPTR_1, uc);
-      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
-      GET_UCHAR(BZ_X_ORIGPTR_2, uc);
-      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
-      GET_UCHAR(BZ_X_ORIGPTR_3, uc);
-      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
-
-      if (s->origPtr < 0)
-         RETURN(BZ_DATA_ERROR);
-      if (s->origPtr > 10 + 100000*s->blockSize100k) 
-         RETURN(BZ_DATA_ERROR);
-
-      /*--- Receive the mapping table ---*/
-      for (i = 0; i < 16; i++) {
-         GET_BIT(BZ_X_MAPPING_1, uc);
-         if (uc == 1) 
-            s->inUse16[i] = True; else 
-            s->inUse16[i] = False;
-      }
-
-      for (i = 0; i < 256; i++) s->inUse[i] = False;
-
-      for (i = 0; i < 16; i++)
-         if (s->inUse16[i])
-            for (j = 0; j < 16; j++) {
-               GET_BIT(BZ_X_MAPPING_2, uc);
-               if (uc == 1) s->inUse[i * 16 + j] = True;
-            }
-      makeMaps_d ( s );
-      if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
-      alphaSize = s->nInUse+2;
-
-      /*--- Now the selectors ---*/
-      GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
-      if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
-      GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
-      if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
-      for (i = 0; i < nSelectors; i++) {
-         j = 0;
-         while (True) {
-            GET_BIT(BZ_X_SELECTOR_3, uc);
-            if (uc == 0) break;
-            j++;
-            if (j >= nGroups) RETURN(BZ_DATA_ERROR);
-         }
-         s->selectorMtf[i] = j;
-      }
-
-      /*--- Undo the MTF values for the selectors. ---*/
-      {
-         UChar pos[BZ_N_GROUPS], tmp, v;
-         for (v = 0; v < nGroups; v++) pos[v] = v;
-   
-         for (i = 0; i < nSelectors; i++) {
-            v = s->selectorMtf[i];
-            tmp = pos[v];
-            while (v > 0) { pos[v] = pos[v-1]; v--; }
-            pos[0] = tmp;
-            s->selector[i] = tmp;
-         }
-      }
-
-      /*--- Now the coding tables ---*/
-      for (t = 0; t < nGroups; t++) {
-         GET_BITS(BZ_X_CODING_1, curr, 5);
-         for (i = 0; i < alphaSize; i++) {
-            while (True) {
-               if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
-               GET_BIT(BZ_X_CODING_2, uc);
-               if (uc == 0) break;
-               GET_BIT(BZ_X_CODING_3, uc);
-               if (uc == 0) curr++; else curr--;
-            }
-            s->len[t][i] = curr;
-         }
-      }
-
-      /*--- Create the Huffman decoding tables ---*/
-      for (t = 0; t < nGroups; t++) {
-         minLen = 32;
-         maxLen = 0;
-         for (i = 0; i < alphaSize; i++) {
-            if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
-            if (s->len[t][i] < minLen) minLen = s->len[t][i];
-         }
-         BZ2_hbCreateDecodeTables ( 
-            &(s->limit[t][0]), 
-            &(s->base[t][0]), 
-            &(s->perm[t][0]), 
-            &(s->len[t][0]),
-            minLen, maxLen, alphaSize
-         );
-         s->minLens[t] = minLen;
-      }
-
-      /*--- Now the MTF values ---*/
-
-      EOB      = s->nInUse+1;
-      nblockMAX = 100000 * s->blockSize100k;
-      groupNo  = -1;
-      groupPos = 0;
-
-      for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
-
-      /*-- MTF init --*/
-      {
-         Int32 ii, jj, kk;
-         kk = MTFA_SIZE-1;
-         for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
-            for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
-               s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
-               kk--;
-            }
-            s->mtfbase[ii] = kk + 1;
-         }
-      }
-      /*-- end MTF init --*/
-
-      nblock = 0;
-      GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
-
-      while (True) {
-
-         if (nextSym == EOB) break;
-
-         if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
-
-            es = -1;
-            N = 1;
-            do {
-               if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
-               if (nextSym == BZ_RUNB) es = es + (1+1) * N;
-               N = N * 2;
-               GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
-            }
-               while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
-
-            es++;
-            uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
-            s->unzftab[uc] += es;
-
-            if (s->smallDecompress)
-               while (es > 0) {
-                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
-                  s->ll16[nblock] = (UInt16)uc;
-                  nblock++;
-                  es--;
-               }
-            else
-               while (es > 0) {
-                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
-                  s->tt[nblock] = (UInt32)uc;
-                  nblock++;
-                  es--;
-               };
-
-            continue;
-
-         } else {
-
-            if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
-
-            /*-- uc = MTF ( nextSym-1 ) --*/
-            {
-               Int32 ii, jj, kk, pp, lno, off;
-               UInt32 nn;
-               nn = (UInt32)(nextSym - 1);
-
-               if (nn < MTFL_SIZE) {
-                  /* avoid general-case expense */
-                  pp = s->mtfbase[0];
-                  uc = s->mtfa[pp+nn];
-                  while (nn > 3) {
-                     Int32 z = pp+nn;
-                     s->mtfa[(z)  ] = s->mtfa[(z)-1];
-                     s->mtfa[(z)-1] = s->mtfa[(z)-2];
-                     s->mtfa[(z)-2] = s->mtfa[(z)-3];
-                     s->mtfa[(z)-3] = s->mtfa[(z)-4];
-                     nn -= 4;
-                  }
-                  while (nn > 0) { 
-                     s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; 
-                  };
-                  s->mtfa[pp] = uc;
-               } else { 
-                  /* general case */
-                  lno = nn / MTFL_SIZE;
-                  off = nn % MTFL_SIZE;
-                  pp = s->mtfbase[lno] + off;
-                  uc = s->mtfa[pp];
-                  while (pp > s->mtfbase[lno]) { 
-                     s->mtfa[pp] = s->mtfa[pp-1]; pp--; 
-                  };
-                  s->mtfbase[lno]++;
-                  while (lno > 0) {
-                     s->mtfbase[lno]--;
-                     s->mtfa[s->mtfbase[lno]] 
-                        = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
-                     lno--;
-                  }
-                  s->mtfbase[0]--;
-                  s->mtfa[s->mtfbase[0]] = uc;
-                  if (s->mtfbase[0] == 0) {
-                     kk = MTFA_SIZE-1;
-                     for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
-                        for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
-                           s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
-                           kk--;
-                        }
-                        s->mtfbase[ii] = kk + 1;
-                     }
-                  }
-               }
-            }
-            /*-- end uc = MTF ( nextSym-1 ) --*/
-
-            s->unzftab[s->seqToUnseq[uc]]++;
-            if (s->smallDecompress)
-               s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
-               s->tt[nblock]   = (UInt32)(s->seqToUnseq[uc]);
-            nblock++;
-
-            GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
-            continue;
-         }
-      }
-
-      /* Now we know what nblock is, we can do a better sanity
-         check on s->origPtr.
-      */
-      if (s->origPtr < 0 || s->origPtr >= nblock)
-         RETURN(BZ_DATA_ERROR);
-
-      /*-- Set up cftab to facilitate generation of T^(-1) --*/
-      s->cftab[0] = 0;
-      for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
-      for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
-      for (i = 0; i <= 256; i++) {
-         if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
-            /* s->cftab[i] can legitimately be == nblock */
-            RETURN(BZ_DATA_ERROR);
-         }
-      }
-
-      s->state_out_len = 0;
-      s->state_out_ch  = 0;
-      BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
-      s->state = BZ_X_OUTPUT;
-      if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
-
-      if (s->smallDecompress) {
-
-         /*-- Make a copy of cftab, used in generation of T --*/
-         for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
-
-         /*-- compute the T vector --*/
-         for (i = 0; i < nblock; i++) {
-            uc = (UChar)(s->ll16[i]);
-            SET_LL(i, s->cftabCopy[uc]);
-            s->cftabCopy[uc]++;
-         }
-
-         /*-- Compute T^(-1) by pointer reversal on T --*/
-         i = s->origPtr;
-         j = GET_LL(i);
-         do {
-            Int32 tmp = GET_LL(j);
-            SET_LL(j, i);
-            i = j;
-            j = tmp;
-         }
-            while (i != s->origPtr);
-
-         s->tPos = s->origPtr;
-         s->nblock_used = 0;
-         if (s->blockRandomised) {
-            BZ_RAND_INIT_MASK;
-            BZ_GET_SMALL(s->k0); s->nblock_used++;
-            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
-         } else {
-            BZ_GET_SMALL(s->k0); s->nblock_used++;
-         }
-
-      } else {
-
-         /*-- compute the T^(-1) vector --*/
-         for (i = 0; i < nblock; i++) {
-            uc = (UChar)(s->tt[i] & 0xff);
-            s->tt[s->cftab[uc]] |= (i << 8);
-            s->cftab[uc]++;
-         }
-
-         s->tPos = s->tt[s->origPtr] >> 8;
-         s->nblock_used = 0;
-         if (s->blockRandomised) {
-            BZ_RAND_INIT_MASK;
-            BZ_GET_FAST(s->k0); s->nblock_used++;
-            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
-         } else {
-            BZ_GET_FAST(s->k0); s->nblock_used++;
-         }
-
-      }
-
-      RETURN(BZ_OK);
-
-
-
-    endhdr_2:
-
-      GET_UCHAR(BZ_X_ENDHDR_2, uc);
-      if (uc != 0x72) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_ENDHDR_3, uc);
-      if (uc != 0x45) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_ENDHDR_4, uc);
-      if (uc != 0x38) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_ENDHDR_5, uc);
-      if (uc != 0x50) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_ENDHDR_6, uc);
-      if (uc != 0x90) RETURN(BZ_DATA_ERROR);
-
-      s->storedCombinedCRC = 0;
-      GET_UCHAR(BZ_X_CCRC_1, uc);
-      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_CCRC_2, uc);
-      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_CCRC_3, uc);
-      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_CCRC_4, uc);
-      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
-
-      s->state = BZ_X_IDLE;
-      RETURN(BZ_STREAM_END);
-
-      default: AssertH ( False, 4001 );
-   }
-
-   AssertH ( False, 4002 );
-
-   save_state_and_return:
-
-   s->save_i           = i;
-   s->save_j           = j;
-   s->save_t           = t;
-   s->save_alphaSize   = alphaSize;
-   s->save_nGroups     = nGroups;
-   s->save_nSelectors  = nSelectors;
-   s->save_EOB         = EOB;
-   s->save_groupNo     = groupNo;
-   s->save_groupPos    = groupPos;
-   s->save_nextSym     = nextSym;
-   s->save_nblockMAX   = nblockMAX;
-   s->save_nblock      = nblock;
-   s->save_es          = es;
-   s->save_N           = N;
-   s->save_curr        = curr;
-   s->save_zt          = zt;
-   s->save_zn          = zn;
-   s->save_zvec        = zvec;
-   s->save_zj          = zj;
-   s->save_gSel        = gSel;
-   s->save_gMinlen     = gMinlen;
-   s->save_gLimit      = gLimit;
-   s->save_gBase       = gBase;
-   s->save_gPerm       = gPerm;
-
-   return retVal;   
-}
-
-
-/*-------------------------------------------------------------*/
-/*--- end                                      decompress.c ---*/
-/*-------------------------------------------------------------*/
-
-/*-------------------------------------------------------------*/
-/*--- Block sorting machinery                               ---*/
-/*---                                           blocksort.c ---*/
-/*-------------------------------------------------------------*/
-
-/*--
-  This file is a part of bzip2 and/or libbzip2, a program and
-  library for lossless, block-sorting data compression.
-
-  Copyright (C) 1996-2004 Julian R Seward.  All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-
-  2. The origin of this software must not be misrepresented; you must 
-     not claim that you wrote the original software.  If you use this 
-     software in a product, an acknowledgment in the product 
-     documentation would be appreciated but is not required.
-
-  3. Altered source versions must be plainly marked as such, and must
-     not be misrepresented as being the original software.
-
-  4. The name of the author may not be used to endorse or promote 
-     products derived from this software without specific prior written 
-     permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
-  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-  Julian Seward, Cambridge, UK.
-  jseward@bzip.org
-  bzip2/libbzip2 version 1.0 of 21 March 2000
-
-  This program is based on (at least) the work of:
-     Mike Burrows
-     David Wheeler
-     Peter Fenwick
-     Alistair Moffat
-     Radford Neal
-     Ian H. Witten
-     Robert Sedgewick
-     Jon L. Bentley
-
-  For more information on these sources, see the manual.
-
-  To get some idea how the block sorting algorithms in this file 
-  work, read my paper 
-     On the Performance of BWT Sorting Algorithms
-  in Proceedings of the IEEE Data Compression Conference 2000,
-  Snowbird, Utah, USA, 27-30 March 2000.  The main sort in this
-  file implements the algorithm called  cache  in the paper.
---*/
-
-
-
-/*---------------------------------------------*/
-/*--- Fallback O(N log(N)^2) sorting        ---*/
-/*--- algorithm, for repetitive blocks      ---*/
-/*---------------------------------------------*/
-
-/*---------------------------------------------*/
-static 
-__inline__
-void fallbackSimpleSort ( UInt32* fmap, 
-                          UInt32* eclass, 
-                          Int32   lo, 
-                          Int32   hi )
-{
-   Int32 i, j, tmp;
-   UInt32 ec_tmp;
-
-   if (lo == hi) return;
-
-   if (hi - lo > 3) {
-      for ( i = hi-4; i >= lo; i-- ) {
-         tmp = fmap[i];
-         ec_tmp = eclass[tmp];
-         for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
-            fmap[j-4] = fmap[j];
-         fmap[j-4] = tmp;
-      }
-   }
-
-   for ( i = hi-1; i >= lo; i-- ) {
-      tmp = fmap[i];
-      ec_tmp = eclass[tmp];
-      for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
-         fmap[j-1] = fmap[j];
-      fmap[j-1] = tmp;
-   }
-}
-
-
-/*---------------------------------------------*/
-#define fswap(zz1, zz2) \
-   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
-
-#define fvswap(zzp1, zzp2, zzn)       \
-{                                     \
-   Int32 yyp1 = (zzp1);               \
-   Int32 yyp2 = (zzp2);               \
-   Int32 yyn  = (zzn);                \
-   while (yyn > 0) {                  \
-      fswap(fmap[yyp1], fmap[yyp2]);  \
-      yyp1++; yyp2++; yyn--;          \
-   }                                  \
-}
-
-
-#define fmin(a,b) ((a) < (b)) ? (a) : (b)
-
-#define fpush(lz,hz) { stackLo[sp] = lz; \
-                       stackHi[sp] = hz; \
-                       sp++; }
-
-#define fpop(lz,hz) { sp--;              \
-                      lz = stackLo[sp];  \
-                      hz = stackHi[sp]; }
-
-#define FALLBACK_QSORT_SMALL_THRESH 10
-#define FALLBACK_QSORT_STACK_SIZE   100
-
-
-static
-void fallbackQSort3 ( UInt32* fmap, 
-                      UInt32* eclass,
-                      Int32   loSt, 
-                      Int32   hiSt )
-{
-   Int32 unLo, unHi, ltLo, gtHi, n, m;
-   Int32 sp, lo, hi;
-   UInt32 med, r, r3;
-   Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
-   Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
-
-   r = 0;
-
-   sp = 0;
-   fpush ( loSt, hiSt );
-
-   while (sp > 0) {
-
-      AssertH ( sp < FALLBACK_QSORT_STACK_SIZE, 1004 );
-
-      fpop ( lo, hi );
-      if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
-         fallbackSimpleSort ( fmap, eclass, lo, hi );
-         continue;
-      }
-
-      /* Random partitioning.  Median of 3 sometimes fails to
-         avoid bad cases.  Median of 9 seems to help but 
-         looks rather expensive.  This too seems to work but
-         is cheaper.  Guidance for the magic constants 
-         7621 and 32768 is taken from Sedgewick's algorithms
-         book, chapter 35.
-      */
-      r = ((r * 7621) + 1) % 32768;
-      r3 = r % 3;
-      if (r3 == 0) med = eclass[fmap[lo]]; else
-      if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
-                   med = eclass[fmap[hi]];
-
-      unLo = ltLo = lo;
-      unHi = gtHi = hi;
-
-      while (1) {
-         while (1) {
-            if (unLo > unHi) break;
-            n = (Int32)eclass[fmap[unLo]] - (Int32)med;
-            if (n == 0) { 
-               fswap(fmap[unLo], fmap[ltLo]); 
-               ltLo++; unLo++; 
-               continue; 
-            };
-            if (n > 0) break;
-            unLo++;
-         }
-         while (1) {
-            if (unLo > unHi) break;
-            n = (Int32)eclass[fmap[unHi]] - (Int32)med;
-            if (n == 0) { 
-               fswap(fmap[unHi], fmap[gtHi]); 
-               gtHi--; unHi--; 
-               continue; 
-            };
-            if (n < 0) break;
-            unHi--;
-         }
-         if (unLo > unHi) break;
-         fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
-      }
-
-      AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
-
-      if (gtHi < ltLo) continue;
-
-      n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
-      m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
-
-      n = lo + unLo - ltLo - 1;
-      m = hi - (gtHi - unHi) + 1;
-
-      if (n - lo > hi - m) {
-         fpush ( lo, n );
-         fpush ( m, hi );
-      } else {
-         fpush ( m, hi );
-         fpush ( lo, n );
-      }
-   }
-}
-
-#undef fmin
-#undef fpush
-#undef fpop
-#undef fswap
-#undef fvswap
-#undef FALLBACK_QSORT_SMALL_THRESH
-#undef FALLBACK_QSORT_STACK_SIZE
-
-
-/*---------------------------------------------*/
-/* Pre:
-      nblock > 0
-      eclass exists for [0 .. nblock-1]
-      ((UChar*)eclass) [0 .. nblock-1] holds block
-      ptr exists for [0 .. nblock-1]
-
-   Post:
-      ((UChar*)eclass) [0 .. nblock-1] holds block
-      All other areas of eclass destroyed
-      fmap [0 .. nblock-1] holds sorted order
-      bhtab [ 0 .. 2+(nblock/32) ] destroyed
-*/
-
-#define       SET_BH(zz)  bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
-#define     CLEAR_BH(zz)  bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
-#define     ISSET_BH(zz)  (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
-#define      WORD_BH(zz)  bhtab[(zz) >> 5]
-#define UNALIGNED_BH(zz)  ((zz) & 0x01f)
-
-static
-void fallbackSort ( UInt32* fmap, 
-                    UInt32* eclass, 
-                    UInt32* bhtab,
-                    Int32   nblock,
-                    Int32   verb )
-{
-   Int32 ftab[257];
-   Int32 ftabCopy[256];
-   Int32 H, i, j, k, l, r, cc, cc1;
-   Int32 nNotDone;
-   Int32 nBhtab;
-   UChar* eclass8 = (UChar*)eclass;
-
-   /*--
-      Initial 1-char radix sort to generate
-      initial fmap and initial BH bits.
-   --*/
-   if (verb >= 4)
-      VPrintf0 ( "        bucket sorting ...\n" );
-   for (i = 0; i < 257;    i++) ftab[i] = 0;
-   for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
-   for (i = 0; i < 256;    i++) ftabCopy[i] = ftab[i];
-   for (i = 1; i < 257;    i++) ftab[i] += ftab[i-1];
-
-   for (i = 0; i < nblock; i++) {
-      j = eclass8[i];
-      k = ftab[j] - 1;
-      ftab[j] = k;
-      fmap[k] = i;
-   }
-
-   nBhtab = 2 + (nblock / 32);
-   for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
-   for (i = 0; i < 256; i++) SET_BH(ftab[i]);
-
-   /*--
-      Inductively refine the buckets.  Kind-of an
-      "exponential radix sort" (!), inspired by the
-      Manber-Myers suffix array construction algorithm.
-   --*/
-
-   /*-- set sentinel bits for block-end detection --*/
-   for (i = 0; i < 32; i++) { 
-      SET_BH(nblock + 2*i);
-      CLEAR_BH(nblock + 2*i + 1);
-   }
-
-   /*-- the log(N) loop --*/
-   H = 1;
-   while (1) {
-
-      if (verb >= 4) 
-         VPrintf1 ( "        depth %6d has ", H );
-
-      j = 0;
-      for (i = 0; i < nblock; i++) {
-         if (ISSET_BH(i)) j = i;
-         k = fmap[i] - H; if (k < 0) k += nblock;
-         eclass[k] = j;
-      }
-
-      nNotDone = 0;
-      r = -1;
-      while (1) {
-
-        /*-- find the next non-singleton bucket --*/
-         k = r + 1;
-         while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
-         if (ISSET_BH(k)) {
-            while (WORD_BH(k) == 0xffffffff) k += 32;
-            while (ISSET_BH(k)) k++;
-         }
-         l = k - 1;
-         if (l >= nblock) break;
-         while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
-         if (!ISSET_BH(k)) {
-            while (WORD_BH(k) == 0x00000000) k += 32;
-            while (!ISSET_BH(k)) k++;
-         }
-         r = k - 1;
-         if (r >= nblock) break;
-
-         /*-- now [l, r] bracket current bucket --*/
-         if (r > l) {
-            nNotDone += (r - l + 1);
-            fallbackQSort3 ( fmap, eclass, l, r );
-
-            /*-- scan bucket and generate header bits-- */
-            cc = -1;
-            for (i = l; i <= r; i++) {
-               cc1 = eclass[fmap[i]];
-               if (cc != cc1) { SET_BH(i); cc = cc1; };
-            }
-         }
-      }
-
-      if (verb >= 4) 
-         VPrintf1 ( "%6d unresolved strings\n", nNotDone );
-
-      H *= 2;
-      if (H > nblock || nNotDone == 0) break;
-   }
-
-   /*-- 
-      Reconstruct the original block in
-      eclass8 [0 .. nblock-1], since the
-      previous phase destroyed it.
-   --*/
-   if (verb >= 4)
-      VPrintf0 ( "        reconstructing block ...\n" );
-   j = 0;
-   for (i = 0; i < nblock; i++) {
-      while (ftabCopy[j] == 0) j++;
-      ftabCopy[j]--;
-      eclass8[fmap[i]] = (UChar)j;
-   }
-   AssertH ( j < 256, 1005 );
-}
-
-#undef       SET_BH
-#undef     CLEAR_BH
-#undef     ISSET_BH
-#undef      WORD_BH
-#undef UNALIGNED_BH
-
-
-/*---------------------------------------------*/
-/*--- The main, O(N^2 log(N)) sorting       ---*/
-/*--- algorithm.  Faster for "normal"       ---*/
-/*--- non-repetitive blocks.                ---*/
-/*---------------------------------------------*/
-
-/*---------------------------------------------*/
-static
-__inline__
-Bool mainGtU ( UInt32  i1, 
-               UInt32  i2,
-               UChar*  block, 
-               UInt16* quadrant,
-               UInt32  nblock,
-               Int32*  budget )
-{
-   Int32  k;
-   UChar  c1, c2;
-   UInt16 s1, s2;
-
-   AssertD ( i1 != i2, "mainGtU" );
-   /* 1 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-   /* 2 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-   /* 3 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-   /* 4 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-   /* 5 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-   /* 6 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-   /* 7 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-   /* 8 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-   /* 9 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-   /* 10 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-   /* 11 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-   /* 12 */
-   c1 = block[i1]; c2 = block[i2];
-   if (c1 != c2) return (c1 > c2);
-   i1++; i2++;
-
-   k = nblock + 8;
-
-   do {
-      /* 1 */
-      c1 = block[i1]; c2 = block[i2];
-      if (c1 != c2) return (c1 > c2);
-      s1 = quadrant[i1]; s2 = quadrant[i2];
-      if (s1 != s2) return (s1 > s2);
-      i1++; i2++;
-      /* 2 */
-      c1 = block[i1]; c2 = block[i2];
-      if (c1 != c2) return (c1 > c2);
-      s1 = quadrant[i1]; s2 = quadrant[i2];
-      if (s1 != s2) return (s1 > s2);
-      i1++; i2++;
-      /* 3 */
-      c1 = block[i1]; c2 = block[i2];
-      if (c1 != c2) return (c1 > c2);
-      s1 = quadrant[i1]; s2 = quadrant[i2];
-      if (s1 != s2) return (s1 > s2);
-      i1++; i2++;
-      /* 4 */
-      c1 = block[i1]; c2 = block[i2];
-      if (c1 != c2) return (c1 > c2);
-      s1 = quadrant[i1]; s2 = quadrant[i2];
-      if (s1 != s2) return (s1 > s2);
-      i1++; i2++;
-      /* 5 */
-      c1 = block[i1]; c2 = block[i2];
-      if (c1 != c2) return (c1 > c2);
-      s1 = quadrant[i1]; s2 = quadrant[i2];
-      if (s1 != s2) return (s1 > s2);
-      i1++; i2++;
-      /* 6 */
-      c1 = block[i1]; c2 = block[i2];
-      if (c1 != c2) return (c1 > c2);
-      s1 = quadrant[i1]; s2 = quadrant[i2];
-      if (s1 != s2) return (s1 > s2);
-      i1++; i2++;
-      /* 7 */
-      c1 = block[i1]; c2 = block[i2];
-      if (c1 != c2) return (c1 > c2);
-      s1 = quadrant[i1]; s2 = quadrant[i2];
-      if (s1 != s2) return (s1 > s2);
-      i1++; i2++;
-      /* 8 */
-      c1 = block[i1]; c2 = block[i2];
-      if (c1 != c2) return (c1 > c2);
-      s1 = quadrant[i1]; s2 = quadrant[i2];
-      if (s1 != s2) return (s1 > s2);
-      i1++; i2++;
-
-      if (i1 >= nblock) i1 -= nblock;
-      if (i2 >= nblock) i2 -= nblock;
-
-      k -= 8;
-      (*budget)--;
-   }
-      while (k >= 0);
-
-   return False;
-}
-
-
-/*---------------------------------------------*/
-/*--
-   Knuth's increments seem to work better
-   than Incerpi-Sedgewick here.  Possibly
-   because the number of elems to sort is
-   usually small, typically <= 20.
---*/
-static
-Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
-                   9841, 29524, 88573, 265720,
-                   797161, 2391484 };
-
-static
-void mainSimpleSort ( UInt32* ptr,
-                      UChar*  block,
-                      UInt16* quadrant,
-                      Int32   nblock,
-                      Int32   lo, 
-                      Int32   hi, 
-                      Int32   d,
-                      Int32*  budget )
-{
-   Int32 i, j, h, bigN, hp;
-   UInt32 v;
-
-   bigN = hi - lo + 1;
-   if (bigN < 2) return;
-
-   hp = 0;
-   while (incs[hp] < bigN) hp++;
-   hp--;
-
-   for (; hp >= 0; hp--) {
-      h = incs[hp];
-
-      i = lo + h;
-      while (True) {
-
-         /*-- copy 1 --*/
-         if (i > hi) break;
-         v = ptr[i];
-         j = i;
-         while ( mainGtU ( 
-                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
-                 ) ) {
-            ptr[j] = ptr[j-h];
-            j = j - h;
-            if (j <= (lo + h - 1)) break;
-         }
-         ptr[j] = v;
-         i++;
-
-         /*-- copy 2 --*/
-         if (i > hi) break;
-         v = ptr[i];
-         j = i;
-         while ( mainGtU ( 
-                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
-                 ) ) {
-            ptr[j] = ptr[j-h];
-            j = j - h;
-            if (j <= (lo + h - 1)) break;
-         }
-         ptr[j] = v;
-         i++;
-
-         /*-- copy 3 --*/
-         if (i > hi) break;
-         v = ptr[i];
-         j = i;
-         while ( mainGtU ( 
-                    ptr[j-h]+d, v+d, block, quadrant, nblock, budget 
-                 ) ) {
-            ptr[j] = ptr[j-h];
-            j = j - h;
-            if (j <= (lo + h - 1)) break;
-         }
-         ptr[j] = v;
-         i++;
-
-         if (*budget < 0) return;
-      }
-   }
-}
-
-
-/*---------------------------------------------*/
-/*--
-   The following is an implementation of
-   an elegant 3-way quicksort for strings,
-   described in a paper "Fast Algorithms for
-   Sorting and Searching Strings", by Robert
-   Sedgewick and Jon L. Bentley.
---*/
-
-#define mswap(zz1, zz2) \
-   { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
-
-#define mvswap(zzp1, zzp2, zzn)       \
-{                                     \
-   Int32 yyp1 = (zzp1);               \
-   Int32 yyp2 = (zzp2);               \
-   Int32 yyn  = (zzn);                \
-   while (yyn > 0) {                  \
-      mswap(ptr[yyp1], ptr[yyp2]);    \
-      yyp1++; yyp2++; yyn--;          \
-   }                                  \
-}
-
-static 
-__inline__
-UChar mmed3 ( UChar a, UChar b, UChar c )
-{
-   UChar t;
-   if (a > b) { t = a; a = b; b = t; };
-   if (b > c) { 
-      b = c;
-      if (a > b) b = a;
-   }
-   return b;
-}
-
-#define mmin(a,b) ((a) < (b)) ? (a) : (b)
-
-#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
-                          stackHi[sp] = hz; \
-                          stackD [sp] = dz; \
-                          sp++; }
-
-#define mpop(lz,hz,dz) { sp--;             \
-                         lz = stackLo[sp]; \
-                         hz = stackHi[sp]; \
-                         dz = stackD [sp]; }
-
-
-#define mnextsize(az) (nextHi[az]-nextLo[az])
-
-#define mnextswap(az,bz)                                        \
-   { Int32 tz;                                                  \
-     tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
-     tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
-     tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
-
-
-#define MAIN_QSORT_SMALL_THRESH 20
-#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
-#define MAIN_QSORT_STACK_SIZE 100
-
-static
-void mainQSort3 ( UInt32* ptr,
-                  UChar*  block,
-                  UInt16* quadrant,
-                  Int32   nblock,
-                  Int32   loSt, 
-                  Int32   hiSt, 
-                  Int32   dSt,
-                  Int32*  budget )
-{
-   Int32 unLo, unHi, ltLo, gtHi, n, m, med;
-   Int32 sp, lo, hi, d;
-
-   Int32 stackLo[MAIN_QSORT_STACK_SIZE];
-   Int32 stackHi[MAIN_QSORT_STACK_SIZE];
-   Int32 stackD [MAIN_QSORT_STACK_SIZE];
-
-   Int32 nextLo[3];
-   Int32 nextHi[3];
-   Int32 nextD [3];
-
-   sp = 0;
-   mpush ( loSt, hiSt, dSt );
-
-   while (sp > 0) {
-
-      AssertH ( sp < MAIN_QSORT_STACK_SIZE, 1001 );
-
-      mpop ( lo, hi, d );
-      if (hi - lo < MAIN_QSORT_SMALL_THRESH || 
-          d > MAIN_QSORT_DEPTH_THRESH) {
-         mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
-         if (*budget < 0) return;
-         continue;
-      }
-
-      med = (Int32) 
-            mmed3 ( block[ptr[ lo         ]+d],
-                    block[ptr[ hi         ]+d],
-                    block[ptr[ (lo+hi)>>1 ]+d] );
-
-      unLo = ltLo = lo;
-      unHi = gtHi = hi;
-
-      while (True) {
-         while (True) {
-            if (unLo > unHi) break;
-            n = ((Int32)block[ptr[unLo]+d]) - med;
-            if (n == 0) { 
-               mswap(ptr[unLo], ptr[ltLo]); 
-               ltLo++; unLo++; continue; 
-            };
-            if (n >  0) break;
-            unLo++;
-         }
-         while (True) {
-            if (unLo > unHi) break;
-            n = ((Int32)block[ptr[unHi]+d]) - med;
-            if (n == 0) { 
-               mswap(ptr[unHi], ptr[gtHi]); 
-               gtHi--; unHi--; continue; 
-            };
-            if (n <  0) break;
-            unHi--;
-         }
-         if (unLo > unHi) break;
-         mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
-      }
-
-      AssertD ( unHi == unLo-1, "mainQSort3(2)" );
-
-      if (gtHi < ltLo) {
-         mpush(lo, hi, d+1 );
-         continue;
-      }
-
-      n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
-      m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
-
-      n = lo + unLo - ltLo - 1;
-      m = hi - (gtHi - unHi) + 1;
-
-      nextLo[0] = lo;  nextHi[0] = n;   nextD[0] = d;
-      nextLo[1] = m;   nextHi[1] = hi;  nextD[1] = d;
-      nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
-
-      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
-      if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
-      if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
-
-      AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
-      AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
-
-      mpush (nextLo[0], nextHi[0], nextD[0]);
-      mpush (nextLo[1], nextHi[1], nextD[1]);
-      mpush (nextLo[2], nextHi[2], nextD[2]);
-   }
-}
-
-#undef mswap
-#undef mvswap
-#undef mpush
-#undef mpop
-#undef mmin
-#undef mnextsize
-#undef mnextswap
-#undef MAIN_QSORT_SMALL_THRESH
-#undef MAIN_QSORT_DEPTH_THRESH
-#undef MAIN_QSORT_STACK_SIZE
-
-
-/*---------------------------------------------*/
-/* Pre:
-      nblock > N_OVERSHOOT
-      block32 exists for [0 .. nblock-1 +N_OVERSHOOT]
-      ((UChar*)block32) [0 .. nblock-1] holds block
-      ptr exists for [0 .. nblock-1]
-
-   Post:
-      ((UChar*)block32) [0 .. nblock-1] holds block
-      All other areas of block32 destroyed
-      ftab [0 .. 65536 ] destroyed
-      ptr [0 .. nblock-1] holds sorted order
-      if (*budget < 0), sorting was abandoned
-*/
-
-#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
-#define SETMASK (1 << 21)
-#define CLEARMASK (~(SETMASK))
-
-static
-void mainSort ( UInt32* ptr, 
-                UChar*  block,
-                UInt16* quadrant, 
-                UInt32* ftab,
-                Int32   nblock,
-                Int32   verb,
-                Int32*  budget )
-{
-   Int32  i, j, k, ss, sb;
-   Int32  runningOrder[256];
-   Bool   bigDone[256];
-   Int32  copyStart[256];
-   Int32  copyEnd  [256];
-   UChar  c1;
-   Int32  numQSorted;
-   UInt16 s;
-   if (verb >= 4) VPrintf0 ( "        main sort initialise ...\n" );
-
-   /*-- set up the 2-byte frequency table --*/
-   for (i = 65536; i >= 0; i--) ftab[i] = 0;
-
-   j = block[0] << 8;
-   i = nblock-1;
-   for (; i >= 3; i -= 4) {
-      quadrant[i] = 0;
-      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
-      ftab[j]++;
-      quadrant[i-1] = 0;
-      j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
-      ftab[j]++;
-      quadrant[i-2] = 0;
-      j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
-      ftab[j]++;
-      quadrant[i-3] = 0;
-      j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
-      ftab[j]++;
-   }
-   for (; i >= 0; i--) {
-      quadrant[i] = 0;
-      j = (j >> 8) | ( ((UInt16)block[i]) << 8);
-      ftab[j]++;
-   }
-
-   /*-- (emphasises close relationship of block & quadrant) --*/
-   for (i = 0; i < BZ_N_OVERSHOOT; i++) {
-      block   [nblock+i] = block[i];
-      quadrant[nblock+i] = 0;
-   }
-
-   if (verb >= 4) VPrintf0 ( "        bucket sorting ...\n" );
-
-   /*-- Complete the initial radix sort --*/
-   for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
-
-   s = block[0] << 8;
-   i = nblock-1;
-   for (; i >= 3; i -= 4) {
-      s = (s >> 8) | (block[i] << 8);
-      j = ftab[s] -1;
-      ftab[s] = j;
-      ptr[j] = i;
-      s = (s >> 8) | (block[i-1] << 8);
-      j = ftab[s] -1;
-      ftab[s] = j;
-      ptr[j] = i-1;
-      s = (s >> 8) | (block[i-2] << 8);
-      j = ftab[s] -1;
-      ftab[s] = j;
-      ptr[j] = i-2;
-      s = (s >> 8) | (block[i-3] << 8);
-      j = ftab[s] -1;
-      ftab[s] = j;
-      ptr[j] = i-3;
-   }
-   for (; i >= 0; i--) {
-      s = (s >> 8) | (block[i] << 8);
-      j = ftab[s] -1;
-      ftab[s] = j;
-      ptr[j] = i;
-   }
-
-   /*--
-      Now ftab contains the first loc of every small bucket.
-      Calculate the running order, from smallest to largest
-      big bucket.
-   --*/
-   for (i = 0; i <= 255; i++) {
-      bigDone     [i] = False;
-      runningOrder[i] = i;
-   }
-
-   {
-      Int32 vv;
-      Int32 h = 1;
-      do h = 3 * h + 1; while (h <= 256);
-      do {
-         h = h / 3;
-         for (i = h; i <= 255; i++) {
-            vv = runningOrder[i];
-            j = i;
-            while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
-               runningOrder[j] = runningOrder[j-h];
-               j = j - h;
-               if (j <= (h - 1)) goto zero;
-            }
-            zero:
-            runningOrder[j] = vv;
-         }
-      } while (h != 1);
-   }
-
-   /*--
-      The main sorting loop.
-   --*/
-
-   numQSorted = 0;
-
-   for (i = 0; i <= 255; i++) {
-
-      /*--
-         Process big buckets, starting with the least full.
-         Basically this is a 3-step process in which we call
-         mainQSort3 to sort the small buckets [ss, j], but
-         also make a big effort to avoid the calls if we can.
-      --*/
-      ss = runningOrder[i];
-
-      /*--
-         Step 1:
-         Complete the big bucket [ss] by quicksorting
-         any unsorted small buckets [ss, j], for j != ss.  
-         Hopefully previous pointer-scanning phases have already
-         completed many of the small buckets [ss, j], so
-         we don't have to sort them at all.
-      --*/
-      for (j = 0; j <= 255; j++) {
-         if (j != ss) {
-            sb = (ss << 8) + j;
-            if ( ! (ftab[sb] & SETMASK) ) {
-               Int32 lo = ftab[sb]   & CLEARMASK;
-               Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
-               if (hi > lo) {
-                  if (verb >= 4)
-                     VPrintf4 ( "        qsort [0x%x, 0x%x]   "
-                                "done %d   this %d\n",
-                                ss, j, numQSorted, hi - lo + 1 );
-                  mainQSort3 ( 
-                     ptr, block, quadrant, nblock, 
-                     lo, hi, BZ_N_RADIX, budget 
-                  );   
-                  numQSorted += (hi - lo + 1);
-                  if (*budget < 0) return;
-               }
-            }
-            ftab[sb] |= SETMASK;
-         }
-      }
-
-      AssertH ( !bigDone[ss], 1006 );
-
-      /*--
-         Step 2:
-         Now scan this big bucket [ss] so as to synthesise the
-         sorted order for small buckets [t, ss] for all t,
-         including, magically, the bucket [ss,ss] too.
-         This will avoid doing Real Work in subsequent Step 1's.
-      --*/
-      {
-         for (j = 0; j <= 255; j++) {
-            copyStart[j] =  ftab[(j << 8) + ss]     & CLEARMASK;
-            copyEnd  [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
-         }
-         for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
-            k = ptr[j]-1; if (k < 0) k += nblock;
-            c1 = block[k];
-            if (!bigDone[c1])
-               ptr[ copyStart[c1]++ ] = k;
-         }
-         for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
-            k = ptr[j]-1; if (k < 0) k += nblock;
-            c1 = block[k];
-            if (!bigDone[c1]) 
-               ptr[ copyEnd[c1]-- ] = k;
-         }
-      }
-
-      AssertH ( (copyStart[ss]-1 == copyEnd[ss])
-                || 
-                /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1.
-                   Necessity for this case is demonstrated by compressing 
-                   a sequence of approximately 48.5 million of character 
-                   251; 1.0.0/1.0.1 will then die here. */
-                (copyStart[ss] == 0 && copyEnd[ss] == nblock-1),
-                1007 )
-
-      for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
-
-      /*--
-         Step 3:
-         The [ss] big bucket is now done.  Record this fact,
-         and update the quadrant descriptors.  Remember to
-         update quadrants in the overshoot area too, if
-         necessary.  The "if (i < 255)" test merely skips
-         this updating for the last bucket processed, since
-         updating for the last bucket is pointless.
-
-         The quadrant array provides a way to incrementally
-         cache sort orderings, as they appear, so as to 
-         make subsequent comparisons in fullGtU() complete
-         faster.  For repetitive blocks this makes a big
-         difference (but not big enough to be able to avoid
-         the fallback sorting mechanism, exponential radix sort).
-
-         The precise meaning is: at all times:
-
-            for 0 <= i < nblock and 0 <= j <= nblock
-
-            if block[i] != block[j], 
-
-               then the relative values of quadrant[i] and 
-                    quadrant[j] are meaningless.
-
-               else {
-                  if quadrant[i] < quadrant[j]
-                     then the string starting at i lexicographically
-                     precedes the string starting at j
-
-                  else if quadrant[i] > quadrant[j]
-                     then the string starting at j lexicographically
-                     precedes the string starting at i
-
-                  else
-                     the relative ordering of the strings starting
-                     at i and j has not yet been determined.
-               }
-      --*/
-      bigDone[ss] = True;
-
-      if (i < 255) {
-         Int32 bbStart  = ftab[ss << 8] & CLEARMASK;
-         Int32 bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
-         Int32 shifts   = 0;
-
-         while ((bbSize >> shifts) > 65534) shifts++;
-
-         for (j = bbSize-1; j >= 0; j--) {
-            Int32 a2update     = ptr[bbStart + j];
-            UInt16 qVal        = (UInt16)(j >> shifts);
-            quadrant[a2update] = qVal;
-            if (a2update < BZ_N_OVERSHOOT)
-               quadrant[a2update + nblock] = qVal;
-         }
-         AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
-      }
-
-   }
-
-   if (verb >= 4)
-      VPrintf3 ( "        %d pointers, %d sorted, %d scanned\n",
-                 nblock, numQSorted, nblock - numQSorted );
-}
-
-#undef BIGFREQ
-#undef SETMASK
-#undef CLEARMASK
-
-
-/*---------------------------------------------*/
-/* Pre:
-      nblock > 0
-      arr2 exists for [0 .. nblock-1 +N_OVERSHOOT]
-      ((UChar*)arr2)  [0 .. nblock-1] holds block
-      arr1 exists for [0 .. nblock-1]
-
-   Post:
-      ((UChar*)arr2) [0 .. nblock-1] holds block
-      All other areas of block destroyed
-      ftab [ 0 .. 65536 ] destroyed
-      arr1 [0 .. nblock-1] holds sorted order
-*/
-void BZ2_blockSort ( EState* s )
-{
-   UInt32* ptr    = s->ptr; 
-   UChar*  block  = s->block;
-   UInt32* ftab   = s->ftab;
-   Int32   nblock = s->nblock;
-   Int32   verb   = s->verbosity;
-   Int32   wfact  = s->workFactor;
-   UInt16* quadrant;
-   Int32   budget;
-   Int32   budgetInit;
-   Int32   i;
-
-   if (nblock < /* 10000 */1000 ) {
-      fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
-   } else {
-      /* Calculate the location for quadrant, remembering to get
-         the alignment right.  Assumes that &(block[0]) is at least
-         2-byte aligned -- this should be ok since block is really
-         the first section of arr2.
-      */
-      i = nblock+BZ_N_OVERSHOOT;
-      if (i & 1) i++;
-      quadrant = (UInt16*)(&(block[i]));
-
-      /* (wfact-1) / 3 puts the default-factor-30
-         transition point at very roughly the same place as 
-         with v0.1 and v0.9.0.  
-         Not that it particularly matters any more, since the
-         resulting compressed stream is now the same regardless
-         of whether or not we use the main sort or fallback sort.
-      */
-      if (wfact < 1  ) wfact = 1;
-      if (wfact > 100) wfact = 100;
-      budgetInit = nblock * ((wfact-1) / 3);
-      budget = budgetInit;
-
-      mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget );
-      if (0 && verb >= 3) 
-         VPrintf3 ( "      %d work, %d block, ratio %5.2f\n",
-                    budgetInit - budget,
-                    nblock, 
-                    (float)(budgetInit - budget) /
-                    (float)(nblock==0 ? 1 : nblock) ); 
-      if (budget < 0) {
-         if (verb >= 2) 
-            VPrintf0 ( "    too repetitive; using fallback"
-                       " sorting algorithm\n" );
-         fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb );
-      }
-   }
-
-   s->origPtr = -1;
-   for (i = 0; i < s->nblock; i++)
-      if (ptr[i] == 0)
-         { s->origPtr = i; break; };
-
-   AssertH( s->origPtr != -1, 1003 );
-}
-
-
-/*-------------------------------------------------------------*/
-/*--- end                                       blocksort.c ---*/
-/*-------------------------------------------------------------*/
-
-/*-------------------------------------------------------------*/
-/*--- Huffman coding low-level stuff                        ---*/
-/*---                                             huffman.c ---*/
-/*-------------------------------------------------------------*/
-
-/*--
-  This file is a part of bzip2 and/or libbzip2, a program and
-  library for lossless, block-sorting data compression.
-
-  Copyright (C) 1996-2004 Julian R Seward.  All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-
-  2. The origin of this software must not be misrepresented; you must 
-     not claim that you wrote the original software.  If you use this 
-     software in a product, an acknowledgment in the product 
-     documentation would be appreciated but is not required.
-
-  3. Altered source versions must be plainly marked as such, and must
-     not be misrepresented as being the original software.
-
-  4. The name of the author may not be used to endorse or promote 
-     products derived from this software without specific prior written 
-     permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
-  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-  Julian Seward, Cambridge, UK.
-  jseward@bzip.org
-  bzip2/libbzip2 version 1.0 of 21 March 2000
-
-  This program is based on (at least) the work of:
-     Mike Burrows
-     David Wheeler
-     Peter Fenwick
-     Alistair Moffat
-     Radford Neal
-     Ian H. Witten
-     Robert Sedgewick
-     Jon L. Bentley
-
-  For more information on these sources, see the manual.
---*/
-
-
-
-/*---------------------------------------------------*/
-#define WEIGHTOF(zz0)  ((zz0) & 0xffffff00)
-#define DEPTHOF(zz1)   ((zz1) & 0x000000ff)
-#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
-
-#define ADDWEIGHTS(zw1,zw2)                           \
-   (WEIGHTOF(zw1)+WEIGHTOF(zw2)) |                    \
-   (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
-
-#define UPHEAP(z)                                     \
-{                                                     \
-   Int32 zz, tmp;                                     \
-   zz = z; tmp = heap[zz];                            \
-   while (weight[tmp] < weight[heap[zz >> 1]]) {      \
-      heap[zz] = heap[zz >> 1];                       \
-      zz >>= 1;                                       \
-   }                                                  \
-   heap[zz] = tmp;                                    \
-}
-
-#define DOWNHEAP(z)                                   \
-{                                                     \
-   Int32 zz, yy, tmp;                                 \
-   zz = z; tmp = heap[zz];                            \
-   while (True) {                                     \
-      yy = zz << 1;                                   \
-      if (yy > nHeap) break;                          \
-      if (yy < nHeap &&                               \
-          weight[heap[yy+1]] < weight[heap[yy]])      \
-         yy++;                                        \
-      if (weight[tmp] < weight[heap[yy]]) break;      \
-      heap[zz] = heap[yy];                            \
-      zz = yy;                                        \
-   }                                                  \
-   heap[zz] = tmp;                                    \
-}
-
-
-/*---------------------------------------------------*/
-void BZ2_hbMakeCodeLengths ( UChar *len, 
-                             Int32 *freq,
-                             Int32 alphaSize,
-                             Int32 maxLen )
-{
-   /*--
-      Nodes and heap entries run from 1.  Entry 0
-      for both the heap and nodes is a sentinel.
-   --*/
-   Int32 nNodes, nHeap, n1, n2, i, j, k;
-   Bool  tooLong;
-
-   Int32 heap   [ BZ_MAX_ALPHA_SIZE + 2 ];
-   Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
-   Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; 
-
-   for (i = 0; i < alphaSize; i++)
-      weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
-
-   while (True) {
-
-      nNodes = alphaSize;
-      nHeap = 0;
-
-      heap[0] = 0;
-      weight[0] = 0;
-      parent[0] = -2;
-
-      for (i = 1; i <= alphaSize; i++) {
-         parent[i] = -1;
-         nHeap++;
-         heap[nHeap] = i;
-         UPHEAP(nHeap);
-      }
-
-      AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
-   
-      while (nHeap > 1) {
-         n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
-         n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
-         nNodes++;
-         parent[n1] = parent[n2] = nNodes;
-         weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
-         parent[nNodes] = -1;
-         nHeap++;
-         heap[nHeap] = nNodes;
-         UPHEAP(nHeap);
-      }
-
-      AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
-
-      tooLong = False;
-      for (i = 1; i <= alphaSize; i++) {
-         j = 0;
-         k = i;
-         while (parent[k] >= 0) { k = parent[k]; j++; }
-         len[i-1] = j;
-         if (j > maxLen) tooLong = True;
-      }
-      
-      if (! tooLong) break;
-
-      /* 17 Oct 04: keep-going condition for the following loop used
-         to be 'i < alphaSize', which missed the last element,
-         theoretically leading to the possibility of the compressor
-         looping.  However, this count-scaling step is only needed if
-         one of the generated Huffman code words is longer than
-         maxLen, which up to and including version 1.0.2 was 20 bits,
-         which is extremely unlikely.  In version 1.0.3 maxLen was
-         changed to 17 bits, which has minimal effect on compression
-         ratio, but does mean this scaling step is used from time to
-         time, enough to verify that it works.
-
-         This means that bzip2-1.0.3 and later will only produce
-         Huffman codes with a maximum length of 17 bits.  However, in
-         order to preserve backwards compatibility with bitstreams
-         produced by versions pre-1.0.3, the decompressor must still
-         handle lengths of up to 20. */
-
-      for (i = 1; i <= alphaSize; i++) {
-         j = weight[i] >> 8;
-         j = 1 + (j / 2);
-         weight[i] = j << 8;
-      }
-   }
-}
-
-
-/*---------------------------------------------------*/
-void BZ2_hbAssignCodes ( Int32 *code,
-                         UChar *length,
-                         Int32 minLen,
-                         Int32 maxLen,
-                         Int32 alphaSize )
-{
-   Int32 n, vec, i;
-
-   vec = 0;
-   for (n = minLen; n <= maxLen; n++) {
-      for (i = 0; i < alphaSize; i++)
-         if (length[i] == n) { code[i] = vec; vec++; };
-      vec <<= 1;
-   }
-}
-
-
-/*---------------------------------------------------*/
-void BZ2_hbCreateDecodeTables ( Int32 *limit,
-                                Int32 *base,
-                                Int32 *perm,
-                                UChar *length,
-                                Int32 minLen,
-                                Int32 maxLen,
-                                Int32 alphaSize )
-{
-   Int32 pp, i, j, vec;
-
-   pp = 0;
-   for (i = minLen; i <= maxLen; i++)
-      for (j = 0; j < alphaSize; j++)
-         if (length[j] == i) { perm[pp] = j; pp++; };
-
-   for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
-   for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
-
-   for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
-
-   for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
-   vec = 0;
-
-   for (i = minLen; i <= maxLen; i++) {
-      vec += (base[i+1] - base[i]);
-      limit[i] = vec-1;
-      vec <<= 1;
-   }
-   for (i = minLen + 1; i <= maxLen; i++)
-      base[i] = ((limit[i-1] + 1) << 1) - base[i];
-}
-
-
-/*-------------------------------------------------------------*/
-/*--- end                                         huffman.c ---*/
-/*-------------------------------------------------------------*/
-
-/*-------------------------------------------------------------*/
-/*--- Compression machinery (not incl block sorting)        ---*/
-/*---                                            compress.c ---*/
-/*-------------------------------------------------------------*/
-
-/*--
-  This file is a part of bzip2 and/or libbzip2, a program and
-  library for lossless, block-sorting data compression.
-
-  Copyright (C) 1996-2004 Julian R Seward.  All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-
-  2. The origin of this software must not be misrepresented; you must 
-     not claim that you wrote the original software.  If you use this 
-     software in a product, an acknowledgment in the product 
-     documentation would be appreciated but is not required.
-
-  3. Altered source versions must be plainly marked as such, and must
-     not be misrepresented as being the original software.
-
-  4. The name of the author may not be used to endorse or promote 
-     products derived from this software without specific prior written 
-     permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
-  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-  Julian Seward, Cambridge, UK.
-  jseward@bzip.org
-  bzip2/libbzip2 version 1.0 of 21 March 2000
-
-  This program is based on (at least) the work of:
-     Mike Burrows
-     David Wheeler
-     Peter Fenwick
-     Alistair Moffat
-     Radford Neal
-     Ian H. Witten
-     Robert Sedgewick
-     Jon L. Bentley
-
-  For more information on these sources, see the manual.
---*/
-
-/*--
-   CHANGES
-   ~~~~~~~
-   0.9.0 -- original version.
-
-   0.9.0a/b -- no changes in this file.
-
-   0.9.0c
-      * changed setting of nGroups in sendMTFValues() so as to 
-        do a bit better on small files
---*/
-
-
-
-/*---------------------------------------------------*/
-/*--- Bit stream I/O                              ---*/
-/*---------------------------------------------------*/
-
-/*---------------------------------------------------*/
-void BZ2_bsInitWrite ( EState* s )
-{
-   s->bsLive = 0;
-   s->bsBuff = 0;
-}
-
-
-/*---------------------------------------------------*/
-static
-void bsFinishWrite ( EState* s )
-{
-   while (s->bsLive > 0) {
-      s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
-      s->numZ++;
-      s->bsBuff <<= 8;
-      s->bsLive -= 8;
-   }
-}
-
-
-/*---------------------------------------------------*/
-#define bsNEEDW(nz)                           \
-{                                             \
-   while (s->bsLive >= 8) {                   \
-      s->zbits[s->numZ]                       \
-         = (UChar)(s->bsBuff >> 24);          \
-      s->numZ++;                              \
-      s->bsBuff <<= 8;                        \
-      s->bsLive -= 8;                         \
-   }                                          \
-}
-
-
-/*---------------------------------------------------*/
-static
-__inline__
-void bsW ( EState* s, Int32 n, UInt32 v )
-{
-   bsNEEDW ( n );
-   s->bsBuff |= (v << (32 - s->bsLive - n));
-   s->bsLive += n;
-}
-
-
-/*---------------------------------------------------*/
-static
-void bsPutUInt32 ( EState* s, UInt32 u )
-{
-   bsW ( s, 8, (u >> 24) & 0xffL );
-   bsW ( s, 8, (u >> 16) & 0xffL );
-   bsW ( s, 8, (u >>  8) & 0xffL );
-   bsW ( s, 8,  u        & 0xffL );
-}
-
-
-/*---------------------------------------------------*/
-static
-void bsPutUChar ( EState* s, UChar c )
-{
-   bsW( s, 8, (UInt32)c );
-}
-
-
-/*---------------------------------------------------*/
-/*--- The back end proper                         ---*/
-/*---------------------------------------------------*/
-
-/*---------------------------------------------------*/
-static
-void makeMaps_e ( EState* s )
-{
-   Int32 i;
-   s->nInUse = 0;
-   for (i = 0; i < 256; i++)
-      if (s->inUse[i]) {
-         s->unseqToSeq[i] = s->nInUse;
-         s->nInUse++;
-      }
-}
-
-
-/*---------------------------------------------------*/
-static
-void generateMTFValues ( EState* s )
-{
-   UChar   yy[256];
-   Int32   i, j;
-   Int32   zPend;
-   Int32   wr;
-   Int32   EOB;
-
-   /* 
-      After sorting (eg, here),
-         s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
-         and
-         ((UChar*)s->arr2) [ 0 .. s->nblock-1 ] 
-         holds the original block data.
-
-      The first thing to do is generate the MTF values,
-      and put them in
-         ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
-      Because there are strictly fewer or equal MTF values
-      than block values, ptr values in this area are overwritten
-      with MTF values only when they are no longer needed.
-
-      The final compressed bitstream is generated into the
-      area starting at
-         (UChar*) (&((UChar*)s->arr2)[s->nblock])
-
-      These storage aliases are set up in bzCompressInit(),
-      except for the last one, which is arranged in 
-      compressBlock().
-   */
-   UInt32* ptr   = s->ptr;
-   UChar* block  = s->block;
-   UInt16* mtfv  = s->mtfv;
-
-   makeMaps_e ( s );
-   EOB = s->nInUse+1;
-
-   for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
-
-   wr = 0;
-   zPend = 0;
-   for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
-
-   for (i = 0; i < s->nblock; i++) {
-      UChar ll_i;
-      AssertD ( wr <= i, "generateMTFValues(1)" );
-      j = ptr[i]-1; if (j < 0) j += s->nblock;
-      ll_i = s->unseqToSeq[block[j]];
-      AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
-
-      if (yy[0] == ll_i) { 
-         zPend++;
-      } else {
-
-         if (zPend > 0) {
-            zPend--;
-            while (True) {
-               if (zPend & 1) {
-                  mtfv[wr] = BZ_RUNB; wr++; 
-                  s->mtfFreq[BZ_RUNB]++; 
-               } else {
-                  mtfv[wr] = BZ_RUNA; wr++; 
-                  s->mtfFreq[BZ_RUNA]++; 
-               }
-               if (zPend < 2) break;
-               zPend = (zPend - 2) / 2;
-            };
-            zPend = 0;
-         }
-         {
-            register UChar  rtmp;
-            register UChar* ryy_j;
-            register UChar  rll_i;
-            rtmp  = yy[1];
-            yy[1] = yy[0];
-            ryy_j = &(yy[1]);
-            rll_i = ll_i;
-            while ( rll_i != rtmp ) {
-               register UChar rtmp2;
-               ryy_j++;
-               rtmp2  = rtmp;
-               rtmp   = *ryy_j;
-               *ryy_j = rtmp2;
-            };
-            yy[0] = rtmp;
-            j = ryy_j - &(yy[0]);
-            mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
-         }
-
-      }
-   }
-
-   if (zPend > 0) {
-      zPend--;
-      while (True) {
-         if (zPend & 1) {
-            mtfv[wr] = BZ_RUNB; wr++; 
-            s->mtfFreq[BZ_RUNB]++; 
-         } else {
-            mtfv[wr] = BZ_RUNA; wr++; 
-            s->mtfFreq[BZ_RUNA]++; 
-         }
-         if (zPend < 2) break;
-         zPend = (zPend - 2) / 2;
-      };
-      zPend = 0;
-   }
-
-   mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
-
-   s->nMTF = wr;
-}
-
-
-/*---------------------------------------------------*/
-#define BZ_LESSER_ICOST  0
-#define BZ_GREATER_ICOST 15
-
-static
-void sendMTFValues ( EState* s )
-{
-   Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
-   Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
-   Int32 nGroups, nBytes;
-
-   /*--
-   UChar  len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
-   is a global since the decoder also needs it.
-
-   Int32  code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
-   Int32  rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
-   are also globals only used in this proc.
-   Made global to keep stack frame size small.
-   --*/
-
-
-   UInt16 cost[BZ_N_GROUPS];
-   Int32  fave[BZ_N_GROUPS];
-
-   UInt16* mtfv = s->mtfv;
-
-   if (s->verbosity >= 3)
-      VPrintf3( "      %d in block, %d after MTF & 1-2 coding, "
-                "%d+2 syms in use\n", 
-                s->nblock, s->nMTF, s->nInUse );
-
-   alphaSize = s->nInUse+2;
-   for (t = 0; t < BZ_N_GROUPS; t++)
-      for (v = 0; v < alphaSize; v++)
-         s->len[t][v] = BZ_GREATER_ICOST;
-
-   /*--- Decide how many coding tables to use ---*/
-   AssertH ( s->nMTF > 0, 3001 );
-   if (s->nMTF < 200)  nGroups = 2; else
-   if (s->nMTF < 600)  nGroups = 3; else
-   if (s->nMTF < 1200) nGroups = 4; else
-   if (s->nMTF < 2400) nGroups = 5; else
-                       nGroups = 6;
-
-   /*--- Generate an initial set of coding tables ---*/
-   { 
-      Int32 nPart, remF, tFreq, aFreq;
-
-      nPart = nGroups;
-      remF  = s->nMTF;
-      gs = 0;
-      while (nPart > 0) {
-         tFreq = remF / nPart;
-         ge = gs-1;
-         aFreq = 0;
-         while (aFreq < tFreq && ge < alphaSize-1) {
-            ge++;
-            aFreq += s->mtfFreq[ge];
-         }
-
-         if (ge > gs 
-             && nPart != nGroups && nPart != 1 
-             && ((nGroups-nPart) % 2 == 1)) {
-            aFreq -= s->mtfFreq[ge];
-            ge--;
-         }
-
-         if (0 && s->verbosity >= 3)
-            VPrintf5( "      initial group %d, [%d .. %d], "
-                      "has %d syms (%4.1f%%)\n",
-                      nPart, gs, ge, aFreq, 
-                      (100.0 * (float)aFreq) / (float)(s->nMTF) );
-         for (v = 0; v < alphaSize; v++)
-            if (v >= gs && v <= ge) 
-               s->len[nPart-1][v] = BZ_LESSER_ICOST; else
-               s->len[nPart-1][v] = BZ_GREATER_ICOST;
-         nPart--;
-         gs = ge+1;
-         remF -= aFreq;
-      }
-   }
-
-   /*--- 
-      Iterate up to BZ_N_ITERS times to improve the tables.
-   ---*/
-   for (iter = 0; iter < BZ_N_ITERS; iter++) {
-
-      for (t = 0; t < nGroups; t++) fave[t] = 0;
-
-      for (t = 0; t < nGroups; t++)
-         for (v = 0; v < alphaSize; v++)
-            s->rfreq[t][v] = 0;
-
-      /*---
-        Set up an auxiliary length table which is used to fast-track
-       the common case (nGroups == 6). 
-      ---*/
-      if (nGroups == 6) {
-         for (v = 0; v < alphaSize; v++) {
-            s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
-            s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
-            s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
-        }
-      }
-
-      nSelectors = 0;
-      totc = 0;
-      gs = 0;
-      while (True) {
-
-         /*--- Set group start & end marks. --*/
-         if (gs >= s->nMTF) break;
-         ge = gs + BZ_G_SIZE - 1; 
-         if (ge >= s->nMTF) ge = s->nMTF-1;
-
-         /*-- 
-            Calculate the cost of this group as coded
-            by each of the coding tables.
-         --*/
-         for (t = 0; t < nGroups; t++) cost[t] = 0;
-
-         if (nGroups == 6 && 50 == ge-gs+1) {
-            /*--- fast track the common case ---*/
-            register UInt32 cost01, cost23, cost45;
-            register UInt16 icv;
-            cost01 = cost23 = cost45 = 0;
-
-#           define BZ_ITER(nn)                \
-               icv = mtfv[gs+(nn)];           \
-               cost01 += s->len_pack[icv][0]; \
-               cost23 += s->len_pack[icv][1]; \
-               cost45 += s->len_pack[icv][2]; \
-
-            BZ_ITER(0);  BZ_ITER(1);  BZ_ITER(2);  BZ_ITER(3);  BZ_ITER(4);
-            BZ_ITER(5);  BZ_ITER(6);  BZ_ITER(7);  BZ_ITER(8);  BZ_ITER(9);
-            BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
-            BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
-            BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
-            BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
-            BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
-            BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
-            BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
-            BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
-
-#           undef BZ_ITER
-
-            cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
-            cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
-            cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
-
-         } else {
-           /*--- slow version which correctly handles all situations ---*/
-            for (i = gs; i <= ge; i++) { 
-               UInt16 icv = mtfv[i];
-               for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
-            }
-         }
-         /*-- 
-            Find the coding table which is best for this group,
-            and record its identity in the selector table.
-         --*/
-         bc = 999999999; bt = -1;
-         for (t = 0; t < nGroups; t++)
-            if (cost[t] < bc) { bc = cost[t]; bt = t; };
-         totc += bc;
-         fave[bt]++;
-         s->selector[nSelectors] = bt;
-         nSelectors++;
-
-         /*-- 
-            Increment the symbol frequencies for the selected table.
-          --*/
-         if (nGroups == 6 && 50 == ge-gs+1) {
-            /*--- fast track the common case ---*/
-
-#           define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
-
-            BZ_ITUR(0);  BZ_ITUR(1);  BZ_ITUR(2);  BZ_ITUR(3);  BZ_ITUR(4);
-            BZ_ITUR(5);  BZ_ITUR(6);  BZ_ITUR(7);  BZ_ITUR(8);  BZ_ITUR(9);
-            BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
-            BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
-            BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
-            BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
-            BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
-            BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
-            BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
-            BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
-
-#           undef BZ_ITUR
-
-         } else {
-           /*--- slow version which correctly handles all situations ---*/
-            for (i = gs; i <= ge; i++)
-               s->rfreq[bt][ mtfv[i] ]++;
-         }
-
-         gs = ge+1;
-      }
-      if (s->verbosity >= 3) {
-         VPrintf2 ( "      pass %d: size is %d, grp uses are ", 
-                   iter+1, totc/8 );
-         for (t = 0; t < nGroups; t++)
-            VPrintf1 ( "%d ", fave[t] );
-         VPrintf0 ( "\n" );
-      }
-
-      /*--
-        Recompute the tables based on the accumulated frequencies.
-      --*/
-      /* maxLen was changed from 20 to 17 in bzip2-1.0.3.  See 
-         comment in huffman.c for details. */
-      for (t = 0; t < nGroups; t++)
-         BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), 
-                                 alphaSize, 17 /*20*/ );
-   }
-
-
-   AssertH( nGroups < 8, 3002 );
-   AssertH( nSelectors < 32768 &&
-            nSelectors <= (2 + (900000 / BZ_G_SIZE)),
-            3003 );
-
-
-   /*--- Compute MTF values for the selectors. ---*/
-   {
-      UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
-      for (i = 0; i < nGroups; i++) pos[i] = i;
-      for (i = 0; i < nSelectors; i++) {
-         ll_i = s->selector[i];
-         j = 0;
-         tmp = pos[j];
-         while ( ll_i != tmp ) {
-            j++;
-            tmp2 = tmp;
-            tmp = pos[j];
-            pos[j] = tmp2;
-         };
-         pos[0] = tmp;
-         s->selectorMtf[i] = j;
-      }
-   };
-
-   /*--- Assign actual codes for the tables. --*/
-   for (t = 0; t < nGroups; t++) {
-      minLen = 32;
-      maxLen = 0;
-      for (i = 0; i < alphaSize; i++) {
-         if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
-         if (s->len[t][i] < minLen) minLen = s->len[t][i];
-      }
-      AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
-      AssertH ( !(minLen < 1),  3005 );
-      BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), 
-                          minLen, maxLen, alphaSize );
-   }
-
-   /*--- Transmit the mapping table. ---*/
-   { 
-      Bool inUse16[16];
-      for (i = 0; i < 16; i++) {
-          inUse16[i] = False;
-          for (j = 0; j < 16; j++)
-             if (s->inUse[i * 16 + j]) inUse16[i] = True;
-      }
-     
-      nBytes = s->numZ;
-      for (i = 0; i < 16; i++)
-         if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
-
-      for (i = 0; i < 16; i++)
-         if (inUse16[i])
-            for (j = 0; j < 16; j++) {
-               if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
-            }
-
-      if (s->verbosity >= 3) 
-         VPrintf1( "      bytes: mapping %d, ", s->numZ-nBytes );
-   }
-
-   /*--- Now the selectors. ---*/
-   nBytes = s->numZ;
-   bsW ( s, 3, nGroups );
-   bsW ( s, 15, nSelectors );
-   for (i = 0; i < nSelectors; i++) { 
-      for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
-      bsW(s,1,0);
-   }
-   if (s->verbosity >= 3)
-      VPrintf1( "selectors %d, ", s->numZ-nBytes );
-
-   /*--- Now the coding tables. ---*/
-   nBytes = s->numZ;
-
-   for (t = 0; t < nGroups; t++) {
-      Int32 curr = s->len[t][0];
-      bsW ( s, 5, curr );
-      for (i = 0; i < alphaSize; i++) {
-         while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
-         while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
-         bsW ( s, 1, 0 );
-      }
-   }
-
-   if (s->verbosity >= 3)
-      VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
-
-   /*--- And finally, the block data proper ---*/
-   nBytes = s->numZ;
-   selCtr = 0;
-   gs = 0;
-   while (True) {
-      if (gs >= s->nMTF) break;
-      ge = gs + BZ_G_SIZE - 1; 
-      if (ge >= s->nMTF) ge = s->nMTF-1;
-      AssertH ( s->selector[selCtr] < nGroups, 3006 );
-
-      if (nGroups == 6 && 50 == ge-gs+1) {
-            /*--- fast track the common case ---*/
-            UInt16 mtfv_i;
-            UChar* s_len_sel_selCtr 
-               = &(s->len[s->selector[selCtr]][0]);
-            Int32* s_code_sel_selCtr
-               = &(s->code[s->selector[selCtr]][0]);
-
-#           define BZ_ITAH(nn)                      \
-               mtfv_i = mtfv[gs+(nn)];              \
-               bsW ( s,                             \
-                     s_len_sel_selCtr[mtfv_i],      \
-                     s_code_sel_selCtr[mtfv_i] )
-
-            BZ_ITAH(0);  BZ_ITAH(1);  BZ_ITAH(2);  BZ_ITAH(3);  BZ_ITAH(4);
-            BZ_ITAH(5);  BZ_ITAH(6);  BZ_ITAH(7);  BZ_ITAH(8);  BZ_ITAH(9);
-            BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
-            BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
-            BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
-            BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
-            BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
-            BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
-            BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
-            BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
-
-#           undef BZ_ITAH
-
-      } else {
-        /*--- slow version which correctly handles all situations ---*/
-         for (i = gs; i <= ge; i++) {
-            bsW ( s, 
-                  s->len  [s->selector[selCtr]] [mtfv[i]],
-                  s->code [s->selector[selCtr]] [mtfv[i]] );
-         }
-      }
-
-
-      gs = ge+1;
-      selCtr++;
-   }
-   AssertH( selCtr == nSelectors, 3007 );
-
-   if (s->verbosity >= 3)
-      VPrintf1( "codes %d\n", s->numZ-nBytes );
-}
-
-
-/*---------------------------------------------------*/
-void BZ2_compressBlock ( EState* s, Bool is_last_block )
-{
-   if (s->nblock > 0) {
-
-      BZ_FINALISE_CRC ( s->blockCRC );
-      s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
-      s->combinedCRC ^= s->blockCRC;
-      if (s->blockNo > 1) s->numZ = 0;
-
-      if (s->verbosity >= 2)
-         VPrintf4( "    block %d: crc = 0x%08x, "
-                   "combined CRC = 0x%08x, size = %d\n",
-                   s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
-
-      BZ2_blockSort ( s );
-   }
-
-   s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
-
-   /*-- If this is the first block, create the stream header. --*/
-   if (s->blockNo == 1) {
-      BZ2_bsInitWrite ( s );
-      bsPutUChar ( s, BZ_HDR_B );
-      bsPutUChar ( s, BZ_HDR_Z );
-      bsPutUChar ( s, BZ_HDR_h );
-      bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
-   }
-
-   if (s->nblock > 0) {
-
-      bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
-      bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
-      bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
-
-      /*-- Now the block's CRC, so it is in a known place. --*/
-      bsPutUInt32 ( s, s->blockCRC );
-
-      /*-- 
-         Now a single bit indicating (non-)randomisation. 
-         As of version 0.9.5, we use a better sorting algorithm
-         which makes randomisation unnecessary.  So always set
-         the randomised bit to 'no'.  Of course, the decoder
-         still needs to be able to handle randomised blocks
-         so as to maintain backwards compatibility with
-         older versions of bzip2.
-      --*/
-      bsW(s,1,0);
-
-      bsW ( s, 24, s->origPtr );
-      generateMTFValues ( s );
-      sendMTFValues ( s );
-   }
-
-
-   /*-- If this is the last block, add the stream trailer. --*/
-   if (is_last_block) {
-
-      bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
-      bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
-      bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
-      bsPutUInt32 ( s, s->combinedCRC );
-      if (s->verbosity >= 2)
-         VPrintf1( "    final combined CRC = 0x%08x\n   ", s->combinedCRC );
-      bsFinishWrite ( s );
-   }
-}
-
-
-/*-------------------------------------------------------------*/
-/*--- end                                        compress.c ---*/
-/*-------------------------------------------------------------*/
-
-
-/*-------------------------------------------------------------*/
-/*--- Table for randomising repetitive blocks               ---*/
-/*---                                           randtable.c ---*/
-/*-------------------------------------------------------------*/
-
-/*--
-  This file is a part of bzip2 and/or libbzip2, a program and
-  library for lossless, block-sorting data compression.
-
-  Copyright (C) 1996-2004 Julian R Seward.  All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-
-  2. The origin of this software must not be misrepresented; you must 
-     not claim that you wrote the original software.  If you use this 
-     software in a product, an acknowledgment in the product 
-     documentation would be appreciated but is not required.
-
-  3. Altered source versions must be plainly marked as such, and must
-     not be misrepresented as being the original software.
-
-  4. The name of the author may not be used to endorse or promote 
-     products derived from this software without specific prior written 
-     permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
-  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-  Julian Seward, Cambridge, UK.
-  jseward@bzip.org
-  bzip2/libbzip2 version 1.0 of 21 March 2000
-
-  This program is based on (at least) the work of:
-     Mike Burrows
-     David Wheeler
-     Peter Fenwick
-     Alistair Moffat
-     Radford Neal
-     Ian H. Witten
-     Robert Sedgewick
-     Jon L. Bentley
-
-  For more information on these sources, see the manual.
---*/
-
-
-
-
-/*---------------------------------------------*/
-Int32 BZ2_rNums[512] = { 
-   619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 
-   985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 
-   733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 
-   419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 
-   878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 
-   862, 687, 507, 283, 482, 129, 807, 591, 733, 623, 
-   150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 
-   170, 607, 520, 932, 727, 476, 693, 425, 174, 647, 
-   73, 122, 335, 530, 442, 853, 695, 249, 445, 515, 
-   909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 
-   641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 
-   161, 604, 958, 533, 221, 400, 386, 867, 600, 782, 
-   382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 
-   98, 553, 163, 354, 666, 933, 424, 341, 533, 870, 
-   227, 730, 475, 186, 263, 647, 537, 686, 600, 224, 
-   469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 
-   184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 
-   715, 67, 618, 276, 204, 918, 873, 777, 604, 560, 
-   951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 
-   652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 
-   645, 863, 803, 350, 139, 93, 354, 99, 820, 908, 
-   609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 
-   653, 282, 762, 623, 680, 81, 927, 626, 789, 125, 
-   411, 521, 938, 300, 821, 78, 343, 175, 128, 250, 
-   170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 
-   857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 
-   669, 112, 134, 694, 363, 992, 809, 743, 168, 974, 
-   944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 
-   344, 805, 988, 739, 511, 655, 814, 334, 249, 515, 
-   897, 955, 664, 981, 649, 113, 974, 459, 893, 228, 
-   433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 
-   686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 
-   946, 670, 656, 610, 738, 392, 760, 799, 887, 653, 
-   978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 
-   680, 879, 194, 572, 640, 724, 926, 56, 204, 700, 
-   707, 151, 457, 449, 797, 195, 791, 558, 945, 679, 
-   297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 
-   134, 108, 571, 364, 631, 212, 174, 643, 304, 329, 
-   343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 
-   140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 
-   170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 
-   369, 970, 294, 750, 807, 827, 150, 790, 288, 923, 
-   804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 
-   896, 831, 547, 261, 524, 462, 293, 465, 502, 56, 
-   661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 
-   768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 
-   61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 
-   372, 567, 466, 434, 645, 210, 389, 550, 919, 135, 
-   780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 
-   920, 176, 193, 713, 857, 265, 203, 50, 668, 108, 
-   645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 
-   936, 638
-};
-
-
-/*-------------------------------------------------------------*/
-/*--- end                                       randtable.c ---*/
-/*-------------------------------------------------------------*/
-
-/*-------------------------------------------------------------*/
-/*--- Table for doing CRCs                                  ---*/
-/*---                                            crctable.c ---*/
-/*-------------------------------------------------------------*/
-
-/*--
-  This file is a part of bzip2 and/or libbzip2, a program and
-  library for lossless, block-sorting data compression.
-
-  Copyright (C) 1996-2004 Julian R Seward.  All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-
-  2. The origin of this software must not be misrepresented; you must 
-     not claim that you wrote the original software.  If you use this 
-     software in a product, an acknowledgment in the product 
-     documentation would be appreciated but is not required.
-
-  3. Altered source versions must be plainly marked as such, and must
-     not be misrepresented as being the original software.
-
-  4. The name of the author may not be used to endorse or promote 
-     products derived from this software without specific prior written 
-     permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
-  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-  Julian Seward, Cambridge, UK.
-  jseward@bzip.org
-  bzip2/libbzip2 version 1.0 of 21 March 2000
-
-  This program is based on (at least) the work of:
-     Mike Burrows
-     David Wheeler
-     Peter Fenwick
-     Alistair Moffat
-     Radford Neal
-     Ian H. Witten
-     Robert Sedgewick
-     Jon L. Bentley
-
-  For more information on these sources, see the manual.
---*/
-
-
-
-
-
-/*--
-  I think this is an implementation of the AUTODIN-II,
-  Ethernet & FDDI 32-bit CRC standard.  Vaguely derived
-  from code by Rob Warnock, in Section 51 of the
-  comp.compression FAQ.
---*/
-
-UInt32 BZ2_crc32Table[256] = {
-
-   /*-- Ugly, innit? --*/
-
-   0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
-   0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
-   0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
-   0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
-   0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
-   0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
-   0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
-   0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
-   0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
-   0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
-   0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
-   0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
-   0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
-   0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
-   0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
-   0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
-   0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
-   0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
-   0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
-   0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
-   0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
-   0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
-   0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
-   0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
-   0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
-   0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
-   0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
-   0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
-   0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
-   0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
-   0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
-   0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
-   0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
-   0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
-   0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
-   0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
-   0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
-   0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
-   0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
-   0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
-   0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
-   0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
-   0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
-   0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
-   0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
-   0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
-   0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
-   0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
-   0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
-   0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
-   0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
-   0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
-   0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
-   0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
-   0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
-   0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
-   0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
-   0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
-   0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
-   0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
-   0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
-   0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
-   0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
-   0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
-};
-
-
-/*-------------------------------------------------------------*/
-/*--- end                                        crctable.c ---*/
-/*-------------------------------------------------------------*/
-
-/*-------------------------------------------------------------*/
-/*--- Library top-level functions.                          ---*/
-/*---                                               bzlib.c ---*/
-/*-------------------------------------------------------------*/
-
-/*--
-  This file is a part of bzip2 and/or libbzip2, a program and
-  library for lossless, block-sorting data compression.
-
-  Copyright (C) 1996-2004 Julian R Seward.  All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-
-  2. The origin of this software must not be misrepresented; you must 
-     not claim that you wrote the original software.  If you use this 
-     software in a product, an acknowledgment in the product 
-     documentation would be appreciated but is not required.
-
-  3. Altered source versions must be plainly marked as such, and must
-     not be misrepresented as being the original software.
-
-  4. The name of the author may not be used to endorse or promote 
-     products derived from this software without specific prior written 
-     permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
-  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-  Julian Seward, Cambridge, UK.
-  jseward@bzip.org
-  bzip2/libbzip2 version 1.0 of 21 March 2000
-
-  This program is based on (at least) the work of:
-     Mike Burrows
-     David Wheeler
-     Peter Fenwick
-     Alistair Moffat
-     Radford Neal
-     Ian H. Witten
-     Robert Sedgewick
-     Jon L. Bentley
-
-  For more information on these sources, see the manual.
---*/
-
-/*--
-   CHANGES
-   ~~~~~~~
-   0.9.0 -- original version.
-
-   0.9.0a/b -- no changes in this file.
-
-   0.9.0c
-      * made zero-length BZ_FLUSH work correctly in bzCompress().
-      * fixed bzWrite/bzRead to ignore zero-length requests.
-      * fixed bzread to correctly handle read requests after EOF.
-      * wrong parameter order in call to bzDecompressInit in
-        bzBuffToBuffDecompress.  Fixed.
---*/
-
-
-
-/*---------------------------------------------------*/
-/*--- Compression stuff                           ---*/
-/*---------------------------------------------------*/
-
-
-/*---------------------------------------------------*/
-void BZ2_bz__AssertH__fail ( int errcode )
-{
-   vex_printf("BZ2_bz__AssertH__fail(%d) called, exiting\n", errcode);
-   (*serviceFn)(0,0);
-}
-
-void bz_internal_error ( int errcode )
-{
-   vex_printf("bz_internal_error called, exiting\n", errcode);
-   (*serviceFn)(0,0);
-}
-
-/*---------------------------------------------------*/
-static
-int bz_config_ok ( void )
-{
-   if (sizeof(int)   != 4) return 0;
-   if (sizeof(short) != 2) return 0;
-   if (sizeof(char)  != 1) return 0;
-   return 1;
-}
-
-
-/*---------------------------------------------------*/
-static
-void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
-{
-   void* v = (void*) (*serviceFn)(2, items * size );
-   return v;
-}
-
-static
-void default_bzfree ( void* opaque, void* addr )
-{
-   if (addr != NULL) (*serviceFn)( 3, (HWord)addr );
-}
-
-
-/*---------------------------------------------------*/
-static
-void prepare_new_block ( EState* s )
-{
-   Int32 i;
-   s->nblock = 0;
-   s->numZ = 0;
-   s->state_out_pos = 0;
-   BZ_INITIALISE_CRC ( s->blockCRC );
-   for (i = 0; i < 256; i++) s->inUse[i] = False;
-   s->blockNo++;
-}
-
-
-/*---------------------------------------------------*/
-static
-void init_RL ( EState* s )
-{
-   s->state_in_ch  = 256;
-   s->state_in_len = 0;
-}
-
-
-static
-Bool isempty_RL ( EState* s )
-{
-   if (s->state_in_ch < 256 && s->state_in_len > 0)
-      return False; else
-      return True;
-}
-
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzCompressInit) 
-                    ( bz_stream* strm, 
-                     int        blockSize100k,
-                     int        verbosity,
-                     int        workFactor )
-{
-   Int32   n;
-   EState* s;
-
-   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
-
-   if (strm == NULL || 
-       blockSize100k < 1 || blockSize100k > 9 ||
-       workFactor < 0 || workFactor > 250)
-     return BZ_PARAM_ERROR;
-
-   if (workFactor == 0) workFactor = 30;
-   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
-   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
-
-   s = BZALLOC( sizeof(EState) );
-   if (s == NULL) return BZ_MEM_ERROR;
-   s->strm = strm;
-
-   s->arr1 = NULL;
-   s->arr2 = NULL;
-   s->ftab = NULL;
-
-   n       = 100000 * blockSize100k;
-   s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
-   s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
-   s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
-
-   if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
-      if (s->arr1 != NULL) BZFREE(s->arr1);
-      if (s->arr2 != NULL) BZFREE(s->arr2);
-      if (s->ftab != NULL) BZFREE(s->ftab);
-      if (s       != NULL) BZFREE(s);
-      return BZ_MEM_ERROR;
-   }
-
-   s->blockNo           = 0;
-   s->state             = BZ_S_INPUT;
-   s->mode              = BZ_M_RUNNING;
-   s->combinedCRC       = 0;
-   s->blockSize100k     = blockSize100k;
-   s->nblockMAX         = 100000 * blockSize100k - 19;
-   s->verbosity         = verbosity;
-   s->workFactor        = workFactor;
-
-   s->block             = (UChar*)s->arr2;
-   s->mtfv              = (UInt16*)s->arr1;
-   s->zbits             = NULL;
-   s->ptr               = (UInt32*)s->arr1;
-
-   strm->state          = s;
-   strm->total_in_lo32  = 0;
-   strm->total_in_hi32  = 0;
-   strm->total_out_lo32 = 0;
-   strm->total_out_hi32 = 0;
-   init_RL ( s );
-   prepare_new_block ( s );
-   return BZ_OK;
-}
-
-
-/*---------------------------------------------------*/
-static
-void add_pair_to_block ( EState* s )
-{
-   Int32 i;
-   UChar ch = (UChar)(s->state_in_ch);
-   for (i = 0; i < s->state_in_len; i++) {
-      BZ_UPDATE_CRC( s->blockCRC, ch );
-   }
-   s->inUse[s->state_in_ch] = True;
-   switch (s->state_in_len) {
-      case 1:
-         s->block[s->nblock] = (UChar)ch; s->nblock++;
-         break;
-      case 2:
-         s->block[s->nblock] = (UChar)ch; s->nblock++;
-         s->block[s->nblock] = (UChar)ch; s->nblock++;
-         break;
-      case 3:
-         s->block[s->nblock] = (UChar)ch; s->nblock++;
-         s->block[s->nblock] = (UChar)ch; s->nblock++;
-         s->block[s->nblock] = (UChar)ch; s->nblock++;
-         break;
-      default:
-         s->inUse[s->state_in_len-4] = True;
-         s->block[s->nblock] = (UChar)ch; s->nblock++;
-         s->block[s->nblock] = (UChar)ch; s->nblock++;
-         s->block[s->nblock] = (UChar)ch; s->nblock++;
-         s->block[s->nblock] = (UChar)ch; s->nblock++;
-         s->block[s->nblock] = ((UChar)(s->state_in_len-4));
-         s->nblock++;
-         break;
-   }
-}
-
-
-/*---------------------------------------------------*/
-static
-void flush_RL ( EState* s )
-{
-   if (s->state_in_ch < 256) add_pair_to_block ( s );
-   init_RL ( s );
-}
-
-
-/*---------------------------------------------------*/
-#define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
-{                                                 \
-   UInt32 zchh = (UInt32)(zchh0);                 \
-   /*-- fast track the common case --*/           \
-   if (zchh != zs->state_in_ch &&                 \
-       zs->state_in_len == 1) {                   \
-      UChar ch = (UChar)(zs->state_in_ch);        \
-      BZ_UPDATE_CRC( zs->blockCRC, ch );          \
-      zs->inUse[zs->state_in_ch] = True;          \
-      zs->block[zs->nblock] = (UChar)ch;          \
-      zs->nblock++;                               \
-      zs->state_in_ch = zchh;                     \
-   }                                              \
-   else                                           \
-   /*-- general, uncommon cases --*/              \
-   if (zchh != zs->state_in_ch ||                 \
-      zs->state_in_len == 255) {                  \
-      if (zs->state_in_ch < 256)                  \
-         add_pair_to_block ( zs );                \
-      zs->state_in_ch = zchh;                     \
-      zs->state_in_len = 1;                       \
-   } else {                                       \
-      zs->state_in_len++;                         \
-   }                                              \
-}
-
-
-/*---------------------------------------------------*/
-static
-Bool copy_input_until_stop ( EState* s )
-{
-   Bool progress_in = False;
-
-   if (s->mode == BZ_M_RUNNING) {
-
-      /*-- fast track the common case --*/
-      while (True) {
-         /*-- block full? --*/
-         if (s->nblock >= s->nblockMAX) break;
-         /*-- no input? --*/
-         if (s->strm->avail_in == 0) break;
-         progress_in = True;
-         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
-         s->strm->next_in++;
-         s->strm->avail_in--;
-         s->strm->total_in_lo32++;
-         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
-      }
-
-   } else {
-
-      /*-- general, uncommon case --*/
-      while (True) {
-         /*-- block full? --*/
-         if (s->nblock >= s->nblockMAX) break;
-         /*-- no input? --*/
-         if (s->strm->avail_in == 0) break;
-         /*-- flush/finish end? --*/
-         if (s->avail_in_expect == 0) break;
-         progress_in = True;
-         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); 
-         s->strm->next_in++;
-         s->strm->avail_in--;
-         s->strm->total_in_lo32++;
-         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
-         s->avail_in_expect--;
-      }
-   }
-   return progress_in;
-}
-
-
-/*---------------------------------------------------*/
-static
-Bool copy_output_until_stop ( EState* s )
-{
-   Bool progress_out = False;
-
-   while (True) {
-
-      /*-- no output space? --*/
-      if (s->strm->avail_out == 0) break;
-
-      /*-- block done? --*/
-      if (s->state_out_pos >= s->numZ) break;
-
-      progress_out = True;
-      *(s->strm->next_out) = s->zbits[s->state_out_pos];
-      s->state_out_pos++;
-      s->strm->avail_out--;
-      s->strm->next_out++;
-      s->strm->total_out_lo32++;
-      if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
-   }
-
-   return progress_out;
-}
-
-
-/*---------------------------------------------------*/
-static
-Bool handle_compress ( bz_stream* strm )
-{
-   Bool progress_in  = False;
-   Bool progress_out = False;
-   EState* s = strm->state;
-   
-   while (True) {
-
-      if (s->state == BZ_S_OUTPUT) {
-         progress_out |= copy_output_until_stop ( s );
-         if (s->state_out_pos < s->numZ) break;
-         if (s->mode == BZ_M_FINISHING && 
-             s->avail_in_expect == 0 &&
-             isempty_RL(s)) break;
-         prepare_new_block ( s );
-         s->state = BZ_S_INPUT;
-         if (s->mode == BZ_M_FLUSHING && 
-             s->avail_in_expect == 0 &&
-             isempty_RL(s)) break;
-      }
-
-      if (s->state == BZ_S_INPUT) {
-         progress_in |= copy_input_until_stop ( s );
-         if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
-            flush_RL ( s );
-            BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
-            s->state = BZ_S_OUTPUT;
-         }
-         else
-         if (s->nblock >= s->nblockMAX) {
-            BZ2_compressBlock ( s, False );
-            s->state = BZ_S_OUTPUT;
-         }
-         else
-         if (s->strm->avail_in == 0) {
-            break;
-         }
-      }
-
-   }
-
-   return progress_in || progress_out;
-}
-
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
-{
-   Bool progress;
-   EState* s;
-   if (strm == NULL) return BZ_PARAM_ERROR;
-   s = strm->state;
-   if (s == NULL) return BZ_PARAM_ERROR;
-   if (s->strm != strm) return BZ_PARAM_ERROR;
-
-   preswitch:
-   switch (s->mode) {
-
-      case BZ_M_IDLE:
-         return BZ_SEQUENCE_ERROR;
-
-      case BZ_M_RUNNING:
-         if (action == BZ_RUN) {
-            progress = handle_compress ( strm );
-            return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
-         } 
-         else
-        if (action == BZ_FLUSH) {
-            s->avail_in_expect = strm->avail_in;
-            s->mode = BZ_M_FLUSHING;
-            goto preswitch;
-         }
-         else
-         if (action == BZ_FINISH) {
-            s->avail_in_expect = strm->avail_in;
-            s->mode = BZ_M_FINISHING;
-            goto preswitch;
-         }
-         else 
-            return BZ_PARAM_ERROR;
-
-      case BZ_M_FLUSHING:
-         if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
-         if (s->avail_in_expect != s->strm->avail_in) 
-            return BZ_SEQUENCE_ERROR;
-         progress = handle_compress ( strm );
-         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
-             s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
-         s->mode = BZ_M_RUNNING;
-         return BZ_RUN_OK;
-
-      case BZ_M_FINISHING:
-         if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
-         if (s->avail_in_expect != s->strm->avail_in) 
-            return BZ_SEQUENCE_ERROR;
-         progress = handle_compress ( strm );
-         if (!progress) return BZ_SEQUENCE_ERROR;
-         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
-             s->state_out_pos < s->numZ) return BZ_FINISH_OK;
-         s->mode = BZ_M_IDLE;
-         return BZ_STREAM_END;
-   }
-   return BZ_OK; /*--not reached--*/
-}
-
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
-{
-   EState* s;
-   if (strm == NULL) return BZ_PARAM_ERROR;
-   s = strm->state;
-   if (s == NULL) return BZ_PARAM_ERROR;
-   if (s->strm != strm) return BZ_PARAM_ERROR;
-
-   if (s->arr1 != NULL) BZFREE(s->arr1);
-   if (s->arr2 != NULL) BZFREE(s->arr2);
-   if (s->ftab != NULL) BZFREE(s->ftab);
-   BZFREE(strm->state);
-
-   strm->state = NULL;   
-
-   return BZ_OK;
-}
-
-
-/*---------------------------------------------------*/
-/*--- Decompression stuff                         ---*/
-/*---------------------------------------------------*/
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzDecompressInit) 
-                     ( bz_stream* strm, 
-                       int        verbosity,
-                       int        small )
-{
-   DState* s;
-
-   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
-
-   if (strm == NULL) return BZ_PARAM_ERROR;
-   if (small != 0 && small != 1) return BZ_PARAM_ERROR;
-   if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
-
-   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
-   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
-
-   s = BZALLOC( sizeof(DState) );
-   if (s == NULL) return BZ_MEM_ERROR;
-   s->strm                  = strm;
-   strm->state              = s;
-   s->state                 = BZ_X_MAGIC_1;
-   s->bsLive                = 0;
-   s->bsBuff                = 0;
-   s->calculatedCombinedCRC = 0;
-   strm->total_in_lo32      = 0;
-   strm->total_in_hi32      = 0;
-   strm->total_out_lo32     = 0;
-   strm->total_out_hi32     = 0;
-   s->smallDecompress       = (Bool)small;
-   s->ll4                   = NULL;
-   s->ll16                  = NULL;
-   s->tt                    = NULL;
-   s->currBlockNo           = 0;
-   s->verbosity             = verbosity;
-
-   return BZ_OK;
-}
-
-
-/*---------------------------------------------------*/
-/* Return  True iff data corruption is discovered.
-   Returns False if there is no problem.
-*/
-static
-Bool unRLE_obuf_to_output_FAST ( DState* s )
-{
-   UChar k1;
-
-   if (s->blockRandomised) {
-
-      while (True) {
-         /* try to finish existing run */
-         while (True) {
-            if (s->strm->avail_out == 0) return False;
-            if (s->state_out_len == 0) break;
-            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
-            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
-            s->state_out_len--;
-            s->strm->next_out++;
-            s->strm->avail_out--;
-            s->strm->total_out_lo32++;
-            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
-         }
-
-         /* can a new run be started? */
-         if (s->nblock_used == s->save_nblock+1) return False;
-               
-         /* Only caused by corrupt data stream? */
-         if (s->nblock_used > s->save_nblock+1)
-            return True;
-   
-         s->state_out_len = 1;
-         s->state_out_ch = s->k0;
-         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
-         k1 ^= BZ_RAND_MASK; s->nblock_used++;
-         if (s->nblock_used == s->save_nblock+1) continue;
-         if (k1 != s->k0) { s->k0 = k1; continue; };
-   
-         s->state_out_len = 2;
-         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
-         k1 ^= BZ_RAND_MASK; s->nblock_used++;
-         if (s->nblock_used == s->save_nblock+1) continue;
-         if (k1 != s->k0) { s->k0 = k1; continue; };
-   
-         s->state_out_len = 3;
-         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
-         k1 ^= BZ_RAND_MASK; s->nblock_used++;
-         if (s->nblock_used == s->save_nblock+1) continue;
-         if (k1 != s->k0) { s->k0 = k1; continue; };
-   
-         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; 
-         k1 ^= BZ_RAND_MASK; s->nblock_used++;
-         s->state_out_len = ((Int32)k1) + 4;
-         BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; 
-         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
-      }
-
-   } else {
-
-      /* restore */
-      UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
-      UChar         c_state_out_ch       = s->state_out_ch;
-      Int32         c_state_out_len      = s->state_out_len;
-      Int32         c_nblock_used        = s->nblock_used;
-      Int32         c_k0                 = s->k0;
-      UInt32*       c_tt                 = s->tt;
-      UInt32        c_tPos               = s->tPos;
-      char*         cs_next_out          = s->strm->next_out;
-      unsigned int  cs_avail_out         = s->strm->avail_out;
-      /* end restore */
-
-      UInt32       avail_out_INIT = cs_avail_out;
-      Int32        s_save_nblockPP = s->save_nblock+1;
-      unsigned int total_out_lo32_old;
-
-      while (True) {
-
-         /* try to finish existing run */
-         if (c_state_out_len > 0) {
-            while (True) {
-               if (cs_avail_out == 0) goto return_notr;
-               if (c_state_out_len == 1) break;
-               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
-               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
-               c_state_out_len--;
-               cs_next_out++;
-               cs_avail_out--;
-            }
-            s_state_out_len_eq_one:
-            {
-               if (cs_avail_out == 0) { 
-                  c_state_out_len = 1; goto return_notr;
-               };
-               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
-               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
-               cs_next_out++;
-               cs_avail_out--;
-            }
-         }   
-         /* Only caused by corrupt data stream? */
-         if (c_nblock_used > s_save_nblockPP)
-            return True;
-
-         /* can a new run be started? */
-         if (c_nblock_used == s_save_nblockPP) {
-            c_state_out_len = 0; goto return_notr;
-         };   
-         c_state_out_ch = c_k0;
-         BZ_GET_FAST_C(k1); c_nblock_used++;
-         if (k1 != c_k0) { 
-            c_k0 = k1; goto s_state_out_len_eq_one; 
-         };
-         if (c_nblock_used == s_save_nblockPP) 
-            goto s_state_out_len_eq_one;
-   
-         c_state_out_len = 2;
-         BZ_GET_FAST_C(k1); c_nblock_used++;
-         if (c_nblock_used == s_save_nblockPP) continue;
-         if (k1 != c_k0) { c_k0 = k1; continue; };
-   
-         c_state_out_len = 3;
-         BZ_GET_FAST_C(k1); c_nblock_used++;
-         if (c_nblock_used == s_save_nblockPP) continue;
-         if (k1 != c_k0) { c_k0 = k1; continue; };
-   
-         BZ_GET_FAST_C(k1); c_nblock_used++;
-         c_state_out_len = ((Int32)k1) + 4;
-         BZ_GET_FAST_C(c_k0); c_nblock_used++;
-      }
-
-      return_notr:
-      total_out_lo32_old = s->strm->total_out_lo32;
-      s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
-      if (s->strm->total_out_lo32 < total_out_lo32_old)
-         s->strm->total_out_hi32++;
-
-      /* save */
-      s->calculatedBlockCRC = c_calculatedBlockCRC;
-      s->state_out_ch       = c_state_out_ch;
-      s->state_out_len      = c_state_out_len;
-      s->nblock_used        = c_nblock_used;
-      s->k0                 = c_k0;
-      s->tt                 = c_tt;
-      s->tPos               = c_tPos;
-      s->strm->next_out     = cs_next_out;
-      s->strm->avail_out    = cs_avail_out;
-      /* end save */
-   }
-   return False;
-}
-
-
-
-/*---------------------------------------------------*/
-/* Return  True iff data corruption is discovered.
-   Returns False if there is no problem.
-*/
-static
-Bool unRLE_obuf_to_output_SMALL ( DState* s )
-{
-   UChar k1;
-
-   if (s->blockRandomised) {
-
-      while (True) {
-         /* try to finish existing run */
-         while (True) {
-            if (s->strm->avail_out == 0) return False;
-            if (s->state_out_len == 0) break;
-            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
-            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
-            s->state_out_len--;
-            s->strm->next_out++;
-            s->strm->avail_out--;
-            s->strm->total_out_lo32++;
-            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
-         }
-   
-         /* can a new run be started? */
-         if (s->nblock_used == s->save_nblock+1) return False;
-
-         /* Only caused by corrupt data stream? */
-         if (s->nblock_used > s->save_nblock+1)
-            return True;
-   
-         s->state_out_len = 1;
-         s->state_out_ch = s->k0;
-         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
-         k1 ^= BZ_RAND_MASK; s->nblock_used++;
-         if (s->nblock_used == s->save_nblock+1) continue;
-         if (k1 != s->k0) { s->k0 = k1; continue; };
-   
-         s->state_out_len = 2;
-         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
-         k1 ^= BZ_RAND_MASK; s->nblock_used++;
-         if (s->nblock_used == s->save_nblock+1) continue;
-         if (k1 != s->k0) { s->k0 = k1; continue; };
-   
-         s->state_out_len = 3;
-         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
-         k1 ^= BZ_RAND_MASK; s->nblock_used++;
-         if (s->nblock_used == s->save_nblock+1) continue;
-         if (k1 != s->k0) { s->k0 = k1; continue; };
-   
-         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 
-         k1 ^= BZ_RAND_MASK; s->nblock_used++;
-         s->state_out_len = ((Int32)k1) + 4;
-         BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; 
-         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
-      }
-
-   } else {
-
-      while (True) {
-         /* try to finish existing run */
-         while (True) {
-            if (s->strm->avail_out == 0) return False;
-            if (s->state_out_len == 0) break;
-            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
-            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
-            s->state_out_len--;
-            s->strm->next_out++;
-            s->strm->avail_out--;
-            s->strm->total_out_lo32++;
-            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
-         }
-   
-         /* can a new run be started? */
-         if (s->nblock_used == s->save_nblock+1) return False;
-
-         /* Only caused by corrupt data stream? */
-         if (s->nblock_used > s->save_nblock+1)
-            return True;
-   
-         s->state_out_len = 1;
-         s->state_out_ch = s->k0;
-         BZ_GET_SMALL(k1); s->nblock_used++;
-         if (s->nblock_used == s->save_nblock+1) continue;
-         if (k1 != s->k0) { s->k0 = k1; continue; };
-   
-         s->state_out_len = 2;
-         BZ_GET_SMALL(k1); s->nblock_used++;
-         if (s->nblock_used == s->save_nblock+1) continue;
-         if (k1 != s->k0) { s->k0 = k1; continue; };
-   
-         s->state_out_len = 3;
-         BZ_GET_SMALL(k1); s->nblock_used++;
-         if (s->nblock_used == s->save_nblock+1) continue;
-         if (k1 != s->k0) { s->k0 = k1; continue; };
-   
-         BZ_GET_SMALL(k1); s->nblock_used++;
-         s->state_out_len = ((Int32)k1) + 4;
-         BZ_GET_SMALL(s->k0); s->nblock_used++;
-      }
-
-   }
-}
-
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
-{
-   Bool    corrupt;
-   DState* s;
-   if (strm == NULL) return BZ_PARAM_ERROR;
-   s = strm->state;
-   if (s == NULL) return BZ_PARAM_ERROR;
-   if (s->strm != strm) return BZ_PARAM_ERROR;
-
-   while (True) {
-      if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
-      if (s->state == BZ_X_OUTPUT) {
-         if (s->smallDecompress)
-            corrupt = unRLE_obuf_to_output_SMALL ( s ); else
-            corrupt = unRLE_obuf_to_output_FAST  ( s );
-         if (corrupt) return BZ_DATA_ERROR;
-         if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
-            BZ_FINALISE_CRC ( s->calculatedBlockCRC );
-            if (s->verbosity >= 3) 
-               VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, 
-                          s->calculatedBlockCRC );
-            if (s->verbosity >= 2) VPrintf0 ( "]" );
-            if (s->calculatedBlockCRC != s->storedBlockCRC)
-               return BZ_DATA_ERROR;
-            s->calculatedCombinedCRC 
-               = (s->calculatedCombinedCRC << 1) | 
-                    (s->calculatedCombinedCRC >> 31);
-            s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
-            s->state = BZ_X_BLKHDR_1;
-         } else {
-            return BZ_OK;
-         }
-      }
-      if (s->state >= BZ_X_MAGIC_1) {
-         Int32 r = BZ2_decompress ( s );
-         if (r == BZ_STREAM_END) {
-            if (s->verbosity >= 3)
-               VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x", 
-                          s->storedCombinedCRC, s->calculatedCombinedCRC );
-            if (s->calculatedCombinedCRC != s->storedCombinedCRC)
-               return BZ_DATA_ERROR;
-            return r;
-         }
-         if (s->state != BZ_X_OUTPUT) return r;
-      }
-   }
-
-   AssertH ( 0, 6001 );
-
-   return 0;  /*NOTREACHED*/
-}
-
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
-{
-   DState* s;
-   if (strm == NULL) return BZ_PARAM_ERROR;
-   s = strm->state;
-   if (s == NULL) return BZ_PARAM_ERROR;
-   if (s->strm != strm) return BZ_PARAM_ERROR;
-
-   if (s->tt   != NULL) BZFREE(s->tt);
-   if (s->ll16 != NULL) BZFREE(s->ll16);
-   if (s->ll4  != NULL) BZFREE(s->ll4);
-
-   BZFREE(strm->state);
-   strm->state = NULL;
-
-   return BZ_OK;
-}
-
-
-#ifndef BZ_NO_STDIO
-/*---------------------------------------------------*/
-/*--- File I/O stuff                              ---*/
-/*---------------------------------------------------*/
-
-#define BZ_SETERR(eee)                    \
-{                                         \
-   if (bzerror != NULL) *bzerror = eee;   \
-   if (bzf != NULL) bzf->lastErr = eee;   \
-}
-
-typedef 
-   struct {
-      FILE*     handle;
-      Char      buf[BZ_MAX_UNUSED];
-      Int32     bufN;
-      Bool      writing;
-      bz_stream strm;
-      Int32     lastErr;
-      Bool      initialisedOk;
-   }
-   bzFile;
-
-
-/*---------------------------------------------*/
-static Bool myfeof ( FILE* f )
-{
-   Int32 c = fgetc ( f );
-   if (c == EOF) return True;
-   ungetc ( c, f );
-   return False;
-}
-
-
-/*---------------------------------------------------*/
-BZFILE* BZ_API(BZ2_bzWriteOpen) 
-                    ( int*  bzerror,      
-                      FILE* f, 
-                      int   blockSize100k, 
-                      int   verbosity,
-                      int   workFactor )
-{
-   Int32   ret;
-   bzFile* bzf = NULL;
-
-   BZ_SETERR(BZ_OK);
-
-   if (f == NULL ||
-       (blockSize100k < 1 || blockSize100k > 9) ||
-       (workFactor < 0 || workFactor > 250) ||
-       (verbosity < 0 || verbosity > 4))
-      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
-
-   if (ferror(f))
-      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
-
-   bzf = malloc ( sizeof(bzFile) );
-   if (bzf == NULL)
-      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
-
-   BZ_SETERR(BZ_OK);
-   bzf->initialisedOk = False;
-   bzf->bufN          = 0;
-   bzf->handle        = f;
-   bzf->writing       = True;
-   bzf->strm.bzalloc  = NULL;
-   bzf->strm.bzfree   = NULL;
-   bzf->strm.opaque   = NULL;
-
-   if (workFactor == 0) workFactor = 30;
-   ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, 
-                              verbosity, workFactor );
-   if (ret != BZ_OK)
-      { BZ_SETERR(ret); free(bzf); return NULL; };
-
-   bzf->strm.avail_in = 0;
-   bzf->initialisedOk = True;
-   return bzf;   
-}
-
-
-
-/*---------------------------------------------------*/
-void BZ_API(BZ2_bzWrite)
-             ( int*    bzerror, 
-               BZFILE* b, 
-               void*   buf, 
-               int     len )
-{
-   Int32 n, n2, ret;
-   bzFile* bzf = (bzFile*)b;
-
-   BZ_SETERR(BZ_OK);
-   if (bzf == NULL || buf == NULL || len < 0)
-      { BZ_SETERR(BZ_PARAM_ERROR); return; };
-   if (!(bzf->writing))
-      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
-   if (ferror(bzf->handle))
-      { BZ_SETERR(BZ_IO_ERROR); return; };
-
-   if (len == 0)
-      { BZ_SETERR(BZ_OK); return; };
-
-   bzf->strm.avail_in = len;
-   bzf->strm.next_in  = buf;
-
-   while (True) {
-      bzf->strm.avail_out = BZ_MAX_UNUSED;
-      bzf->strm.next_out = bzf->buf;
-      ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
-      if (ret != BZ_RUN_OK)
-         { BZ_SETERR(ret); return; };
-
-      if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
-         n = BZ_MAX_UNUSED - bzf->strm.avail_out;
-         n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
-                       n, bzf->handle );
-         if (n != n2 || ferror(bzf->handle))
-            { BZ_SETERR(BZ_IO_ERROR); return; };
-      }
-
-      if (bzf->strm.avail_in == 0)
-         { BZ_SETERR(BZ_OK); return; };
-   }
-}
-
-
-/*---------------------------------------------------*/
-void BZ_API(BZ2_bzWriteClose)
-                  ( int*          bzerror, 
-                    BZFILE*       b, 
-                    int           abandon,
-                    unsigned int* nbytes_in,
-                    unsigned int* nbytes_out )
-{
-   BZ2_bzWriteClose64 ( bzerror, b, abandon, 
-                        nbytes_in, NULL, nbytes_out, NULL );
-}
-
-
-void BZ_API(BZ2_bzWriteClose64)
-                  ( int*          bzerror, 
-                    BZFILE*       b, 
-                    int           abandon,
-                    unsigned int* nbytes_in_lo32,
-                    unsigned int* nbytes_in_hi32,
-                    unsigned int* nbytes_out_lo32,
-                    unsigned int* nbytes_out_hi32 )
-{
-   Int32   n, n2, ret;
-   bzFile* bzf = (bzFile*)b;
-
-   if (bzf == NULL)
-      { BZ_SETERR(BZ_OK); return; };
-   if (!(bzf->writing))
-      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
-   if (ferror(bzf->handle))
-      { BZ_SETERR(BZ_IO_ERROR); return; };
-
-   if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
-   if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
-   if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
-   if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
-
-   if ((!abandon) && bzf->lastErr == BZ_OK) {
-      while (True) {
-         bzf->strm.avail_out = BZ_MAX_UNUSED;
-         bzf->strm.next_out = bzf->buf;
-         ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
-         if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
-            { BZ_SETERR(ret); return; };
-
-         if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
-            n = BZ_MAX_UNUSED - bzf->strm.avail_out;
-            n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), 
-                          n, bzf->handle );
-            if (n != n2 || ferror(bzf->handle))
-               { BZ_SETERR(BZ_IO_ERROR); return; };
-         }
-
-         if (ret == BZ_STREAM_END) break;
-      }
-   }
-
-   if ( !abandon && !ferror ( bzf->handle ) ) {
-      fflush ( bzf->handle );
-      if (ferror(bzf->handle))
-         { BZ_SETERR(BZ_IO_ERROR); return; };
-   }
-
-   if (nbytes_in_lo32 != NULL)
-      *nbytes_in_lo32 = bzf->strm.total_in_lo32;
-   if (nbytes_in_hi32 != NULL)
-      *nbytes_in_hi32 = bzf->strm.total_in_hi32;
-   if (nbytes_out_lo32 != NULL)
-      *nbytes_out_lo32 = bzf->strm.total_out_lo32;
-   if (nbytes_out_hi32 != NULL)
-      *nbytes_out_hi32 = bzf->strm.total_out_hi32;
-
-   BZ_SETERR(BZ_OK);
-   BZ2_bzCompressEnd ( &(bzf->strm) );
-   free ( bzf );
-}
-
-
-/*---------------------------------------------------*/
-BZFILE* BZ_API(BZ2_bzReadOpen) 
-                   ( int*  bzerror, 
-                     FILE* f, 
-                     int   verbosity,
-                     int   small,
-                     void* unused,
-                     int   nUnused )
-{
-   bzFile* bzf = NULL;
-   int     ret;
-
-   BZ_SETERR(BZ_OK);
-
-   if (f == NULL || 
-       (small != 0 && small != 1) ||
-       (verbosity < 0 || verbosity > 4) ||
-       (unused == NULL && nUnused != 0) ||
-       (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
-      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
-
-   if (ferror(f))
-      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
-
-   bzf = malloc ( sizeof(bzFile) );
-   if (bzf == NULL) 
-      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
-
-   BZ_SETERR(BZ_OK);
-
-   bzf->initialisedOk = False;
-   bzf->handle        = f;
-   bzf->bufN          = 0;
-   bzf->writing       = False;
-   bzf->strm.bzalloc  = NULL;
-   bzf->strm.bzfree   = NULL;
-   bzf->strm.opaque   = NULL;
-   
-   while (nUnused > 0) {
-      bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
-      unused = ((void*)( 1 + ((UChar*)(unused))  ));
-      nUnused--;
-   }
-
-   ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
-   if (ret != BZ_OK)
-      { BZ_SETERR(ret); free(bzf); return NULL; };
-
-   bzf->strm.avail_in = bzf->bufN;
-   bzf->strm.next_in  = bzf->buf;
-
-   bzf->initialisedOk = True;
-   return bzf;   
-}
-
-
-/*---------------------------------------------------*/
-void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
-{
-   bzFile* bzf = (bzFile*)b;
-
-   BZ_SETERR(BZ_OK);
-   if (bzf == NULL)
-      { BZ_SETERR(BZ_OK); return; };
-
-   if (bzf->writing)
-      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
-
-   if (bzf->initialisedOk)
-      (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
-   free ( bzf );
-}
-
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzRead) 
-           ( int*    bzerror, 
-             BZFILE* b, 
-             void*   buf, 
-             int     len )
-{
-   Int32   n, ret;
-   bzFile* bzf = (bzFile*)b;
-
-   BZ_SETERR(BZ_OK);
-
-   if (bzf == NULL || buf == NULL || len < 0)
-      { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
-
-   if (bzf->writing)
-      { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
-
-   if (len == 0)
-      { BZ_SETERR(BZ_OK); return 0; };
-
-   bzf->strm.avail_out = len;
-   bzf->strm.next_out = buf;
-
-   while (True) {
-
-      if (ferror(bzf->handle)) 
-         { BZ_SETERR(BZ_IO_ERROR); return 0; };
-
-      if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
-         n = fread ( bzf->buf, sizeof(UChar), 
-                     BZ_MAX_UNUSED, bzf->handle );
-         if (ferror(bzf->handle))
-            { BZ_SETERR(BZ_IO_ERROR); return 0; };
-         bzf->bufN = n;
-         bzf->strm.avail_in = bzf->bufN;
-         bzf->strm.next_in = bzf->buf;
-      }
-
-      ret = BZ2_bzDecompress ( &(bzf->strm) );
-
-      if (ret != BZ_OK && ret != BZ_STREAM_END)
-         { BZ_SETERR(ret); return 0; };
-
-      if (ret == BZ_OK && myfeof(bzf->handle) && 
-          bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
-         { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
-
-      if (ret == BZ_STREAM_END)
-         { BZ_SETERR(BZ_STREAM_END);
-           return len - bzf->strm.avail_out; };
-      if (bzf->strm.avail_out == 0)
-         { BZ_SETERR(BZ_OK); return len; };
-      
-   }
-
-   return 0; /*not reached*/
-}
-
-
-/*---------------------------------------------------*/
-void BZ_API(BZ2_bzReadGetUnused) 
-                     ( int*    bzerror, 
-                       BZFILE* b, 
-                       void**  unused, 
-                       int*    nUnused )
-{
-   bzFile* bzf = (bzFile*)b;
-   if (bzf == NULL)
-      { BZ_SETERR(BZ_PARAM_ERROR); return; };
-   if (bzf->lastErr != BZ_STREAM_END)
-      { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
-   if (unused == NULL || nUnused == NULL)
-      { BZ_SETERR(BZ_PARAM_ERROR); return; };
-
-   BZ_SETERR(BZ_OK);
-   *nUnused = bzf->strm.avail_in;
-   *unused = bzf->strm.next_in;
-}
-#endif
-
-
-/*---------------------------------------------------*/
-/*--- Misc convenience stuff                      ---*/
-/*---------------------------------------------------*/
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzBuffToBuffCompress) 
-                         ( char*         dest, 
-                           unsigned int* destLen,
-                           char*         source, 
-                           unsigned int  sourceLen,
-                           int           blockSize100k, 
-                           int           verbosity, 
-                           int           workFactor )
-{
-   bz_stream strm;
-   int ret;
-
-   if (dest == NULL || destLen == NULL || 
-       source == NULL ||
-       blockSize100k < 1 || blockSize100k > 9 ||
-       verbosity < 0 || verbosity > 4 ||
-       workFactor < 0 || workFactor > 250) 
-      return BZ_PARAM_ERROR;
-
-   if (workFactor == 0) workFactor = 30;
-   strm.bzalloc = NULL;
-   strm.bzfree = NULL;
-   strm.opaque = NULL;
-   ret = BZ2_bzCompressInit ( &strm, blockSize100k, 
-                              verbosity, workFactor );
-   if (ret != BZ_OK) return ret;
-
-   strm.next_in = source;
-   strm.next_out = dest;
-   strm.avail_in = sourceLen;
-   strm.avail_out = *destLen;
-
-   ret = BZ2_bzCompress ( &strm, BZ_FINISH );
-   if (ret == BZ_FINISH_OK) goto output_overflow;
-   if (ret != BZ_STREAM_END) goto errhandler;
-
-   /* normal termination */
-   *destLen -= strm.avail_out;   
-   BZ2_bzCompressEnd ( &strm );
-   return BZ_OK;
-
-   output_overflow:
-   BZ2_bzCompressEnd ( &strm );
-   return BZ_OUTBUFF_FULL;
-
-   errhandler:
-   BZ2_bzCompressEnd ( &strm );
-   return ret;
-}
-
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzBuffToBuffDecompress) 
-                           ( char*         dest, 
-                             unsigned int* destLen,
-                             char*         source, 
-                             unsigned int  sourceLen,
-                             int           small,
-                             int           verbosity )
-{
-   bz_stream strm;
-   int ret;
-
-   if (dest == NULL || destLen == NULL || 
-       source == NULL ||
-       (small != 0 && small != 1) ||
-       verbosity < 0 || verbosity > 4) 
-          return BZ_PARAM_ERROR;
-
-   strm.bzalloc = NULL;
-   strm.bzfree = NULL;
-   strm.opaque = NULL;
-   ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
-   if (ret != BZ_OK) return ret;
-
-   strm.next_in = source;
-   strm.next_out = dest;
-   strm.avail_in = sourceLen;
-   strm.avail_out = *destLen;
-
-   ret = BZ2_bzDecompress ( &strm );
-   if (ret == BZ_OK) goto output_overflow_or_eof;
-   if (ret != BZ_STREAM_END) goto errhandler;
-
-   /* normal termination */
-   *destLen -= strm.avail_out;
-   BZ2_bzDecompressEnd ( &strm );
-   return BZ_OK;
-
-   output_overflow_or_eof:
-   if (strm.avail_out > 0) {
-      BZ2_bzDecompressEnd ( &strm );
-      return BZ_UNEXPECTED_EOF;
-   } else {
-      BZ2_bzDecompressEnd ( &strm );
-      return BZ_OUTBUFF_FULL;
-   };      
-
-   errhandler:
-   BZ2_bzDecompressEnd ( &strm );
-   return ret; 
-}
-
-
-/*---------------------------------------------------*/
-/*--
-   Code contributed by Yoshioka Tsuneo
-   (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
-   to support better zlib compatibility.
-   This code is not _officially_ part of libbzip2 (yet);
-   I haven't tested it, documented it, or considered the
-   threading-safeness of it.
-   If this code breaks, please contact both Yoshioka and me.
---*/
-/*---------------------------------------------------*/
-
-/*---------------------------------------------------*/
-/*--
-   return version like "0.9.0c".
---*/
-const char * BZ_API(BZ2_bzlibVersion)(void)
-{
-   return BZ_VERSION;
-}
-
-
-#ifndef BZ_NO_STDIO
-/*---------------------------------------------------*/
-
-#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
-#   include <fcntl.h>
-#   include <io.h>
-#   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
-#else
-#   define SET_BINARY_MODE(file)
-#endif
-static
-BZFILE * bzopen_or_bzdopen
-               ( const char *path,   /* no use when bzdopen */
-                 int fd,             /* no use when bzdopen */
-                 const char *mode,
-                 int open_mode)      /* bzopen: 0, bzdopen:1 */
-{
-   int    bzerr;
-   char   unused[BZ_MAX_UNUSED];
-   int    blockSize100k = 9;
-   int    writing       = 0;
-   char   mode2[10]     = "";
-   FILE   *fp           = NULL;
-   BZFILE *bzfp         = NULL;
-   int    verbosity     = 0;
-   int    workFactor    = 30;
-   int    smallMode     = 0;
-   int    nUnused       = 0; 
-
-   if (mode == NULL) return NULL;
-   while (*mode) {
-      switch (*mode) {
-      case 'r':
-         writing = 0; break;
-      case 'w':
-         writing = 1; break;
-      case 's':
-         smallMode = 1; break;
-      default:
-         if (isdigit((int)(*mode))) {
-            blockSize100k = *mode-BZ_HDR_0;
-         }
-      }
-      mode++;
-   }
-   strcat(mode2, writing ? "w" : "r" );
-   strcat(mode2,"b");   /* binary mode */
-
-   if (open_mode==0) {
-      if (path==NULL || strcmp(path,"")==0) {
-        fp = (writing ? stdout : stdin);
-        SET_BINARY_MODE(fp);
-      } else {
-        fp = fopen(path,mode2);
-      }
-   } else {
-#ifdef BZ_STRICT_ANSI
-      fp = NULL;
-#else
-      fp = fdopen(fd,mode2);
-#endif
-   }
-   if (fp == NULL) return NULL;
-
-   if (writing) {
-      /* Guard against total chaos and anarchy -- JRS */
-      if (blockSize100k < 1) blockSize100k = 1;
-      if (blockSize100k > 9) blockSize100k = 9; 
-      bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
-                             verbosity,workFactor);
-   } else {
-      bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
-                            unused,nUnused);
-   }
-   if (bzfp == NULL) {
-      if (fp != stdin && fp != stdout) fclose(fp);
-      return NULL;
-   }
-   return bzfp;
-}
-
-
-/*---------------------------------------------------*/
-/*--
-   open file for read or write.
-      ex) bzopen("file","w9")
-      case path="" or NULL => use stdin or stdout.
---*/
-BZFILE * BZ_API(BZ2_bzopen)
-               ( const char *path,
-                 const char *mode )
-{
-   return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
-}
-
-
-/*---------------------------------------------------*/
-BZFILE * BZ_API(BZ2_bzdopen)
-               ( int fd,
-                 const char *mode )
-{
-   return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
-}
-
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
-{
-   int bzerr, nread;
-   if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
-   nread = BZ2_bzRead(&bzerr,b,buf,len);
-   if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
-      return nread;
-   } else {
-      return -1;
-   }
-}
-
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
-{
-   int bzerr;
-
-   BZ2_bzWrite(&bzerr,b,buf,len);
-   if(bzerr == BZ_OK){
-      return len;
-   }else{
-      return -1;
-   }
-}
-
-
-/*---------------------------------------------------*/
-int BZ_API(BZ2_bzflush) (BZFILE *b)
-{
-   /* do nothing now... */
-   return 0;
-}
-
-
-/*---------------------------------------------------*/
-void BZ_API(BZ2_bzclose) (BZFILE* b)
-{
-   int bzerr;
-   FILE *fp = ((bzFile *)b)->handle;
-   
-   if (b==NULL) {return;}
-   if(((bzFile*)b)->writing){
-      BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
-      if(bzerr != BZ_OK){
-         BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
-      }
-   }else{
-      BZ2_bzReadClose(&bzerr,b);
-   }
-   if(fp!=stdin && fp!=stdout){
-      fclose(fp);
-   }
-}
-
-
-/*---------------------------------------------------*/
-/*--
-   return last error code 
---*/
-static char *bzerrorstrings[] = {
-       "OK"
-      ,"SEQUENCE_ERROR"
-      ,"PARAM_ERROR"
-      ,"MEM_ERROR"
-      ,"DATA_ERROR"
-      ,"DATA_ERROR_MAGIC"
-      ,"IO_ERROR"
-      ,"UNEXPECTED_EOF"
-      ,"OUTBUFF_FULL"
-      ,"CONFIG_ERROR"
-      ,"???"   /* for future */
-      ,"???"   /* for future */
-      ,"???"   /* for future */
-      ,"???"   /* for future */
-      ,"???"   /* for future */
-      ,"???"   /* for future */
-};
-
-
-const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
-{
-   int err = ((bzFile *)b)->lastErr;
-
-   if(err>0) err = 0;
-   *errnum = err;
-   return bzerrorstrings[err*-1];
-}
-#endif
-
-
-/*-------------------------------------------------------------*/
-/*--- end                                           bzlib.c ---*/
-/*-------------------------------------------------------------*/
-
-
-/////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////
-
-
-/* A test program written to test robustness to decompression of
-   corrupted data.  Usage is 
-       unzcrash filename
-   and the program will read the specified file, compress it (in memory),
-   and then repeatedly decompress it, each time with a different bit of
-   the compressed data inverted, so as to test all possible one-bit errors.
-   This should not cause any invalid memory accesses.  If it does, 
-   I want to know about it!
-
-   p.s.  As you can see from the above description, the process is
-   incredibly slow.  A file of size eg 5KB will cause it to run for
-   many hours.
-*/
-
-//#include <stdio.h>
-//#include <assert.h>
-//#include "bzlib.h"
-
-#define M_BLOCK 1000000
-
-
-#define M_BLOCK_OUT (M_BLOCK + 1000000)
- char inbuf[M_BLOCK];
- char outbuf[M_BLOCK_OUT];
- char zbuf[M_BLOCK + 600 + (M_BLOCK / 100)];
-
-int nIn;
-unsigned int nOut;
-unsigned int nZ;
-
-#if 0
-static char *bzerrorstrings[] = {
-       "OK"
-      ,"SEQUENCE_ERROR"
-      ,"PARAM_ERROR"
-      ,"MEM_ERROR"
-      ,"DATA_ERROR"
-      ,"DATA_ERROR_MAGIC"
-      ,"IO_ERROR"
-      ,"UNEXPECTED_EOF"
-      ,"OUTBUFF_FULL"
-      ,"???"   /* for future */
-      ,"???"   /* for future */
-      ,"???"   /* for future */
-      ,"???"   /* for future */
-      ,"???"   /* for future */
-      ,"???"   /* for future */
-};
-#endif
-
-void flip_bit ( int bit )
-{
-   int byteno = bit / 8;
-   int bitno  = bit % 8;
-   UChar mask = 1 << bitno;
-   //fprintf ( stderr, "(byte %d  bit %d  mask %d)",
-   //          byteno, bitno, (int)mask );
-   zbuf[byteno] ^= mask;
-}
-
-void set_inbuf ( void )
-{
-  inbuf[0] = 0;
-  my_strcat(inbuf, "At her sixtieth birthday party, Margaret Thatcher ");
-  my_strcat(inbuf, "blew on the cake to light the candles.\n");
-  my_strcat(inbuf, "This program, bzip2, the associated library libbzip2, and all\n");
-  my_strcat(inbuf, "documentation, are copyright (C) 1996-2004 Julian R Seward.  All\n");
-  my_strcat(inbuf, "rights reserved.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "Redistribution and use in source and binary forms, with or without\n");
-  my_strcat(inbuf, "modification, are permitted provided that the following conditions\n");
-  my_strcat(inbuf, "are met:\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "1. Redistributions of source code must retain the above copyright\n");
-  my_strcat(inbuf, "   notice, this list of conditions and the following disclaimer.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "2. The origin of this software must not be misrepresented; you must\n");
-  my_strcat(inbuf, "   not claim that you wrote the original software.  If you use this\n");
-  my_strcat(inbuf, "   software in a product, an acknowledgment in the product\n");
-  my_strcat(inbuf, "   documentation would be appreciated but is not required.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "3. Altered source versions must be plainly marked as such, and must\n");
-  my_strcat(inbuf, "   not be misrepresented as being the original software.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "4. The name of the author may not be used to endorse or promote\n");
-  my_strcat(inbuf, "   products derived from this software without specific prior written\n");
-  my_strcat(inbuf, "   permission.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS\n");
-  my_strcat(inbuf, "OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n");
-  my_strcat(inbuf, "WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n");
-  my_strcat(inbuf, "ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\n");
-  my_strcat(inbuf, "DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n");
-  my_strcat(inbuf, "DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n");
-  my_strcat(inbuf, "GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n");
-  my_strcat(inbuf, "INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n");
-  my_strcat(inbuf, "WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n");
-  my_strcat(inbuf, "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n");
-  my_strcat(inbuf, "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "ababababababababababababababababababababababababababababababab");
-  my_strcat(inbuf, "               GNU GENERAL PUBLIC LICENSE\n");
-  my_strcat(inbuf, "                  Version 2, June 1991\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, " Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n");
-  my_strcat(inbuf, "     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n");
-  my_strcat(inbuf, " Everyone is permitted to copy and distribute verbatim copies\n");
-  my_strcat(inbuf, " of this license document, but changing it is not allowed.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "                       Preamble\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  The licenses for most software are designed to take away your\n");
-  my_strcat(inbuf, "freedom to share and change it.  By contrast, the GNU General Public\n");
-  my_strcat(inbuf, "License is intended to guarantee your freedom to share and change free\n");
-  my_strcat(inbuf, "software--to make sure the software is free for all its users.  This\n");
-  my_strcat(inbuf, "General Public License applies to most of the Free Software\n");
-  my_strcat(inbuf, "Foundation's software and to any other program whose authors commit to\n");
-  my_strcat(inbuf, "using it.  (Some other Free Software Foundation software is covered by\n");
-  my_strcat(inbuf, "the GNU Library General Public License instead.)  You can apply it to\n");
-  my_strcat(inbuf, "your programs, too.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  When we speak of free software, we are referring to freedom, not\n");
-  my_strcat(inbuf, "price.  Our General Public Licenses are designed to make sure that you\n");
-  my_strcat(inbuf, "have the freedom to distribute copies of free software (and charge for\n");
-  my_strcat(inbuf, "this service if you wish), that you receive source code or can get it\n");
-  my_strcat(inbuf, "if you want it, that you can change the software or use pieces of it\n");
-  my_strcat(inbuf, "in new free programs; and that you know you can do these things.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  To protect your rights, we need to make restrictions that forbid\n");
-  my_strcat(inbuf, "anyone to deny you these rights or to ask you to surrender the rights.\n");
-  my_strcat(inbuf, "These restrictions translate to certain responsibilities for you if you\n");
-  my_strcat(inbuf, "distribute copies of the software, or if you modify it.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  For example, if you distribute copies of such a program, whether\n");
-  my_strcat(inbuf, "gratis or for a fee, you must give the recipients all the rights that\n");
-  my_strcat(inbuf, "you have.  You must make sure that they, too, receive or can get the\n");
-  my_strcat(inbuf, "source code.  And you must show them these terms so they know their\n");
-  my_strcat(inbuf, "rights.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  We protect your rights with two steps: (1) copyright the software, and\n");
-  my_strcat(inbuf, "(2) offer you this license which gives you legal permission to copy,\n");
-  my_strcat(inbuf, "distribute and/or modify the software.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  Also, for each author's protection and ours, we want to make certain\n");
-  my_strcat(inbuf, "that everyone understands that there is no warranty for this free\n");
-  my_strcat(inbuf, "software.  If the software is modified by someone else and passed on, we\n");
-  my_strcat(inbuf, "want its recipients to know that what they have is not the original, so\n");
-  my_strcat(inbuf, "that any problems introduced by others will not reflect on the original\n");
-  my_strcat(inbuf, "authors' reputations.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  Finally, any free program is threatened constantly by software\n");
-  my_strcat(inbuf, "patents.  We wish to avoid the danger that redistributors of a free\n");
-  my_strcat(inbuf, "program will individually obtain patent licenses, in effect making the\n");
-  my_strcat(inbuf, "program proprietary.  To prevent this, we have made it clear that any\n");
-  my_strcat(inbuf, "patent must be licensed for everyone's free use or not licensed at all.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  The precise terms and conditions for copying, distribution and\n");
-  my_strcat(inbuf, "modification follow.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "               GNU GENERAL PUBLIC LICENSE\n");
-  my_strcat(inbuf, "   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  0. This License applies to any program or other work which contains\n");
-  my_strcat(inbuf, "a notice placed by the copyright holder saying it may be distributed\n");
-  my_strcat(inbuf, "under the terms of this General Public License.  The Program, below,\n");
-  my_strcat(inbuf, "refers to any such program or work, and a work based on the Program\n");
-  my_strcat(inbuf, "means either the Program or any derivative work under copyright law:\n");
-  my_strcat(inbuf, "that is to say, a work containing the Program or a portion of it,\n");
-  my_strcat(inbuf, "either verbatim or with modifications and/or translated into another\n");
-  my_strcat(inbuf, "language.  (Hereinafter, translation is included without limitation in\n");
-  my_strcat(inbuf, "the term modification.)  Each licensee is addressed as you.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "Activities other than copying, distribution and modification are not\n");
-  my_strcat(inbuf, "covered by this License; they are outside its scope.  The act of\n");
-  my_strcat(inbuf, "running the Program is not restricted, and the output from the Program\n");
-  my_strcat(inbuf, "is covered only if its contents constitute a work based on the\n");
-  my_strcat(inbuf, "Program (independent of having been made by running the Program).\n");
-  my_strcat(inbuf, "Whether that is true depends on what the Program does.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  1. You may copy and distribute verbatim copies of the Program's\n");
-  my_strcat(inbuf, "source code as you receive it, in any medium, provided that you\n");
-  my_strcat(inbuf, "conspicuously and appropriately publish on each copy an appropriate\n");
-  my_strcat(inbuf, "copyright notice and disclaimer of warranty; keep intact all the\n");
-  my_strcat(inbuf, "notices that refer to this License and to the absence of any warranty;\n");
-  my_strcat(inbuf, "and give any other recipients of the Program a copy of this License\n");
-  my_strcat(inbuf, "along with the Program.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "You may charge a fee for the physical act of transferring a copy, and\n");
-  my_strcat(inbuf, "you may at your option offer warranty protection in exchange for a fee.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  2. You may modify your copy or copies of the Program or any portion\n");
-  my_strcat(inbuf, "of it, thus forming a work based on the Program, and copy and\n");
-  my_strcat(inbuf, "distribute such modifications or work under the terms of Section 1\n");
-  my_strcat(inbuf, "above, provided that you also meet all of these conditions:\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "    a) You must cause the modified files to carry prominent notices\n");
-  my_strcat(inbuf, "    stating that you changed the files and the date of any change.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "    b) You must cause any work that you distribute or publish, that in\n");
-  my_strcat(inbuf, "    whole or in part contains or is derived from the Program or any\n");
-  my_strcat(inbuf, "    part thereof, to be licensed as a whole at no charge to all third\n");
-  my_strcat(inbuf, "    parties under the terms of this License.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "    c) If the modified program normally reads commands interactively\n");
-  my_strcat(inbuf, "    when run, you must cause it, when started running for such\n");
-  my_strcat(inbuf, "    interactive use in the most ordinary way, to print or display an\n");
-  my_strcat(inbuf, "    announcement including an appropriate copyright notice and a\n");
-  my_strcat(inbuf, "    notice that there is no warranty (or else, saying that you provide\n");
-  my_strcat(inbuf, "    a warranty) and that users may redistribute the program under\n");
-  my_strcat(inbuf, "    these conditions, and telling the user how to view a copy of this\n");
-  my_strcat(inbuf, "    License.  (Exception: if the Program itself is interactive but\n");
-  my_strcat(inbuf, "    does not normally print such an announcement, your work based on\n");
-  my_strcat(inbuf, "    the Program is not required to print an announcement.)\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "These requirements apply to the modified work as a whole.  If\n");
-  my_strcat(inbuf, "identifiable sections of that work are not derived from the Program,\n");
-  my_strcat(inbuf, "and can be reasonably considered independent and separate works in\n");
-  my_strcat(inbuf, "themselves, then this License, and its terms, do not apply to those\n");
-  my_strcat(inbuf, "sections when you distribute them as separate works.  But when you\n");
-  my_strcat(inbuf, "distribute the same sections as part of a whole which is a work based\n");
-  my_strcat(inbuf, "on the Program, the distribution of the whole must be on the terms of\n");
-  my_strcat(inbuf, "this License, whose permissions for other licensees extend to the\n");
-  my_strcat(inbuf, "entire whole, and thus to each and every part regardless of who wrote it.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "Thus, it is not the intent of this section to claim rights or contest\n");
-  my_strcat(inbuf, "your rights to work written entirely by you; rather, the intent is to\n");
-  my_strcat(inbuf, "exercise the right to control the distribution of derivative or\n");
-  my_strcat(inbuf, "collective works based on the Program.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "In addition, mere aggregation of another work not based on the Program\n");
-  my_strcat(inbuf, "with the Program (or with a work based on the Program) on a volume of\n");
-  my_strcat(inbuf, "a storage or distribution medium does not bring the other work under\n");
-  my_strcat(inbuf, "the scope of this License.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  3. You may copy and distribute the Program (or a work based on it,\n");
-  my_strcat(inbuf, "under Section 2) in object code or executable form under the terms of\n");
-  my_strcat(inbuf, "Sections 1 and 2 above provided that you also do one of the following:\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "    a) Accompany it with the complete corresponding machine-readable\n");
-  my_strcat(inbuf, "    source code, which must be distributed under the terms of Sections\n");
-  my_strcat(inbuf, "    1 and 2 above on a medium customarily used for software interchange; or,\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "    b) Accompany it with a written offer, valid for at least three\n");
-  my_strcat(inbuf, "    years, to give any third party, for a charge no more than your\n");
-  my_strcat(inbuf, "    cost of physically performing source distribution, a complete\n");
-  my_strcat(inbuf, "    machine-readable copy of the corresponding source code, to be\n");
-  my_strcat(inbuf, "    distributed under the terms of Sections 1 and 2 above on a medium\n");
-  my_strcat(inbuf, "    customarily used for software interchange; or,\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "    c) Accompany it with the information you received as to the offer\n");
-  my_strcat(inbuf, "    to distribute corresponding source code.  (This alternative is\n");
-  my_strcat(inbuf, "    allowed only for noncommercial distribution and only if you\n");
-  my_strcat(inbuf, "    received the program in object code or executable form with such\n");
-  my_strcat(inbuf, "    an offer, in accord with Subsection b above.)\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "The source code for a work means the preferred form of the work for\n");
-  my_strcat(inbuf, "making modifications to it.  For an executable work, complete source\n");
-  my_strcat(inbuf, "code means all the source code for all modules it contains, plus any\n");
-  my_strcat(inbuf, "associated interface definition files, plus the scripts used to\n");
-  my_strcat(inbuf, "control compilation and installation of the executable.  However, as a\n");
-  my_strcat(inbuf, "special exception, the source code distributed need not include\n");
-  my_strcat(inbuf, "anything that is normally distributed (in either source or binary\n");
-  my_strcat(inbuf, "form) with the major components (compiler, kernel, and so on) of the\n");
-  my_strcat(inbuf, "operating system on which the executable runs, unless that component\n");
-  my_strcat(inbuf, "itself accompanies the executable.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "If distribution of executable or object code is made by offering\n");
-  my_strcat(inbuf, "access to copy from a designated place, then offering equivalent\n");
-  my_strcat(inbuf, "access to copy the source code from the same place counts as\n");
-  my_strcat(inbuf, "distribution of the source code, even though third parties are not\n");
-  my_strcat(inbuf, "compelled to copy the source along with the object code.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  4. You may not copy, modify, sublicense, or distribute the Program\n");
-  my_strcat(inbuf, "except as expressly provided under this License.  Any attempt\n");
-  my_strcat(inbuf, "otherwise to copy, modify, sublicense or distribute the Program is\n");
-  my_strcat(inbuf, "void, and will automatically terminate your rights under this License.\n");
-  my_strcat(inbuf, "However, parties who have received copies, or rights, from you under\n");
-  my_strcat(inbuf, "this License will not have their licenses terminated so long as such\n");
-  my_strcat(inbuf, "parties remain in full compliance.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  5. You are not required to accept this License, since you have not\n");
-  my_strcat(inbuf, "signed it.  However, nothing else grants you permission to modify or\n");
-  my_strcat(inbuf, "distribute the Program or its derivative works.  These actions are\n");
-  my_strcat(inbuf, "prohibited by law if you do not accept this License.  Therefore, by\n");
-  my_strcat(inbuf, "modifying or distributing the Program (or any work based on the\n");
-  my_strcat(inbuf, "Program), you indicate your acceptance of this License to do so, and\n");
-  my_strcat(inbuf, "all its terms and conditions for copying, distributing or modifying\n");
-  my_strcat(inbuf, "the Program or works based on it.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  6. Each time you redistribute the Program (or any work based on the\n");
-  my_strcat(inbuf, "Program), the recipient automatically receives a license from the\n");
-  my_strcat(inbuf, "original licensor to copy, distribute or modify the Program subject to\n");
-  my_strcat(inbuf, "these terms and conditions.  You may not impose any further\n");
-  my_strcat(inbuf, "restrictions on the recipients' exercise of the rights granted herein.\n");
-  my_strcat(inbuf, "You are not responsible for enforcing compliance by third parties to\n");
-  my_strcat(inbuf, "this License.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  7. If, as a consequence of a court judgment or allegation of patent\n");
-  my_strcat(inbuf, "infringement or for any other reason (not limited to patent issues),\n");
-  my_strcat(inbuf, "conditions are imposed on you (whether by court order, agreement or\n");
-  my_strcat(inbuf, "otherwise) that contradict the conditions of this License, they do not\n");
-  my_strcat(inbuf, "excuse you from the conditions of this License.  If you cannot\n");
-  my_strcat(inbuf, "distribute so as to satisfy simultaneously your obligations under this\n");
-  my_strcat(inbuf, "License and any other pertinent obligations, then as a consequence you\n");
-  my_strcat(inbuf, "may not distribute the Program at all.  For example, if a patent\n");
-  my_strcat(inbuf, "license would not permit royalty-free redistribution of the Program by\n");
-  my_strcat(inbuf, "all those who receive copies directly or indirectly through you, then\n");
-  my_strcat(inbuf, "the only way you could satisfy both it and this License would be to\n");
-  my_strcat(inbuf, "refrain entirely from distribution of the Program.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "If any portion of this section is held invalid or unenforceable under\n");
-  my_strcat(inbuf, "any particular circumstance, the balance of the section is intended to\n");
-  my_strcat(inbuf, "apply and the section as a whole is intended to apply in other\n");
-  my_strcat(inbuf, "circumstances.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "It is not the purpose of this section to induce you to infringe any\n");
-  my_strcat(inbuf, "patents or other property right claims or to contest validity of any\n");
-  my_strcat(inbuf, "such claims; this section has the sole purpose of protecting the\n");
-  my_strcat(inbuf, "integrity of the free software distribution system, which is\n");
-  my_strcat(inbuf, "implemented by public license practices.  Many people have made\n");
-  my_strcat(inbuf, "generous contributions to the wide range of software distributed\n");
-  my_strcat(inbuf, "through that system in reliance on consistent application of that\n");
-  my_strcat(inbuf, "system; it is up to the author/donor to decide if he or she is willing\n");
-  my_strcat(inbuf, "to distribute software through any other system and a licensee cannot\n");
-  my_strcat(inbuf, "impose that choice.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "This section is intended to make thoroughly clear what is believed to\n");
-  my_strcat(inbuf, "be a consequence of the rest of this License.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  8. If the distribution and/or use of the Program is restricted in\n");
-  my_strcat(inbuf, "certain countries either by patents or by copyrighted interfaces, the\n");
-  my_strcat(inbuf, "original copyright holder who places the Program under this License\n");
-  my_strcat(inbuf, "may add an explicit geographical distribution limitation excluding\n");
-  my_strcat(inbuf, "those countries, so that distribution is permitted only in or among\n");
-  my_strcat(inbuf, "countries not thus excluded.  In such case, this License incorporates\n");
-  my_strcat(inbuf, "the limitation as if written in the body of this License.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  9. The Free Software Foundation may publish revised and/or new versions\n");
-  my_strcat(inbuf, "of the General Public License from time to time.  Such new versions will\n");
-  my_strcat(inbuf, "be similar in spirit to the present version, but may differ in detail to\n");
-  my_strcat(inbuf, "address new problems or concerns.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "Each version is given a distinguishing version number.  If the Program\n");
-  my_strcat(inbuf, "specifies a version number of this License which applies to it and any\n");
-  my_strcat(inbuf, "later version, you have the option of following the terms and conditions\n");
-  my_strcat(inbuf, "either of that version or of any later version published by the Free\n");
-  my_strcat(inbuf, "Software Foundation.  If the Program does not specify a version number of\n");
-  my_strcat(inbuf, "this License, you may choose any version ever published by the Free Software\n");
-  my_strcat(inbuf, "Foundation.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  10. If you wish to incorporate parts of the Program into other free\n");
-  my_strcat(inbuf, "programs whose distribution conditions are different, write to the author\n");
-  my_strcat(inbuf, "to ask for permission.  For software which is copyrighted by the Free\n");
-  my_strcat(inbuf, "Software Foundation, write to the Free Software Foundation; we sometimes\n");
-  my_strcat(inbuf, "make exceptions for this.  Our decision will be guided by the two goals\n");
-  my_strcat(inbuf, "of preserving the free status of all derivatives of our free software and\n");
-  my_strcat(inbuf, "of promoting the sharing and reuse of software generally.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "                       NO WARRANTY\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n");
-  my_strcat(inbuf, "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n");
-  my_strcat(inbuf, "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n");
-  my_strcat(inbuf, "PROVIDE THE PROGRAM AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n");
-  my_strcat(inbuf, "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n");
-  my_strcat(inbuf, "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n");
-  my_strcat(inbuf, "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n");
-  my_strcat(inbuf, "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n");
-  my_strcat(inbuf, "REPAIR OR CORRECTION.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n");
-  my_strcat(inbuf, "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n");
-  my_strcat(inbuf, "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n");
-  my_strcat(inbuf, "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n");
-  my_strcat(inbuf, "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n");
-  my_strcat(inbuf, "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n");
-  my_strcat(inbuf, "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n");
-  my_strcat(inbuf, "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n");
-  my_strcat(inbuf, "POSSIBILITY OF SUCH DAMAGES.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "                END OF TERMS AND CONDITIONS\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "       How to Apply These Terms to Your New Programs\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  If you develop a new program, and you want it to be of the greatest\n");
-  my_strcat(inbuf, "possible use to the public, the best way to achieve this is to make it\n");
-  my_strcat(inbuf, "free software which everyone can redistribute and change under these terms.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  To do so, attach the following notices to the program.  It is safest\n");
-  my_strcat(inbuf, "to attach them to the start of each source file to most effectively\n");
-  my_strcat(inbuf, "convey the exclusion of warranty; and each file should have at least\n");
-  my_strcat(inbuf, "the copyright line and a pointer to where the full notice is found.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "    <one line to give the program's name and a brief idea of what it does.>\n");
-  my_strcat(inbuf, "    Copyright (C) <year>  <name of author>\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "    This program is free software; you can redistribute it and/or modify\n");
-  my_strcat(inbuf, "    it under the terms of the GNU General Public License as published by\n");
-  my_strcat(inbuf, "    the Free Software Foundation; either version 2 of the License, or\n");
-  my_strcat(inbuf, "    (at your option) any later version.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "    This program is distributed in the hope that it will be useful,\n");
-  my_strcat(inbuf, "    but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
-  my_strcat(inbuf, "    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n");
-  my_strcat(inbuf, "    GNU General Public License for more details.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "    You should have received a copy of the GNU General Public License\n");
-  my_strcat(inbuf, "    along with this program; if not, write to the Free Software\n");
-  my_strcat(inbuf, "    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "Also add information on how to contact you by electronic and paper mail.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "If the program is interactive, make it output a short notice like this\n");
-  my_strcat(inbuf, "when it starts in an interactive mode:\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "    Gnomovision version 69, Copyright (C) year  name of author\n");
-  my_strcat(inbuf, "    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n");
-  my_strcat(inbuf, "    This is free software, and you are welcome to redistribute it\n");
-  my_strcat(inbuf, "    under certain conditions; type `show c' for details.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "The hypothetical commands `show w' and `show c' should show the appropriate\n");
-  my_strcat(inbuf, "parts of the General Public License.  Of course, the commands you use may\n");
-  my_strcat(inbuf, "be called something other than `show w' and `show c'; they could even be\n");
-  my_strcat(inbuf, "mouse-clicks or menu items--whatever suits your program.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "You should also get your employer (if you work as a programmer) or your\n");
-  my_strcat(inbuf, "school, if any, to sign a copyright disclaimer for the program, if\n");
-  my_strcat(inbuf, "necessary.  Here is a sample; alter the names:\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n");
-  my_strcat(inbuf, "  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "  <signature of Ty Coon>, 1 April 1989\n");
-  my_strcat(inbuf, "  Ty Coon, President of Vice\n");
-  my_strcat(inbuf, "\n");
-  my_strcat(inbuf, "This General Public License does not permit incorporating your program into\n");
-  my_strcat(inbuf, "proprietary programs.  If your program is a subroutine library, you may\n");
-  my_strcat(inbuf, "consider it more useful to permit linking proprietary applications with the\n");
-  my_strcat(inbuf, "library.  If this is what you want to do, use the GNU Library General\n");
-  my_strcat(inbuf, "Public License instead of this License.\n");
-
-  my_strcat(inbuf, "\n");
-}
-
-#include <stdio.h>
-#include <assert.h>
-
-/* For providing services. */
-static HWord g_serviceFn ( HWord arg1, HWord arg2 )
-{
-   switch (arg1) {
-      case 0: /* EXIT */
-         exit(0);
-      case 1: /* PUTC */
-         putchar(arg2);
-         return 0;
-      case 2: /* MALLOC */
-         return (HWord)malloc(arg2);
-      case 3: /* FREE */
-         free((void*)arg2);
-         return 0;
-      default:
-         assert(0);
-   }
-}
-
-static char *bzerrorstrings[] = {
-       "OK"
-       ,"SEQUENCE_ERROR"
-       ,"PARAM_ERROR"
-       ,"MEM_ERROR"
-       ,"DATA_ERROR"
-       ,"DATA_ERROR_MAGIC"
-       ,"IO_ERROR"
-       ,"UNEXPECTED_EOF"
-       ,"OUTBUFF_FULL"
-       ,"CONFIG_ERROR"
-       ,"???"   /* for future */
-       ,"???"   /* for future */
-       ,"???"   /* for future */
-       ,"???"   /* for future */
-       ,"???"   /* for future */
-       ,"???"   /* for future */
-};
-
-// If given a cmd line arg, behave as a correctness regtest
-// (run fast and be verbose).  If not, run for a long time
-// which is what is needed for the performance suite.
-int main ( int argc, char** argv )
-{
-   int   r;
-   int   bit;
-   int   i;
-
-   int regtest;
-   assert(argc == 1 || argc == 2);
-   regtest = argc==2;
-   regtest = 1;
-   serviceFn = g_serviceFn;
-
-   set_inbuf();
-   nIn = vex_strlen(inbuf)+1;
-   vex_printf( "%d bytes read\n", nIn );
-
-   nZ = M_BLOCK;
-   r = BZ2_bzBuffToBuffCompress (
-          zbuf, &nZ, inbuf, nIn, 9, 3/*verb*/, 30 );
-
-   if (r != BZ_OK) {
-     vex_printf("initial compress failed!\n");
-     (*serviceFn)(0,0);
-   }
-   vex_printf( "%d after compression\n", nZ );
-
-   for (bit = 0; bit < nZ*8; bit += (bit < 35 ? 1 : (regtest?2377:137))) {
-      if (regtest)
-         vex_printf( "bit %d  ", bit );
-      flip_bit ( bit );
-      nOut = M_BLOCK_OUT;
-      r = BZ2_bzBuffToBuffDecompress (
-             outbuf, &nOut, zbuf, nZ, 1/*small*/, 0 );
-      if (regtest)
-         vex_printf( " %d  %s ", r, bzerrorstrings[-r] );
-
-      if (r != BZ_OK) {
-        if (regtest)
-            vex_printf( "\n" );
-      } else {
-         if (nOut != nIn) {
-           vex_printf(  "nIn/nOut mismatch %d %d\n", nIn, nOut );
-           (*serviceFn)(0,0);
-         } else {
-           for (i = 0; i < nOut; i++)
-             if (inbuf[i] != outbuf[i]) { 
-                vex_printf(  "mismatch at %d\n", i ); 
-                (*serviceFn)(0,0); 
-           }
-           if (i == nOut) vex_printf( "really ok!\n" );
-         }
-      }
-
-      flip_bit ( bit );
-   }
-
-#if 0
-   assert (nOut == nIn);
-   for (i = 0; i < nOut; i++) {
-     if (inbuf[i] != outbuf[i]) {
-        vex_printf( "difference at %d !\n", i );
-        return 1;
-     }
-   }
-#endif
-
-   vex_printf( "all ok\n" );
-   (*serviceFn)(0,0);
-   /*NOTREACHED*/
-   return 0;
-}
diff --git a/exp-sgcheck/tests/hackedbz2.stderr.exp-glibc28-amd64 b/exp-sgcheck/tests/hackedbz2.stderr.exp-glibc28-amd64
deleted file mode 100644 (file)
index 6ff30bd..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-
-Invalid read of size 1
-   at 0x........: vex_strlen (hackedbz2.c:1006)
-   by 0x........: add_to_myprintf_buf (hackedbz2.c:1284)
-   by 0x........: vex_printf (hackedbz2.c:1155)
-   by 0x........: BZ2_compressBlock (hackedbz2.c:4039)
-   by 0x........: handle_compress (hackedbz2.c:4761)
-   by 0x........: BZ2_bzCompress (hackedbz2.c:4831)
-   by 0x........: BZ2_bzBuffToBuffCompress (hackedbz2.c:5638)
-   by 0x........: main (hackedbz2.c:6484)
- Address 0x........ expected vs actual:
- Expected: global array "myprintf_buf" of size 70 in object with soname "NONE"
- Actual:   unknown
- Actual:   is 0 after Expected
-
-
-ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/exp-sgcheck/tests/hackedbz2.stdout.exp b/exp-sgcheck/tests/hackedbz2.stdout.exp
deleted file mode 100644 (file)
index 3bfc54e..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-22323 bytes read
-    block 1: crc = 0xA212ABF8, combined CRC = 0xA212ABF8, size = 22373
-    too repetitive; using fallback sorting algorithm
-      22373 in block, 13504 after MTF & 1-2 coding, 79+2 syms in use
-      pass 1: size is 17143, grp uses are 38 62 2 92 6 71 
-      pass 2: size is 6506, grp uses are 28 71 0 86 9 77 
-      pass 3: size is 6479, grp uses are 26 70 0 81 11 83 
-      pass 4: size is 6469, grp uses are 26 69 0 74 17 85 
-      bytes: mapping 19, selectors 66, code lengths 134, codes 6465
-    final combined CRC = 0xA212ABF8
-   6710 after compression
-bit 0   -5  DATA_ERROR_MAGIC 
-bit 1   -5  DATA_ERROR_MAGIC 
-bit 2   -5  DATA_ERROR_MAGIC 
-bit 3   -5  DATA_ERROR_MAGIC 
-bit 4   -5  DATA_ERROR_MAGIC 
-bit 5   -5  DATA_ERROR_MAGIC 
-bit 6   -5  DATA_ERROR_MAGIC 
-bit 7   -5  DATA_ERROR_MAGIC 
-bit 8   -5  DATA_ERROR_MAGIC 
-bit 9   -5  DATA_ERROR_MAGIC 
-bit 10   -5  DATA_ERROR_MAGIC 
-bit 11   -5  DATA_ERROR_MAGIC 
-bit 12   -5  DATA_ERROR_MAGIC 
-bit 13   -5  DATA_ERROR_MAGIC 
-bit 14   -5  DATA_ERROR_MAGIC 
-bit 15   -5  DATA_ERROR_MAGIC 
-bit 16   -5  DATA_ERROR_MAGIC 
-bit 17   -5  DATA_ERROR_MAGIC 
-bit 18   -5  DATA_ERROR_MAGIC 
-bit 19   -5  DATA_ERROR_MAGIC 
-bit 20   -5  DATA_ERROR_MAGIC 
-bit 21   -5  DATA_ERROR_MAGIC 
-bit 22   -5  DATA_ERROR_MAGIC 
-bit 23   -5  DATA_ERROR_MAGIC 
-bit 24   0  OK really ok!
-bit 25   -5  DATA_ERROR_MAGIC 
-bit 26   -5  DATA_ERROR_MAGIC 
-bit 27   0  OK really ok!
-bit 28   -5  DATA_ERROR_MAGIC 
-bit 29   -5  DATA_ERROR_MAGIC 
-bit 30   -5  DATA_ERROR_MAGIC 
-bit 31   -5  DATA_ERROR_MAGIC 
-bit 32   -4  DATA_ERROR 
-bit 33   -4  DATA_ERROR 
-bit 34   -4  DATA_ERROR 
-bit 35   -4  DATA_ERROR 
-bit 2412   -4  DATA_ERROR 
-bit 4789   -4  DATA_ERROR 
-bit 7166   -4  DATA_ERROR 
-bit 9543   -4  DATA_ERROR 
-bit 11920   -4  DATA_ERROR 
-bit 14297   -4  DATA_ERROR 
-bit 16674   -4  DATA_ERROR 
-bit 19051   -4  DATA_ERROR 
-bit 21428   -4  DATA_ERROR 
-bit 23805   -4  DATA_ERROR 
-bit 26182   -4  DATA_ERROR 
-bit 28559   -4  DATA_ERROR 
-bit 30936   -4  DATA_ERROR 
-bit 33313   -4  DATA_ERROR 
-bit 35690   -4  DATA_ERROR 
-bit 38067   -4  DATA_ERROR 
-bit 40444   -4  DATA_ERROR 
-bit 42821   -4  DATA_ERROR 
-bit 45198   -4  DATA_ERROR 
-bit 47575   -4  DATA_ERROR 
-bit 49952   -4  DATA_ERROR 
-bit 52329   -4  DATA_ERROR 
-all ok
diff --git a/exp-sgcheck/tests/hackedbz2.vgtest b/exp-sgcheck/tests/hackedbz2.vgtest
deleted file mode 100644 (file)
index 95a2829..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
-prog: hackedbz2
diff --git a/exp-sgcheck/tests/hsg.c b/exp-sgcheck/tests/hsg.c
deleted file mode 100644 (file)
index 7f497b4..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-
-/* A simple test to demonstrate heap, stack, and global overrun
-   detection. */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-short ga[100];
-
-__attribute__((noinline))
-int addup_wrongly ( short* arr )
-{
-   int sum = 0, i;
-   for (i = 0; i <= 100; i++)
-      sum += (int)arr[i];
-   return sum;
-}
-
-__attribute__((noinline))
-int do_other_stuff ( void )
-{
-   short la[100];
-   return 123 + addup_wrongly(la);
-}
-
-__attribute__((noinline))
-int do_stupid_malloc_stuff ( void )
-{
-   int sum = 0;
-   unsigned char* duh = malloc(100 * sizeof(char));
-   sum += duh[-1];
-   free(duh);
-   sum += duh[50];
-   return sum;
-}
-
-int main ( void )
-{
-   long s = addup_wrongly(ga);
-   s += do_other_stuff();
-   s += do_stupid_malloc_stuff();
-   if (s == 123456789) {
-      fprintf(stdout, "well, i never!\n");
-   } else {
-      fprintf(stdout, "boringly as expected\n");
-   }
-   return 0;
-}
diff --git a/exp-sgcheck/tests/hsg.stderr.exp b/exp-sgcheck/tests/hsg.stderr.exp
deleted file mode 100644 (file)
index 8964070..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-<?xml version="1.0"?>
-
-<valgrindoutput>
-
-<protocolversion>4</protocolversion>
-<protocoltool>exp-sgcheck</protocoltool>
-
-<preamble>
-  <line>...</line>
-  <line>...</line>
-  <line>...</line>
-  <line>...</line>
-  <line>...</line>
-</preamble>
-
-<pid>...</pid>
-<ppid>...</ppid>
-<tool>exp-sgcheck</tool>
-
-<args>
-  <vargv>...</vargv>
-  <argv>
-    <exe>./hsg</exe>
-  </argv>
-</args>
-
-<status>
-  <state>RUNNING</state>
-  <time>...</time>
-</status>
-
-<error>
-  <unique>0x........</unique>
-  <tid>...</tid>
-  <kind>SorG</kind>
-  <what>Invalid read of size 2</what>
-  <stack>
-    <frame>
-      <ip>0x........</ip>
-      <obj>...</obj>
-      <fn>addup_wrongly</fn>
-      <dir>...</dir>
-      <file>hsg.c</file>
-      <line>...</line>
-    </frame>
-    <frame>
-      <ip>0x........</ip>
-      <obj>...</obj>
-      <fn>main</fn>
-      <dir>...</dir>
-      <file>hsg.c</file>
-      <line>...</line>
-    </frame>
-  </stack>
-  <auxwhat>Address 0x........ expected vs actual:</auxwhat>
-  <auxwhat>Expected: global array "ga" of size 200 in object with soname "NONE"</auxwhat>
-  <auxwhat>Actual:   unknown</auxwhat>
-</error>
-
-<error>
-  <unique>0x........</unique>
-  <tid>...</tid>
-  <kind>SorG</kind>
-  <what>Invalid read of size 2</what>
-  <stack>
-    <frame>
-      <ip>0x........</ip>
-      <obj>...</obj>
-      <fn>addup_wrongly</fn>
-      <dir>...</dir>
-      <file>hsg.c</file>
-      <line>...</line>
-    </frame>
-    <frame>
-      <ip>0x........</ip>
-      <obj>...</obj>
-      <fn>do_other_stuff</fn>
-      <dir>...</dir>
-      <file>hsg.c</file>
-      <line>...</line>
-    </frame>
-    <frame>
-      <ip>0x........</ip>
-      <obj>...</obj>
-      <fn>main</fn>
-      <dir>...</dir>
-      <file>hsg.c</file>
-      <line>...</line>
-    </frame>
-  </stack>
-  <auxwhat>Address 0x........ expected vs actual:</auxwhat>
-  <auxwhat>Expected: stack array "la" of size 200 in frame 1 back from here</auxwhat>
-  <auxwhat>Actual:   unknown</auxwhat>
-</error>
-
-
-<status>
-  <state>FINISHED</state>
-  <time>...</time>
-</status>
-
-<errorcounts>
-  <pair>
-    <count>...</count>
-    <unique>0x........</unique>
-  </pair>
-  <pair>
-    <count>...</count>
-    <unique>0x........</unique>
-  </pair>
-</errorcounts>
-
-<suppcounts>...</suppcounts>
-
-</valgrindoutput>
-
diff --git a/exp-sgcheck/tests/hsg.stdout.exp b/exp-sgcheck/tests/hsg.stdout.exp
deleted file mode 100644 (file)
index e5b8e6d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-boringly as expected
diff --git a/exp-sgcheck/tests/hsg.vgtest b/exp-sgcheck/tests/hsg.vgtest
deleted file mode 100644 (file)
index cdf35ba..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
-prog: hsg
-vgopts: --xml=yes --xml-fd=2 --log-file=/dev/null
-stderr_filter: ../../memcheck/tests/filter_xml
diff --git a/exp-sgcheck/tests/is_arch_supported b/exp-sgcheck/tests/is_arch_supported
deleted file mode 100755 (executable)
index d4c6191..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Not all architectures are supported by exp-ptr. Currently, PowerPC, s390x,
-# MIPS and ARM are not supported and will fail these tests as follows:
-# WARNING: exp-ptrcheck on <blah> platforms: stack and global array
-# WARNING: checking is not currently supported.  Only heap checking is
-# WARNING: supported.
-#
-# So we use this script to prevent these tests from running on unsupported
-# architectures.
-
-case `uname -m` in
-  ppc*|aarch64|arm*|s390x|mips*) exit 1;;
-  *)         exit 0;;
-esac
diff --git a/exp-sgcheck/tests/preen_invars.c b/exp-sgcheck/tests/preen_invars.c
deleted file mode 100644 (file)
index cef91be..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-
-#include <stdio.h>
-#include <assert.h>
-#include <dlfcn.h>
-
-/* see comments in preen_invar_so.c for explanation of this */
-
-
-int main ( void )
-{
-  int i, r, sum = 0;
-  char* im_a_global_array;
-  void* hdl = dlopen("./preen_invars_so.so", RTLD_NOW);
-  assert(hdl);
-  im_a_global_array = dlsym(hdl, "im_a_global_array");
-  assert(im_a_global_array);
-  /* printf("%p %p\n", im_a_global_array, me_too_me_too); */
-
-  /* poke around in the global array, so as to cause exp-ptrcheck
-     to generate an Inv_Global invar for it. */
-  for (i = 10/*ERROR*/; i >= 0; i--) {
-     sum += im_a_global_array[i];
-  }
-  /* iterating 10 .. 0 causes an Unknown->Global transition at i = 9.
-     We do it this way in order that at the end of a loop, there is a
-     Global invar in place for the memory read in the loop, so that
-     the subsequent dlclose (hence munmap) causes it to get preened.
-
-     Unfortunately there's nothing to show that the preen was
-     successful or happened at all.  The only way to see is from the
-     -v output:
-
-     --686--  sg_:  251 Invars preened, of which 1 changed
-
-     It's the "1 changed" bit which is significant.
-  */
-
-  /* let's hope gcc is not clever enough to optimise this away, since
-     if it does, then it will also nuke the preceding loop, and
-     thereby render this test program useless. */
-
-  if (sum & 1) printf("%s bar %d\n", "foo", sum & 1); else
-               printf("foo %s %d\n", "bar", 1 - (sum & 1));
-
-  /* Now close (== unmap) the array, so that exp-ptrcheck has to check
-     its collection of Inv_Global invars, and remove this one from
-     it. */
-  r = dlclose(hdl);
-  assert(r == 0);
-
-  return 0;
-}
diff --git a/exp-sgcheck/tests/preen_invars.stderr.exp-glibc28-amd64 b/exp-sgcheck/tests/preen_invars.stderr.exp-glibc28-amd64
deleted file mode 100644 (file)
index 3d08101..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-Invalid read of size 1
-   at 0x........: main (preen_invars.c:22)
- Address 0x........ expected vs actual:
- Expected: unknown
- Actual:   global array "im_a_global_arr" of size 10 in object with soname "preen_invars_so"
-
-
-ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/exp-sgcheck/tests/preen_invars.stdout.exp b/exp-sgcheck/tests/preen_invars.stdout.exp
deleted file mode 100644 (file)
index b3162be..0000000
+++ /dev/null
@@ -1 +0,0 @@
-foo bar 1
diff --git a/exp-sgcheck/tests/preen_invars.vgtest b/exp-sgcheck/tests/preen_invars.vgtest
deleted file mode 100644 (file)
index cbd0d52..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
-prog: preen_invars
diff --git a/exp-sgcheck/tests/preen_invars_so.c b/exp-sgcheck/tests/preen_invars_so.c
deleted file mode 100644 (file)
index 0e59d9c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-
-/* This file contains a global array.  It is compiled into a .so,
-   which is dlopened by preen_invar.c.  That then accesses the global
-   array, hence generating Inv_Global invariants in sg_main.c.
-
-   preen_invar.c then dlcloses this object, causing it to get
-   unmapped; and we then need to be sure that the Inv_Global is
-   removed by preen_Invars (or, at least, that the system doesn't
-   crash..). */
-
-char im_a_global_array[10];
-
diff --git a/exp-sgcheck/tests/stackerr.c b/exp-sgcheck/tests/stackerr.c
deleted file mode 100644 (file)
index 36b8e67..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-
-/* Check basic stack overflow detection.
-
-   It's difficult to get consistent behaviour across all platforms.
-   For example, x86 w/ gcc-4.3.1 gives
-
-     Expected: stack array "a" in frame 2 back from here
-     Actual:   stack array "beforea" in frame 2 back from here
-
-   whereas amd64 w/ gcc-4.3.1 gives
-
-     Expected: stack array "a" in frame 2 back from here
-     Actual:   unknown
-
-   This happens because on x86 the arrays are placed on the
-   stack without holes in between, but not so for amd64.  I don't
-   know why.
-*/
-
-
-#include <stdio.h>
-
-__attribute__((noinline)) void foo ( long* sa, int n )
-{
-  int i;
-  for (i = 0; i < n; i++)
-    sa[i] = 0;
-}
-
-__attribute__((noinline)) void bar ( long* sa, int n )
-{
-   foo(sa, n);
-}
-
-int main ( void )
-{
-  int i;
-  long beforea[3];
-  long a[7];
-  long aftera[3];
-  bar(a, 7+1);     /* generates error */
-  bar(a, 7+0);     /* generates no error */
-  for (i = 0; i < 7+1; i++) {
-     a[i] = 0;
-  }
- {char beforebuf[8];
-  char buf[8];
-  char afterbuf[8];
-  sprintf(buf, "%d", 123456789);
-  return 1 & ((a[4] + beforea[1] + aftera[1] + beforebuf[1] 
-                    + buf[2] + afterbuf[3]) / 100000) ;
- }
-}
diff --git a/exp-sgcheck/tests/stackerr.stderr.exp-glibc27-x86 b/exp-sgcheck/tests/stackerr.stderr.exp-glibc27-x86
deleted file mode 100644 (file)
index b551dc5..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-
-Invalid write of size 4
-   at 0x........: foo (stackerr.c:27)
-   by 0x........: bar (stackerr.c:32)
-   by 0x........: main (stackerr.c:41)
- Address 0x........ expected vs actual:
- Expected: stack array "a" of size 28 in frame 2 back from here
- Actual:   stack array "beforea" of size 12 in frame 2 back from here
- Actual:   is 0 after Expected
-
-Invalid write of size 4
-   at 0x........: main (stackerr.c:44)
- Address 0x........ expected vs actual:
- Expected: stack array "a" of size 28 in this frame
- Actual:   stack array "beforea" of size 12 in this frame
- Actual:   is 0 after Expected
-
-Invalid write of size 1
-   at 0x........: _IO_default_xsputn (in /...libc...)
-   by 0x........: ...
-   by 0x........: ...
- Address 0x........ expected vs actual:
- Expected: stack array "buf" of size 8 in frame 4 back from here
- Actual:   stack array "beforebuf" of size 8 in frame 4 back from here
- Actual:   is 0 after Expected
-
-
-ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
diff --git a/exp-sgcheck/tests/stackerr.stderr.exp-glibc28-amd64 b/exp-sgcheck/tests/stackerr.stderr.exp-glibc28-amd64
deleted file mode 100644 (file)
index f15f025..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-
-Invalid write of size 8
-   at 0x........: foo (stackerr.c:27)
-   by 0x........: bar (stackerr.c:32)
-   by 0x........: main (stackerr.c:41)
- Address 0x........ expected vs actual:
- Expected: stack array "a" of size 56 in frame 2 back from here
- Actual:   unknown
- Actual:   is 0 after Expected
-
-Invalid write of size 8
-   at 0x........: main (stackerr.c:44)
- Address 0x........ expected vs actual:
- Expected: stack array "a" of size 56 in this frame
- Actual:   unknown
- Actual:   is 0 after Expected
-
-Invalid write of size 1
-   at 0x........: _IO_default_xsputn (in /...libc...)
-   by 0x........: ...
-   by 0x........: ...
- Address 0x........ expected vs actual:
- Expected: stack array "buf" of size 8 in frame 4 back from here
- Actual:   unknown
- Actual:   is 0 after Expected
-
-
-ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
diff --git a/exp-sgcheck/tests/stackerr.stdout.exp b/exp-sgcheck/tests/stackerr.stdout.exp
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/exp-sgcheck/tests/stackerr.vgtest b/exp-sgcheck/tests/stackerr.vgtest
deleted file mode 100644 (file)
index 8f20a4f..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-prereq: ./is_arch_supported && (../../tests/os_test linux || ../../tests/os_test solaris)
-vgopts: --num-callers=3
-prog: stackerr
index 71590d03a5d0d0d89c46527a0c954495de86c6e0..e53423b425a16340630d7a3a2694d15bdf46630d 100644 (file)
@@ -340,8 +340,7 @@ void delayXms ( int i )
    // We do the sleep in small pieces to have scheduling
    // events ensuring a fair switch between threads, even
    // without --fair-sched=yes. This is a.o. needed for
-   // running this test under an outer helgrind or an outer
-   // sgcheck.
+   // running this test under an outer helgrind.
    while (i > 0) {
       nanosleep(&ts, NULL);
       i--;
index 7b65b4e93e0e910b708f9f17ec2eceecc789f2de..46c49280a275b1b22857192e1c4c6433d43ea865 100644 (file)
@@ -56,8 +56,6 @@ file path=usr/lib/valgrind/drd-amd64-solaris                             owner=r
 file path=usr/lib/valgrind/drd-x86-solaris                               owner=root group=bin mode=0755
 file path=usr/lib/valgrind/exp-bbv-amd64-solaris                         owner=root group=bin mode=0755
 file path=usr/lib/valgrind/exp-bbv-x86-solaris                           owner=root group=bin mode=0755
-file path=usr/lib/valgrind/exp-sgcheck-amd64-solaris                     owner=root group=bin mode=0755
-file path=usr/lib/valgrind/exp-sgcheck-x86-solaris                       owner=root group=bin mode=0755
 file path=usr/lib/valgrind/getoff-amd64-solaris                          owner=root group=bin mode=0755
 file path=usr/lib/valgrind/getoff-x86-solaris                            owner=root group=bin mode=0755
 file path=usr/lib/valgrind/helgrind-amd64-solaris                        owner=root group=bin mode=0755
@@ -77,8 +75,6 @@ file path=usr/lib/valgrind/vgpreload_drd-amd64-solaris.so                owner=r
 file path=usr/lib/valgrind/vgpreload_drd-x86-solaris.so                  owner=root group=bin mode=0755
 file path=usr/lib/valgrind/vgpreload_dhat-amd64-solaris.so               owner=root group=bin mode=0755
 file path=usr/lib/valgrind/vgpreload_dhat-x86-solaris.so                 owner=root group=bin mode=0755
-file path=usr/lib/valgrind/vgpreload_exp-sgcheck-amd64-solaris.so        owner=root group=bin mode=0755
-file path=usr/lib/valgrind/vgpreload_exp-sgcheck-x86-solaris.so          owner=root group=bin mode=0755
 file path=usr/lib/valgrind/vgpreload_massif-amd64-solaris.so             owner=root group=bin mode=0755
 file path=usr/lib/valgrind/vgpreload_massif-x86-solaris.so               owner=root group=bin mode=0755
 file path=usr/lib/valgrind/vgpreload_memcheck-amd64-solaris.so           owner=root group=bin mode=0755
index 49a51e1e03fb5438e874705b395e1662aebdb27f..0148cbf4de26208a1c7cc4b39f07cdc71422f1a7 100755 (executable)
@@ -52,7 +52,6 @@ my %tool_dirs = (
     "lackey" => 1,
     "none" => 1,
     "exp-bbv" => 1,
-    "exp-sgcheck" => 1,
     "shared" => 1,
     );