diff -urN linux-2.2.5-e2c0.4.30/arch/alpha/defconfig linux-2.2.5-e2c0.4.30-lzrw/arch/alpha/defconfig
--- linux-2.2.5-e2c0.4.30/arch/alpha/defconfig	
+++ linux-2.2.5-e2c0.4.30-lzrw/arch/alpha/defconfig	
@@ -261,10 +261,12 @@
 CONFIG_EXT2_COMPRESS=n
 CONFIG_EXT2_HAVE_LZO=y
 CONFIG_EXT2_HAVE_LZV1=y
+# CONFIG_EXT2_HAVE_LZRW3A is not set
 CONFIG_EXT2_HAVE_GZIP=y
 CONFIG_EXT2_HAVE_BZIP2=y
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_NONE is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZV1 is not set
+# CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZRW3A is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP1 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP3 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP6 is not set
diff -urN linux-2.2.5-e2c0.4.30/arch/arm/defconfig linux-2.2.5-e2c0.4.30-lzrw/arch/arm/defconfig
--- linux-2.2.5-e2c0.4.30/arch/arm/defconfig	
+++ linux-2.2.5-e2c0.4.30-lzrw/arch/arm/defconfig	
@@ -181,10 +181,12 @@
 CONFIG_EXT2_COMPRESS=n
 CONFIG_EXT2_HAVE_LZO=y
 CONFIG_EXT2_HAVE_LZV1=y
+# CONFIG_EXT2_HAVE_LZRW3A is not set
 CONFIG_EXT2_HAVE_GZIP=y
 CONFIG_EXT2_HAVE_BZIP2=y
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_NONE is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZV1 is not set
+# CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZRW3A is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP1 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP3 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP6 is not set
diff -urN linux-2.2.5-e2c0.4.30/arch/i386/defconfig linux-2.2.5-e2c0.4.30-lzrw/arch/i386/defconfig
--- linux-2.2.5-e2c0.4.30/arch/i386/defconfig	
+++ linux-2.2.5-e2c0.4.30-lzrw/arch/i386/defconfig	
@@ -312,10 +312,12 @@
 CONFIG_EXT2_COMPRESS=n
 CONFIG_EXT2_HAVE_LZO=y
 CONFIG_EXT2_HAVE_LZV1=y
+# CONFIG_EXT2_HAVE_LZRW3A is not set
 CONFIG_EXT2_HAVE_GZIP=y
 CONFIG_EXT2_HAVE_BZIP2=y
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_NONE is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZV1 is not set
+# CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZRW3A is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP1 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP3 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP6 is not set
diff -urN linux-2.2.5-e2c0.4.30/arch/m68k/defconfig linux-2.2.5-e2c0.4.30-lzrw/arch/m68k/defconfig
--- linux-2.2.5-e2c0.4.30/arch/m68k/defconfig	
+++ linux-2.2.5-e2c0.4.30-lzrw/arch/m68k/defconfig	
@@ -183,11 +183,13 @@
 CONFIG_EXT2_COMPRESS=n
 CONFIG_EXT2_HAVE_LZO=y
 CONFIG_EXT2_HAVE_LZV1=y
+# CONFIG_EXT2_HAVE_LZRW3A is not set
 CONFIG_EXT2_HAVE_GZIP=y
 CONFIG_EXT2_HAVE_BZIP2=y
 CONFIG_EXT2_COMPR_X86_CODE=y
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_NONE is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZV1 is not set
+# CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZRW3A is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP1 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP3 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP6 is not set
diff -urN linux-2.2.5-e2c0.4.30/arch/mips/defconfig linux-2.2.5-e2c0.4.30-lzrw/arch/mips/defconfig
--- linux-2.2.5-e2c0.4.30/arch/mips/defconfig	
+++ linux-2.2.5-e2c0.4.30-lzrw/arch/mips/defconfig	
@@ -271,11 +271,13 @@
 CONFIG_EXT2_COMPRESS=n
 CONFIG_EXT2_HAVE_LZO=y
 CONFIG_EXT2_HAVE_LZV1=y
+# CONFIG_EXT2_HAVE_LZRW3A is not set
 CONFIG_EXT2_HAVE_GZIP=y
 CONFIG_EXT2_HAVE_BZIP2=y
 CONFIG_EXT2_COMPR_X86_CODE=y
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_NONE is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZV1 is not set
+# CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZRW3A is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP1 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP3 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP6 is not set
diff -urN linux-2.2.5-e2c0.4.30/arch/ppc/defconfig linux-2.2.5-e2c0.4.30-lzrw/arch/ppc/defconfig
--- linux-2.2.5-e2c0.4.30/arch/ppc/defconfig	
+++ linux-2.2.5-e2c0.4.30-lzrw/arch/ppc/defconfig	
@@ -365,10 +365,12 @@
 CONFIG_EXT2_COMPRESS=n
 CONFIG_EXT2_HAVE_LZO=y
 CONFIG_EXT2_HAVE_LZV1=y
+# CONFIG_EXT2_HAVE_LZRW3A is not set
 CONFIG_EXT2_HAVE_GZIP=y
 CONFIG_EXT2_HAVE_BZIP2=y
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_NONE is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZV1 is not set
+# CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZRW3A is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP1 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP3 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP6 is not set
diff -urN linux-2.2.5-e2c0.4.30/arch/sparc/defconfig linux-2.2.5-e2c0.4.30-lzrw/arch/sparc/defconfig
--- linux-2.2.5-e2c0.4.30/arch/sparc/defconfig	
+++ linux-2.2.5-e2c0.4.30-lzrw/arch/sparc/defconfig	
@@ -242,10 +242,12 @@
 CONFIG_EXT2_COMPRESS=n
 CONFIG_EXT2_HAVE_LZO=y
 CONFIG_EXT2_HAVE_LZV1=y
+# CONFIG_EXT2_HAVE_LZRW3A is not set
 CONFIG_EXT2_HAVE_GZIP=y
 CONFIG_EXT2_HAVE_BZIP2=y
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_NONE is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZV1 is not set
+# CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZRW3A is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP1 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP3 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP6 is not set
diff -urN linux-2.2.5-e2c0.4.30/arch/sparc64/defconfig linux-2.2.5-e2c0.4.30-lzrw/arch/sparc64/defconfig
--- linux-2.2.5-e2c0.4.30/arch/sparc64/defconfig	
+++ linux-2.2.5-e2c0.4.30-lzrw/arch/sparc64/defconfig	
@@ -279,10 +279,12 @@
 CONFIG_EXT2_COMPRESS=n
 CONFIG_EXT2_HAVE_LZO=y
 CONFIG_EXT2_HAVE_LZV1=y
+# CONFIG_EXT2_HAVE_LZRW3A is not set
 CONFIG_EXT2_HAVE_GZIP=y
 CONFIG_EXT2_HAVE_BZIP2=y
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_NONE is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZV1 is not set
+# CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZRW3A is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP1 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP3 is not set
 # CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP6 is not set
diff -urN linux-2.2.5-e2c0.4.30/fs/Config.in linux-2.2.5-e2c0.4.30-lzrw/fs/Config.in
--- linux-2.2.5-e2c0.4.30/fs/Config.in	
+++ linux-2.2.5-e2c0.4.30-lzrw/fs/Config.in	
@@ -55,6 +55,7 @@
   if [ "$CONFIG_EXT2_COMPRESS" = "y" ]; then
     tristate '    LZO1X_1 algorithm' CONFIG_EXT2_HAVE_LZO
     tristate '    LZV1 algorithm' CONFIG_EXT2_HAVE_LZV1
+    tristate '    LZRW3A algorithm (patented and thus deprecated; see help text)' CONFIG_EXT2_HAVE_LZRW3A
     tristate '    GZIP algorithm' CONFIG_EXT2_HAVE_GZIP
     tristate '    BZIP2 algorithm' CONFIG_EXT2_HAVE_BZIP2
     # It would be nice if we could restrict the choice to the algorithms
@@ -65,6 +66,7 @@
     	"defer CONFIG_EXT2_DEFAULT_COMPR_METHOD_DEFER \
     	LZO CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZO \
     	LZV1 CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZV1 \
+	LZRW3A CONFIG_EXT2_DEFAULT_COMPR_METHOD_LZRW3A \
 	GZIP CONFIG_EXT2_DEFAULT_COMPR_METHOD_GZIP \
 	BZIP2 CONFIG_EXT2_DEFAULT_COMPR_METHOD_BZIP2"  GZIP
     # N.B. Don't offer EXT2_NEVER_METH or any lossy algorithms for the
diff -urN linux-2.2.5-e2c0.4.30/fs/ext2/Makefile linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/Makefile
--- linux-2.2.5-e2c0.4.30/fs/ext2/Makefile	
+++ linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/Makefile	
@@ -8,7 +8,7 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 SUB_DIRS := 
-ALL_SUB_DIRS := bzip gzip lzo lzv
+ALL_SUB_DIRS := bzip gzip lzo lzrw lzv
 MOD_LIST_NAME := E2C_MODULES
 
 ifeq ($(CONFIG_EXT2_COMPRESS),y)
@@ -34,6 +34,14 @@
 else
   ifeq ($(CONFIG_EXT2_HAVE_LZO),m)
   MOD_SUB_DIRS += lzo
+  endif
+endif
+
+ifeq ($(CONFIG_EXT2_HAVE_LZRW3A),y)
+SUB_DIRS += lzrw
+else
+  ifeq ($(CONFIG_EXT2_HAVE_LZRW3A),m)
+  MOD_SUB_DIRS += lzrw
   endif
 endif
 
diff -urN linux-2.2.5-e2c0.4.30/fs/ext2/compress.c linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/compress.c
--- linux-2.2.5-e2c0.4.30/fs/ext2/compress.c	
+++ linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/compress.c	
@@ -101,7 +101,11 @@
 	{"lzv1", 0, ext2_iNONE, ext2_wNONE, ext2_rNONE},
 #endif
 
+#ifdef  CONFIG_EXT2_HAVE_LZRW3A
+	{"lzrw3a", 1, ext2_iLZRW3A, ext2_wLZRW3A, ext2_rLZRW3A},
+#else
 	{"lzrw3a", 0, ext2_iNONE, ext2_wNONE, ext2_rNONE},
+#endif
 
 
 #ifdef  CONFIG_EXT2_HAVE_GZIP
diff -urN linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/Makefile linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/Makefile
--- linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/Makefile	
+++ linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/Makefile	
@@ -0,0 +1,23 @@
+#
+# Makefile for the linux compression routines.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.o:
+	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+
+O_TARGET := lzrw.o
+
+ifeq ($(CONFIG_EXT2_COMPR_X86_CODE),y)
+O_OBJS   := e2compr-lzrw3a.o rlzrw3a.o wlzrw3a.o
+else
+O_OBJS   := e2compr-lzrw3a.o lzrw3a.o
+endif
+
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/e2compr-lzrw3a.c linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/e2compr-lzrw3a.c
--- linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/e2compr-lzrw3a.c	
+++ linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/e2compr-lzrw3a.c	
@@ -0,0 +1,72 @@
+#include <linux/ext2_fs_c.h>
+#include <linux/types.h>
+#include <linux/module.h>
+
+#include "lzrw.h"
+
+#define U(X)	((unsigned long) X)
+#define MEM_REQ	(U(4096)*(U(sizeof(unsigned char *))) + (U(16)))
+
+extern int ext2_LZRW3A_compress(UBYTE *p_src_first, UBYTE *p_dst_first,
+				UBYTE *heap, int  src_len, int p_dst_len);
+extern int ext2_LZRW3A_decompress(UBYTE *p_src_first, UBYTE *p_dst,
+				UBYTE *heap, int src_len, int dst_len);
+
+size_t ext2_iLZRW3A(int action)
+{
+	switch (action) {
+		case EXT2_ALG_INIT_COMPRESS:
+			return MEM_REQ;
+		case EXT2_ALG_INIT_DECOMPRESS:
+			return MEM_REQ;
+		default:
+			return 0;
+	}
+}
+
+size_t ext2_wLZRW3A (unsigned char *p_src_first, unsigned char *p_dst_first,
+		void *heap, size_t src_len, size_t p_dst_len, int xarg)
+{
+	int ret_code;
+
+	MOD_INC_USE_COUNT;
+	ret_code = ext2_LZRW3A_compress(p_src_first, p_dst_first, heap, src_len, p_dst_len);
+	MOD_DEC_USE_COUNT;
+	return ret_code;
+}
+
+size_t ext2_rLZRW3A (unsigned char *p_src_first, unsigned char *p_dst,
+		void *heap, size_t src_len, size_t dst_len, int xarg)
+{
+	int ret_code;
+
+	MOD_INC_USE_COUNT;
+	ret_code = ext2_LZRW3A_decompress(p_src_first, p_dst, heap, src_len, dst_len);
+	MOD_DEC_USE_COUNT;
+	return ret_code;
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+        struct ext2_algorithm lzrw3a_alg;
+
+        lzrw3a_alg.name = NULL;
+        lzrw3a_alg.avail = 1;
+        lzrw3a_alg.init = ext2_iLZRW3A;
+        lzrw3a_alg.compress = ext2_wLZRW3A;
+        lzrw3a_alg.decompress = ext2_rLZRW3A;
+
+        return ext2_register_compression_module(EXT2_LZRW3A_ALG,
+                        MEM_REQ, MEM_REQ,
+                        &lzrw3a_alg);
+}
+
+void cleanup_module(void)
+{
+        ext2_unregister_compression_module(EXT2_LZRW3A_ALG);
+}
+
+#endif
+
diff -urN linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/lzrw.h linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/lzrw.h
--- linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/lzrw.h	
+++ linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/lzrw.h	
@@ -0,0 +1,106 @@
+/* Author : Ross Williams.                                                    */
+/* Date   : December 1989.                                                    */
+/* This header file and the C functions have been modified in order to        */
+/* include them in the DouBle device driver by Jean-Marc Verbavatz, Feb 1994. */
+/*                                                                            */
+/* This header file defines the interface to a set of lzrw functions          */
+/* each member of which implements a particular data compression              */
+/* algorithm.                                                                 */
+/*                                                                            */
+/* Normally in C programming, for each .H file, there is a corresponding .C   */
+/* file that implements the functions promised in the .H file.                */
+/* Here, there are many .C files corresponding to this header file.           */
+/* Each comforming implementation file contains a single function             */
+/* called that implements a single data compression                           */
+/* algorithm that conforms with the interface specified in this header file.  */
+/*                                                                            */
+/******************************************************************************/
+/* See the formal C definition later for a description of the parameters.     */
+/*                                                                            */
+/* Although compression algorithms usually compress data, there will always   */
+/* be data that a given compressor will expand (this can be proven).          */
+/*                                                                            */
+/* Unfortunately, in general, the only way to tell if an algorithm will       */
+/* expand a particular block of data is to run the algorithm on the data.     */
+/* If the algorithm does not continuously monitor how many output bytes it    */
+/* has written, it might write an output block far larger than the input      */
+/* block before realizing that it has done so.                                */
+/* On the other hand, continuous checks on output length are inefficient.     */
+/*                                                                            */
+/* The problem does not arise for decompression.                              */
+/*                                                                            */
+/******************************************************************************/
+/* Macro definitions and types that are likely to change between computers.   */
+/*                                                                            */
+#ifndef DONE_PORT       /* Only do this if not previously done.               */
+   #ifndef TRUE
+	#define TRUE 1
+	#define FALSE 0
+   #endif
+   #ifndef UBYTE
+      #define UBYTE unsigned char      /* Unsigned byte                       */
+      #define UWORD unsigned short     /* Unsigned word (2 bytes)             */
+      #define ULONG unsigned long      /* Unsigned word (4 bytes)             */
+  #endif
+
+   #define DONE_PORT                   /* Don't do all this again.            */
+   #define LOCAL static                /* For non-exported routines.          */
+   #define EXPORT                      /* Signals exported function.          */
+
+#endif
+
+#if 0
+extern void *ext2_lzrw3a_htab;
+#endif
+
+int  rlzrw2(        /* function for decompression algorithm. */
+UBYTE   *src_adr,      /* Address of input  data.            */
+UBYTE   *dst_adr,      /* Address of output data.            */
+int      src_len,      /* Length  of output data.            */
+int      dst_len       /* Length  of output data.            */
+);
+
+void  wlzrw2(        /* function for compression algorithm. */
+UBYTE   *src_adr,      /* Address of input  data.           */
+int      src_len,      /* Length  of input  data.           */
+UBYTE   *dst_adr,      /* Address of output data.           */
+int   *p_dst_len       /* Pointer to a longword for         */
+                       /*    Length of output data. */
+);
+
+int  rlzrw3(        /* function for decompression algorithm. */
+UBYTE   *src_adr,      /* Address of input  data.                             */
+UBYTE   *dst_adr,      /* Address of output data.                             */
+ULONG    dst_len       /* Length  of output data.                             */
+);
+
+void  wlzrw3(        /* function for compression algorithm. */
+UBYTE   *src_adr,      /* Address of input  data.                             */
+ULONG    src_len,      /* Length  of input  data.                             */
+UBYTE   *dst_adr,      /* Address of output data.                             */
+ULONG *p_dst_len       /* Pointer to a longword where routine will write:     */
+                       /*    Length of output data. */
+);
+/*
+ * NOTE: lzrw3 is not implemented in the DouBle driver version 0.2
+ */
+
+int  rlzrw3a(        /* function for decompression algorithm. */
+UBYTE   *src_adr,      /* Address of input  data.             */
+UBYTE   *dst_adr,      /* Address of output data.             */
+int      src_len,      /* Length  of input data.              */
+int      dst_len       /* Length  of output data.             */
+);
+
+void  wlzrw3a(        /* function for compression algorithm. */
+UBYTE   *src_adr,      /* Address of input  data.            */
+int      src_len,      /* Length  of input  data.            */
+UBYTE   *dst_adr,      /* Address of output data.            */
+int   *p_dst_len       /* Pointer to a longword for          */
+                       /*    Length of output data.          */
+);
+
+/******************************************************************************/
+/*                             End of LZRW.H                                  */
+/******************************************************************************/
+
diff -urN linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/lzrw3a.c linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/lzrw3a.c
--- linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/lzrw3a.c	
+++ linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/lzrw3a.c	
@@ -0,0 +1,803 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                  LZRW3-A.C                                */
+/*                                                                           */
+/*****************************************************************************/
+/*                                                                           */
+/* Author  : Ross Williams.                                                  */
+/* Date    : 15-Jul-1991.                                                    */
+/* Release : 1.                                                              */
+/*                                                                           */
+/*****************************************************************************/
+/*                                                                           */
+/* This file contains an implementation of the LZRW3-A data compression      */
+/* algorithm in the C programming language.                                  */
+/*                                                                           */
+/* The LZRW3-A algorithm has the following features:                         */
+/*                                                                           */
+/*    1 Requires only 16K of memory (for both compression and decompression).*/
+/*    2 The compressor   runs about two   times faster than Unix compress's. */
+/*    3 The decompressor runs about three times faster than Unix compress's. */
+/*    4 Yields a few percent better compression than Unix compress for       */
+/*      most files.                                                          */
+/*    5 Allows you to dial up extra compression at a speed cost in the       */
+/*      compressor. The speed of the decompressor is not affected.           */
+/*    6 Algorithm is deterministic.                                          */
+/*    8 This implementation in C is in the public domain.                    */
+/*                                                                           */
+/* (Timing tests for the speed comparison were performed on a Pyramid 9820.) */
+/*                                                                           */
+/* LZRW3-A is LZRW3 with a deepened hash table. This simple change yields    */
+/* about a 6% (absolute) improvement in compression.                         */
+/*                                                                           */
+/* Here are the results of applying this code, compiled under THINK C 4.0    */
+/* and running on a Mac-SE (8MHz 68000), to the standard calgary corpus.     */
+/*                                                                           */
+/*     +----------------------------------------------------------------+    */
+/*     | DATA COMPRESSION TEST                                          |    */
+/*     | =====================                                          |    */
+/*     | Time of run     : Mon 15-Jul-1991 05:29PM                      |    */
+/*     | Timing accuracy : One part in 100                              |    */
+/*     | Context length  : 262144 bytes (= 256.0000K)                   |    */
+/*     | Test suite      : Calgary Corpus Suite                         |    */
+/*     | Files in suite  : 14                                           |    */
+/*     | Algorithm       : LZRW3-A                                      |    */
+/*     | Note: All averages are calculated from the un-rounded values.  |    */
+/*     +----------------------------------------------------------------+    */
+/*     | File Name   Length  CxB  ComLen  %Remn  Bits  Com K/s  Dec K/s |    */
+/*     | ----------  ------  ---  ------  -----  ----  -------  ------- |    */
+/*     | rpus:Bib.D  111261    1   49044   44.1  3.53     8.47    31.19 |    */
+/*     | us:Book1.D  768771    3  420464   54.7  4.38     7.27    30.07 |    */
+/*     | us:Book2.D  610856    3  277955   45.5  3.64     8.51    33.40 |    */
+/*     | rpus:Geo.D  102400    1   84218   82.2  6.58     4.23    15.04 |    */
+/*     | pus:News.D  377109    2  192880   51.1  4.09     7.08    25.89 |    */
+/*     | pus:Obj1.D   21504    1   12651   58.8  4.71     5.23    17.44 |    */
+/*     | pus:Obj2.D  246814    1  108044   43.8  3.50     8.01    28.11 |    */
+/*     | s:Paper1.D   53161    1   24526   46.1  3.69     8.11    30.24 |    */
+/*     | s:Paper2.D   82199    1   39483   48.0  3.84     8.11    32.04 |    */
+/*     | rpus:Pic.D  513216    2  111622   21.7  1.74    10.64    49.31 |    */
+/*     | us:Progc.D   39611    1   17923   45.2  3.62     8.06    29.01 |    */
+/*     | us:Progl.D   71646    1   24362   34.0  2.72    10.74    39.51 |    */
+/*     | us:Progp.D   49379    1   16805   34.0  2.72    10.64    37.58 |    */
+/*     | us:Trans.D   93695    1   30296   32.3  2.59    11.02    38.06 |    */
+/*     +----------------------------------------------------------------+    */
+/*     | Average     224401    1  100733   45.8  3.67     8.29    31.21 |    */
+/*     +----------------------------------------------------------------+    */
+/*                                                                           */
+/*****************************************************************************/
+
+#include "lzrw.h"
+/******************************************************************************/
+
+/*
+  The following structure is returned by the "compress" function below when 
+  the user asks the function to return identifying information.             
+  The most important field in the record is the working memory field which  
+  tells the calling program how much working memory should be passed to     
+  "compress" when it is called to perform a compression or decompression.   
+  LZRW3-A uses the same amount of memory during compression and             
+  decompression. For more information on this structure see "lzrw.h".       
+  The alignment fudge below really only needs to be 4 (but I play it safe!).
+  The id looks non-random, but it really was generated by coin tossing!     
+  */
+
+#define U(X)            ((ULONG) X)
+#define SIZE_P_BYTE     (U(sizeof(UBYTE *)))
+#define ALIGNMENT_FUDGE (U(16))
+#define MEM_REQ ( U(4096)*(SIZE_P_BYTE) + ALIGNMENT_FUDGE )
+
+/*
+   static struct compress_identity identity =
+   {
+     U(0x01B90B91),                         * Algorithm identification number. * 
+     MEM_REQ,                               * Working memory (bytes) required. * 
+     "LZRW3-A",                             * Name of algorithm.               * 
+     "1.0",                                 * Version number of algorithm.     * 
+     "15-Jul-1990",                         * Date of algorithm.               * 
+     "Ross N. Williams",                    * Author of algorithm.             * 
+     "Renaissance Software",                * Affiliation of author.           * 
+   };
+*/
+
+/******************************************************************************/
+/*                                                                            */
+/* BRIEF DESCRIPTION OF THE LZRW3-A ALGORITHM                                 */
+/* ==========================================                                 */
+/* Note: Before attempting to understand this algorithm, you should first     */
+/* understand the LZRW3 algorithm from which this algorithm is derived.       */
+/*                                                                            */
+/* The LZRW3-A algorithm is identical to the LZRW3 algorithm except that the  */
+/* hash table has been "deepened". The LZRW3 algorithm has a hash table of    */
+/* 4096 pointers which point to strings in the buffer. LZRW3-A generalizes    */
+/* this to 4096/(2^n) partitions each of which contains (2^n) pointers.       */
+/* In LZRW3-A, the hash function hashes to a partition number.                */
+/*                                                                            */
+/* During the processing of each phrase, LZRW3 overwrites the pointer in the  */
+/* position selected by the hash function. LZRW3-A overwrites one of the      */
+/* pointers in the partition that was selected by the hash function.          */
+/*                                                                            */
+/* When searching for a match, LZRW3-A matches against all (2^n) strings      */
+/* pointed to by the pointers in the target partition.                        */
+/*                                                                            */
+/* Deep hash tables were used in early versions of LZRW1 in late 1989, but    */
+/* were discarded in an effort to increase speed (which was the primary       */
+/* requirement for LZRW1). They were revived for use in LZRW3-A in order to   */
+/* produce an algorithm with compression performance competitive with Unix    */
+/* compress.                                                                  */
+/*                                                                            */
+/* Until 14-Jul-1991, deep hash tables used in prototype LZRW* algorithms     */
+/* used a queue discipline within each partition. Upon the arrival of a new   */
+/* pointer, the pointers in the partition would be block copied back one      */
+/* position (with the oldest pointer being overwritten) and the new pointer   */
+/* being inserted in the space at the front (the youngest position).          */
+/* This meant that pointers to the (2^n) most recent phrases corresponding to */
+/* each hash was kept. The only flaw in this system was the time-consuming    */
+/* block copy operation which was cheap for shallow tables but expensive for  */
+/* deep tables.                                                               */
+/*                                                                            */
+/* The traditional solution to ring buffer block copy problems is to maintain */
+/* a cyclic counter which points to the "head" of the queue. However, this    */
+/* would have required one counter to be stored for each partition and would  */
+/* have been slightly messy. After some thought (on 14-Jul-1991) a better     */
+/* solution was found. Instead of maintaining a counter for each partition,   */
+/* LZRW3-A maintains a single counter for all partitions! This counter is     */
+/* maintained in both the compressor and decompressor and means that the      */
+/* algorithm (effectively) overwrites a RANDOM element of the partition to be */
+/* updated. The result was to increase the speed of the compressor and        */
+/* decompressor, to make the decompressor's speed independent from whatever   */
+/* depth was selected, and to impair compression by less than 1% absolute.    */
+/*                                                                            */
+/* Setting the depth is a speed/compression tradeoff. The table below gives   */
+/* the tradeoff observed for a typical 50K text file on a Mac-SE.             */
+/* Note: %Rem=Percentage Remaining (after compression).                       */
+/*                                                                            */
+/*      Depth    %Rem    CmpK/s  DecK/s                                       */
+/*          1    45.2    14.77   32.24                                        */
+/*          2    42.6    12.12   31.26                                        */
+/*          4    40.9    10.28   31.91                                        */
+/*          8    40.0     7.81   32.36                                        */
+/*         16    39.5     5.30   32.47                                        */
+/*         32    39.0     3.23   32.59                                        */
+/*                                                                            */
+/* I have chosen a depth of 8 as the "default" depth for LZRW3-A. If you use  */
+/* a depth different to this (e.g. 4), you should use the name LZRW3-A(4) to  */
+/* indicate that a different depth is being used. LZRW3-A(8) is an acceptable */
+/* longhand for LZRW3-A.                                                      */
+/*                                                                            */
+/* To change the depth, search for "HERE IT IS" in the rest of this file.     */
+/*                                                                            */
+/*                                  +---+                                     */
+/*                                  |___|4095                                 */
+/*                                  |===|                                     */
+/*              +---------------------*_|<---+   /----+---\                   */
+/*              |                   |___|    +---|Hash    |                   */
+/*              |    512 partitions |___|        |Function|                   */
+/*              |    of 8 pointers  |===|        \--------/                   */
+/*              |    each (or any   |___|0            ^                       */
+/*              |    a*b=4096)      +---+             |                       */
+/*              |                   Hash        +-----+                       */
+/*              |                   Table       |                             */
+/*              |                              ---                            */
+/*              v                              ^^^                            */
+/*      +-------------------------------------|----------------+              */
+/*      ||||||||||||||||||||||||||||||||||||||||||||||||||||||||              */
+/*      +-------------------------------------|----------------+              */
+/*      |                                     |1......18|      |              */
+/*      |<------- Lempel=History ------------>|<--Ziv-->|      |              */
+/*      |     (=bytes already processed)      |<-Still to go-->|              */
+/*      |<-------------------- INPUT BLOCK ------------------->|              */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+/*                                                                            */
+/*                     DEFINITION OF COMPRESSED FILE FORMAT                   */
+/*                     ====================================                   */
+/*    The file consists of zero  */
+/*    or more GROUPS, each of which represents one or more bytes.             */
+/*  * Each group consists of two bytes of CONTROL information followed by     */
+/*    sixteen ITEMs except for the last group which can contain from one      */
+/*    to sixteen items.                                                       */
+/*  * An item can be either a LITERAL item or a COPY item.                    */
+/*  * Each item corresponds to a bit in the control bytes.                    */
+/*  * The first control byte corresponds to the first 8 items in the group    */
+/*    with bit 0 corresponding to the first item in the group and bit 7 to    */
+/*    the eighth item in the group.                                           */
+/*  * The second control byte corresponds to the second 8 items in the group  */
+/*    with bit 0 corresponding to the ninth item in the group and bit 7 to    */
+/*    the sixteenth item in the group.                                        */
+/*  * A zero bit in a control word means that the corresponding item is a     */
+/*    literal item. A one bit corresponds to a copy item.                     */
+/*  * A literal item consists of a single byte which represents itself.       */
+/*  * A copy item consists of two bytes that represent from 3 to 18 bytes.    */
+/*  * The first  byte in a copy item will be denoted C1.                      */
+/*  * The second byte in a copy item will be denoted C2.                      */
+/*  * Bits will be selected using square brackets.                            */
+/*    For example: C1[0..3] is the low nibble of the first control byte.      */
+/*    of copy item C1.                                                        */
+/*  * The LENGTH of a copy item is defined to be C1[0..3]+3 which is a number */
+/*    in the range [3,18].                                                    */
+/*  * The INDEX of a copy item is defined to be C1[4..7]*256+C2[0..8] which   */
+/*    is a number in the range [0,4095].                                      */
+/*  * A copy item represents the sequence of bytes                            */
+/*       text[POS-OFFSET..POS-OFFSET+LENGTH-1] where                          */
+/*          text   is the entire text of the uncompressed string.             */
+/*          POS    is the index in the text of the character following the    */
+/*                   string represented by all the items preceeding the item  */
+/*                   being defined.                                           */
+/*          OFFSET is obtained from INDEX by looking up the hash table.       */
+/*                                                                            */
+/******************************************************************************/
+
+/* When I first started to get concerned about the portability of my C code,  */
+/* I switched over to using only macro defined types UBYTE, UWORD, ULONG and  */
+/* one or two others. While, these are useful for most purposes, they impair  */
+/* efficiency as, if I have a variable whose range will be [0,1000], I will   */
+/* declare it as a UWORD. This will translate into (say) "short int" and      */
+/* hence may be less efficient than just an "int" which represents the        */
+/* natural size of the machine. Before releasing LZRW3-A, I realized this     */
+/* mistake. Unfortunately, I can't access the ftp archive with my portability */
+/* header in it in time for this algorithm's release and so I am including an */
+/* extra definition. The definition UCARD stands for an unsigned (cardinal)   */
+/* type that can hold values in the range [0,32767]. This is within the ANSI  */
+/* range of a standard int or unsigned. No assumption about overflow of this  */
+/* type is made in the code (i.e. all usages are within range and I do not    */
+/* use the value -1 to detect the end of loops.).                             */
+/* You can use either "unsigned" or just "int" here depending on which is     */
+/* more efficient in your environment (both the same probably).               */
+#define UCARD unsigned
+
+/* The following constant defines the maximum length of an uncompressed item. */
+/* This definition must not be changed; its value is hardwired into the code. */
+/* The longest number of bytes that can be spanned by a single item is 18     */
+/* for the longest copy item.                                                 */
+#define MAX_RAW_ITEM (18)
+
+/* The following constant defines the maximum length of a compressed group.   */
+/* This definition must not be changed; its value is hardwired into the code. */
+/* A compressed group consists of two control bytes followed by up to 16      */
+/* compressed items each of which can have a maximum length of two bytes.     */
+#define MAX_CMP_GROUP (2+16*2)
+
+/* This constant defines the number of pointers in the hash table. The number */
+/* of partitions multiplied by the number of pointers in each partition must  */
+/* multiply out to this value of 4096. In LZRW1, LZRW1-A, and LZRW2, this     */
+/* table length value can be changed. However, in LZRW3-A (and LZRW3), the    */
+/* table length cannot be changed because it is connected directly to the     */
+/* coding scheme which is hardwired (the table index of a single pointer is   */
+/* transmitted in the 12-bit index field). So don't change this constant!     */
+#define HASH_TABLE_LENGTH (4096)
+
+/* HERE IT IS: THE PLACE TO CHANGE THE HASH TABLE DEPTH!                      */
+/* The following definition is the log_2 of the depth of the hash table. This */
+/* constant can be in the range [0,1,2,3,...,12]. Increasing the depth        */
+/* increases compression at the expense of speed. However, you are not likely */
+/* to see much of a compression improvement (e.g. not more than 0.5%) above a */
+/* value of 6 and the algorithm will start to get very slow. See the table in */
+/* the earlier comments block for an idea of the trade-off involved.          */
+/* Note: The parentheses are to avoid macro substitution funnies.             */
+/* Note: The LZRW3-A default is a value of (3).                               */
+/* Note: If you end up choosing a value of 0, you should use LZRW3 instead.   */
+/* Note: Changing the value of HASH_TABLE_DEPTH_BITS is the ONLY thing you    */
+/* have to do to change the depth, so go ahead and recompile now!             */
+/* Note: I have tested LZRW3-A for DEPTH_BITS=0,1,2,3,4 and a few other       */
+/* values. However, I have not tested it for 12 as I can't wait that long!    */
+#define HASH_TABLE_DEPTH_BITS (3)      /* Must be in range [0,12].            */
+
+/* The following definitions are all self-explanatory and follow from the     */
+/* definition of HASH_TABLE_DEPTH_BITS and the hardwired requirement that the */
+/* hash table contain exactly 4096 pointers.                                  */
+#define PARTITION_LENGTH_BITS (12-HASH_TABLE_DEPTH_BITS)
+#define PARTITION_LENGTH      (1<<PARTITION_LENGTH_BITS)
+#define HASH_TABLE_DEPTH      (1<<HASH_TABLE_DEPTH_BITS )
+#define HASH_MASK             (PARTITION_LENGTH-1)
+#define DEPTH_MASK            (HASH_TABLE_DEPTH-1)
+
+/* LZRW3-A, unlike LZRW1(-A), must initialize its hash table so as to enable  */
+/* the compressor and decompressor to stay in step maintaining identical hash */
+/* tables. In an early version of LZRW3, the tables were simply               */
+/* initialized to zero and a check for zero was included just before the      */
+/* matching code. However, this test costs time. A better solution is to      */
+/* initialize all the entries in the hash table to point to a constant        */
+/* string. The decompressor does the same. This solution requires no extra    */
+/* test. The contents of the string do not matter so long as the string is    */
+/* the same for the compressor and decompressor and contains at least         */
+/* MAX_RAW_ITEM bytes. I chose consecutive decimal digits because they do not */
+/* have white space problems (e.g. there is no chance that the compiler will  */
+/* replace more than one space by a TAB) and because they make the length of  */
+/* the string obvious by inspection.                                          */
+#define START_STRING_18 ((UBYTE *) "123456789012345678")
+/* fixme: I (pjm) am not at all sure that the above string cannot be written to. */
+
+/* The following macro accepts a pointer PTR to three consecutive bytes in    */
+/* memory and hashes them into an integer that is a hash table index that     */
+/* points to the zeroth (first) element of a partition. Thus, the hash        */
+/* function really hashes to a partition number but, for convenience,         */
+/* multiplies it up to yield a hash table index. From all this, we see that   */
+/* the resultant number is in the range [0,HASH_TABLE_LENGTH-1] and is a      */
+/* multiple of HASH_TABLE_DEPTH.                                              */
+/* A macro is used, because in LZRW3-A we have to hash more than once.        */
+#if 0
+#define HASH(PTR) \
+ ( \
+     (((40543*(((*(PTR))<<8)^((*((PTR)+1))<<4)^(*((PTR)+2))))>>4) & HASH_MASK) \
+  << HASH_TABLE_DEPTH_BITS \
+ )
+
+#else
+#define HASH(PTR) \
+ ( \
+     ( ((((*(PTR)<<3)^(*((PTR)+1)))<<3)^(*((PTR)+2))) & HASH_MASK) \
+  << HASH_TABLE_DEPTH_BITS \
+ )
+#endif
+
+/* Another operation that is performed more than once is the updating of the  */
+/* hash table. Here two macros are defined to simplify update operations.     */
+/* Updating consists of identifying and overwriting a pointer in a partition  */
+/* with a newer pointer and then updating the global cycle value.             */
+/* These macros accept the new pointer (NEWPTR) and either a pointer to       */
+/* (P_BASE) or the index of (I_BASE) the zeroth (first, or base) pointer in   */
+/* the partition that is to be updated. The macros use the 'cycle' variable   */
+/* to locate and overwrite a pointer and then update the cycle value.         */
+/* Note: Hardcoding 'cycle' in this macro is naughty (it should really be a   */
+/* macro parameter), but I have done so because it neatens up the code.       */
+#define UPDATE_P(P_BASE,NEWPTR) \
+{(P_BASE)[cycle++]=(NEWPTR); cycle&=DEPTH_MASK;}
+
+#define UPDATE_I(I_BASE,NEWPTR) \
+{hash[(I_BASE)+cycle++]=(NEWPTR); cycle&=DEPTH_MASK;}
+
+/* This constant supplies a legal (in-range) hash table index for use when    */
+/* a legal-but-don't-care index is required.                                  */
+#define ANY_HASH_INDEX (0)
+
+/******************************************************************************/
+#if 0
+void *ext2_lzrw3a_htab;
+#endif
+
+EXPORT int ext2_LZRW3A_compress
+           (p_src_first,p_dst_first,heap,src_len,p_dst_len)
+/* Input  : Specify input block using p_src_first and src_len.                */
+/* Input  : Point p_dst_first to the start of the output zone (OZ).           */
+/* Input  : Point p_dst_len to a ULONG to receive the output length.          */
+/* Input  : Input block and output zone must not overlap.                     */
+/* Output : Length of output block written to *p_dst_len.                     */
+/* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. May   */
+/* Output : write in OZ=Mem[p_dst_first..p_dst_first+src_len+MAX_CMP_GROUP-1].*/
+/* Output : Upon completion *p_dst_len contains final size or 0               */
+UBYTE *p_src_first;
+UBYTE *p_dst_first;
+void *heap;
+int  src_len;
+int p_dst_len;
+{
+  /* p_src and p_dst step through the source and destination blocks.           */
+  UBYTE const *p_src = p_src_first;
+  UBYTE *p_dst = p_dst_first;
+
+  /* The following variables are never modified and are used in the            */
+  /* calculations that determine when the main loop terminates.                */
+  UBYTE const * const p_src_post  = p_src_first + src_len;
+  UBYTE       * const p_dst_post  = p_dst_first + p_dst_len;
+  UBYTE const * const p_src_max1  = p_src_first + src_len - MAX_RAW_ITEM;
+  UBYTE const * const p_src_max16 = p_src_first + src_len - (MAX_RAW_ITEM * 16);
+
+  /* The variables 'p_control' and 'control' are used to buffer control bits.  */
+  /* Before each group is processed, the next two bytes of the output block    */
+  /* are set aside for the control word for the group about to be processed.   */
+  /* 'p_control' is set to point to the first byte of that word. Meanwhile,    */
+  /* 'control' buffers the control bits being generated during the processing  */
+  /* of the group. Instead of having a counter to keep track of how many items */
+  /* have been processed (=the number of bits in the control word), at the     */
+  /* start of each group, the top word of 'control' is filled with 1 bits.     */
+  /* As 'control' is shifted for each item, the 1 bits in the top word are     */
+  /* absorbed or destroyed. When they all run out (i.e. when the top word is   */
+  /* all zero bits, we know that we are at the end of a group.                 */
+  #define TOPWORD 0xFFFF0000
+  UBYTE *p_control;
+  ULONG control=TOPWORD;
+
+  /* The variable 'hash' always points to the first element of the hash table. */
+#if 0
+  UBYTE **hash= (UBYTE **) ext2_lzrw3a_htab;
+#else
+  UBYTE **hash= (UBYTE **) heap;
+#endif
+
+  /* The following two variables represent the literal buffer. p_h1 points to  */
+  /* the partition (i.e. the zero'th (first) element of the partition)         */
+  /* corresponding to the youngest literal. p_h2 points to the partition       */
+  /* corresponding to the second youngest literal.                             */
+  /* The value zero denotes an "empty" buffer value with p_h1=0 => p_h2=0.     */
+  UBYTE **p_h1=0;
+  UBYTE **p_h2=0;
+
+  /* The following variable holds the current 'cycle' value. This value cycles */
+  /* through the range [0,HASH_TABLE_DEPTH-1], being incremented every time    */
+  /* the hash table is updated. The value gives the within-partition number of */
+  /* the next pointer to be overwritten. The decompressor maintains a cycle    */
+  /* value in synchrony.                                                       */
+  UCARD cycle=0;
+
+  /* Reserve the first two bytes of output as the control word for the first group. */
+  /* Note: This is undone at the end if the input block is empty.              */
+  p_control = p_dst;
+  p_dst += 2;
+
+  /* Initialize all elements of the hash table to point to a constant string.  */
+  /* Use of an unrolled loop speeds this up considerably.                      */
+  /* These variables should really be declared "register", but I am worried    */
+  /* about the possibility that extra register declarations will tempt stupid  */
+  /* compilers to allocate all registers before they get to the innermostloop. */
+  {
+   UCARD i;
+   UBYTE **p_h = hash;
+   #define ZH *p_h++=START_STRING_18
+   for (i = 256; i--;)     /* 256=HASH_TABLE_LENGTH/16. */
+     {ZH;ZH;ZH;ZH;
+      ZH;ZH;ZH;ZH;
+      ZH;ZH;ZH;ZH;
+      ZH;ZH;ZH;ZH;}
+   #undef ZH
+  }
+
+  /* The main loop processes either 1 or 16 items per iteration. As its        */
+  /* termination logic is complicated, I have opted for an infinite loop       */
+  /* structure containing 'break' and 'goto' statements.                       */
+  while (TRUE)
+    {/* Begin main processing loop. */
+
+     /* Note: All the variables here except unroll should be defined within    */
+     /*       the inner loop. Unfortunately the loop hasn't got a block.       */
+      UBYTE const *p_ziv = (void *) 0; /* Points to first byte of current Ziv.       */
+      UCARD unroll;              /* Loop counter for unrolled inner loop.      */
+      UCARD index;               /* Index of current partition.                */
+      UBYTE **p_h0;              /* Pointer to current partition.              */
+      register UCARD d;          /* Depth looping variable.                    */
+      register UCARD bestlen;    /* Holds the best length seen so far.         */
+      register UCARD bestpos;    /* Holds number of best pointer seen so far.  */
+
+     /* Test for overrun and jump to overrun code if necessary.                */
+     if (p_dst > p_dst_post)	/* tbi: This looks wrong.  Why not '>=' ? */
+	goto overrun;
+
+     /* The following cascade of if statements efficiently catches and deals   */
+     /* with varying degrees of closeness to the end of the input block.       */
+     /* When we get very close to the end, we stop updating the table and      */
+     /* code the remaining bytes as literals. This makes the code simpler.     */
+     unroll=16;
+     if (p_src>p_src_max16)
+       {
+	unroll=1;
+	if (p_src>p_src_max1)
+	  {
+	   if (p_src==p_src_post)
+	      break;
+	   else
+	      {p_h0=&hash[ANY_HASH_INDEX]; /* Avoid undefined pointer. */
+	       goto literal;}
+	  }
+       }
+
+     /* This inner unrolled loop processes 'unroll' (whose value is either 1   */
+     /* or 16) items. I have chosen to implement this loop with labels and     */
+     /* gotos to heighten the ease with which the loop may be implemented with */
+     /* a single decrement and branch instruction in assembly language and     */
+     /* also because the labels act as highly readable place markers.          */
+     /* (Also because we jump into the loop for endgame literals (see above)). */
+
+     begin_unrolled_loop:
+
+	p_ziv=p_src;
+
+	/* To process the next phrase, we hash the next three bytes to obtain  */
+	/* an index to the zeroth (first) pointer in a target partition. We    */
+	/* get the pointer.                                                    */
+	index=HASH(p_src);
+	p_h0=&hash[index];
+
+	/* This next part runs through the pointers in the partition matching  */
+	/* the bytes they point to in the Lempel with the bytes in the Ziv.    */
+	/* The length (bestlen) and within-partition pointer number (bestpos)  */
+	/* of the longest match so far is maintained and is the output of this */
+	/* segment of code. The s[bestlen]==... is an optimization only.       */
+	bestlen=0;
+	bestpos=0;
+	for (d=0;d<HASH_TABLE_DEPTH;d++)
+	  {
+	   register UBYTE const *s=p_src;
+	   register UBYTE *p=p_h0[d];
+	   register UCARD len;
+	   if (s[bestlen] == p[bestlen])
+	     {
+	      #define PS *p++!=*s++
+	      (void) (PS || PS || PS || PS || PS || PS || PS || PS || PS ||
+		      PS || PS || PS || PS || PS || PS || PS || PS || PS || s++);
+	      len = s - p_src - 1;
+	      if (len>bestlen)
+		{
+		 bestpos=d;
+		 bestlen=len;
+		}
+	     }
+	  }
+
+	/* The length of the longest match determines whether we code a */
+	/* literal item or a copy item.                                 */
+
+	if (bestlen<3)
+	  {
+	   /* Literal. */
+
+	   /* Code the literal byte as itself and a zero control bit.          */
+	   literal: *p_dst++=*p_src++; control&=0xFFFEFFFF;
+
+	   /* We have just coded a literal. If we had two pending ones, that   */
+	   /* makes three and we can update the hash table.                    */
+	   if (p_h2!=0)
+	      {UPDATE_P(p_h2, p_ziv - 2);}
+
+	   /* In any case, rotate the hash table pointers for next time. */
+	   p_h2=p_h1;
+	   p_h1=p_h0;
+
+	  }
+	else
+	  {
+	   /* Copy */
+
+	   /* To code a copy item, we construct a hash table index of the      */
+	   /* winning pointer (index+=bestpos) and code it and the best length */
+	   /* into a 2 byte code word. Bump up p_src.                          */
+	   index+=bestpos;
+	   *p_dst++=((index&0xF00)>>4)|(bestlen-3);
+	   *p_dst++=index&0xFF;
+	   p_src+=bestlen;
+
+	   /* As we have just coded three bytes, we are now in a position to   */
+	   /* update the hash table with the literal bytes that were pending   */
+	   /* upon the arrival of extra context bytes.                         */
+	   if (p_h1!=0)
+	     {
+	      if (p_h2!=0)
+		{UPDATE_P(p_h2,p_ziv-2); p_h2=0;}
+	      UPDATE_P(p_h1,p_ziv-1); p_h1=0;
+	     }
+
+	   /* In any case, we can update the hash table based on the current   */
+	   /* position as we just coded at least three bytes in a copy items.  */
+	   UPDATE_P(p_h0,p_ziv);
+	  }
+	control>>=1;
+
+	/* This loop is all set up for a decrement and jump instruction! */
+     if (--unroll) goto begin_unrolled_loop;
+
+     /* At this point it will nearly always be the end of a group in which     */
+     /* case, we have to do some control-word processing. However, near the    */
+     /* end of the input block, the inner unrolled loop is only executed once. */
+     /* This necessitates the 'if' test.                                       */
+     if ((control&TOPWORD)==0)
+       {
+	/* Write the control word to the place we saved for it in the output. */
+	*p_control++=  control     &0xFF;
+	*p_control  = (control>>8) &0xFF;
+
+	/* Reserve the next word in the output block for the control word */
+	/* for the group about to be processed.                           */
+	p_control=p_dst; p_dst+=2;
+
+	/* Reset the control bits buffer. */
+	control=TOPWORD;
+       }
+
+    } /* End main processing loop. */
+
+  /* After the main processing loop has executed, all the input bytes have     */
+  /* been processed. However, the control word has still to be written to the  */
+  /* word reserved for it in the output at the start of the most recent group. */
+  /* Before writing, the control word has to be shifted so that all the bits   */
+  /* are in the right place. The "empty" bit positions are filled with 1s      */
+  /* which partially fill the top word.                                        */
+  while(control&TOPWORD) control>>=1;
+  *p_control++= control     &0xFF;
+  *p_control++=(control>>8) &0xFF;
+
+  /* If the last group contained no items, delete the control word too.        */
+  if (p_control==p_dst) p_dst-=2;
+
+  /* Write the length of the output block to the dst_len parameter and return. */
+  return p_dst - p_dst_first;
+
+  /* Jump here as soon as an overrun is detected. An overrun is defined to     */
+  /* have occurred if p_dst>p_dst_first+*p_dst_len as set by caller. */
+  /* The algorithm checks for overruns at least at the end of each group       */
+  /* which means that the maximum overrun is MAX_CMP_GROUP bytes.              */
+  /* Once an overrun occurs, the only thing to do is to return an error        */
+  overrun:
+  return 0;
+}
+
+/******************************************************************************/
+
+#ifndef LZRW3A_ASM
+EXPORT int ext2_LZRW3A_decompress
+           (p_src_first, p_dst, heap, src_len, dst_len)
+/* Input  : Specify input block using p_src_first.                */
+/* Input  : Point p_dst to the start of the output zone.                */
+/* Input  : dst_len contains output length */
+/* Input  : Input block and output zone must not overlap. User knows          */
+/* Input  : upperbound on output block length from earlier compression.       */
+/* Input  : In any case, maximum expansion possible is nine times.            */
+/* Input  : src_len contains max input length */
+/* Output : Writes only  in Mem[p_dst..p_dst+dst_len-1].       */
+UBYTE *p_src_first;
+UBYTE *p_dst;
+void *heap;
+int src_len;
+int dst_len;
+{
+ UBYTE *p_dst_first = p_dst;
+
+ /* Byte pointers scan through the input and output blocks.   */
+ register UBYTE *p_src = p_src_first;
+
+ /* The following two variables are never modified and are used to control    */
+ /* the main loop.                                                            */
+ UBYTE * const p_dst_post  = p_dst+dst_len;
+ UBYTE * const p_dst_max16 = p_dst+dst_len-MAX_RAW_ITEM*16;
+
+ /* The hash table is the only resident of the working memory. The hash table */
+ /* contains HASH_TABLE_LENGTH=4096 pointers to positions in the history. To  */
+ /* keep Macintoshes happy, it is longword aligned.                           */
+#if 0
+ UBYTE **hash = (UBYTE **) ext2_lzrw3a_htab;
+#else
+ UBYTE **hash = (UBYTE **) heap;
+#endif
+
+ /* The variable 'control' is used to buffer the control bits which appear in */
+ /* groups of 16 bits (control words) at the start of each compressed group.  */
+ /* When each group is read, bit 16 of the register is set to one. Whenever   */
+ /* a new bit is needed, the register is shifted right. When the value of the */
+ /* register becomes 1, we know that we have reached the end of a group.      */
+ /* Initializing the register to 1 thus instructs the code to follow that it  */
+ /* should read a new control word immediately.                               */
+ register ULONG control=1;
+
+ /* The value of 'literals' is always in the range 0..3. It is the number of  */
+ /* consecutive literal items just seen. We have to record this number so as  */
+ /* to know when to update the hash table. When literals gets to 3, there     */
+ /* have been three consecutive literals and we can update at the position of */
+ /* the oldest of the three.                                                  */
+ register UCARD literals=0;
+
+ /* The following variable holds the current 'cycle' value. This value cycles */
+ /* through the range [0,HASH_TABLE_DEPTH-1], being incremented every time    */
+ /* the hash table is updated. The value give the within-partition number of  */
+ /* the next pointer to be overwritten. The compressor maintains a cycle      */
+ /* value in synchrony.                                                       */
+ UCARD cycle=0;
+
+ /* Initialize all elements of the hash table to point to a constant string.  */
+ /* Use of an unrolled loop speeds this up considerably.                      */
+ /* The comment about register declarations above similar code in the         */
+ /* compressor applies here too.                                              */
+ {
+  UCARD i; 
+  UBYTE **p_h = hash;
+
+  #define ZJ *p_h++=START_STRING_18
+  for (i=0;i<256;i++)     /* 256=HASH_TABLE_LENGTH/16. */
+    {ZJ;ZJ;ZJ;ZJ;
+     ZJ;ZJ;ZJ;ZJ;
+     ZJ;ZJ;ZJ;ZJ;
+     ZJ;ZJ;ZJ;ZJ;}
+  #undef ZJ
+ }
+
+ /* The outer loop processes either 1 or 16 items per iteration depending on  */
+ /* how close p_dst is to the end of the output block.                         */
+ while (p_dst < p_dst_post && src_len >= 0)
+   {/* Start of outer loop */
+
+    register UCARD unroll;   /* Counts unrolled loop executions.              */
+
+    /* When 'control' has the value 1, it means that the 16 buffered control  */
+    /* bits that were read in at the start of the current group have all been */
+    /* shifted out and that all that is left is the 1 bit that was injected   */
+    /* into bit 16 at the start of the current group. When we reach the end   */
+    /* of a group, we have to load a new control word and inject a new 1 bit. */
+    if (control==1)
+      {
+       control=0x10000|*p_src++;
+       control|=(*p_src++)<<8;
+       src_len -= 2;
+      }
+
+    /* If it is possible that we are within 16 groups from the end of the     */
+    /* input, execute the unrolled loop only once, else process a whole group */
+    /* of 16 items by looping 16 times.                                       */
+    unroll= p_dst<=p_dst_max16 ? 16 : 1;
+
+    /* This inner loop processes one phrase (item) per iteration. */
+    while (unroll--)
+      { /* Begin unrolled inner loop. */
+
+       /* Process a literal or copy item depending on the next control bit. */
+       if (control&1)
+         {
+          /* Copy item. */
+
+          register UBYTE *p;           /* Points to place from which to copy. */
+          register UCARD lenmt;        /* Length of copy item minus three.    */
+          register UBYTE *p_ziv = p_dst; /* Pointer to start of current Ziv.    */
+          register UCARD index;        /* Index of hash table copy pointer.   */
+
+          /* Read and dismantle the copy word. Work out from where to copy.   */
+          lenmt=*p_src++;
+          index=((lenmt&0xF0)<<4)|*p_src++;
+	  src_len -= 2;
+          p=hash[index];
+          lenmt&=0xF;
+
+          /* Now perform the copy using a half unrolled loop. */
+          *p_dst++=*p++;
+          *p_dst++=*p++;
+          *p_dst++=*p++;
+          while (lenmt--)
+             *p_dst++=*p++;
+
+          /* Because we have just received 3 or more bytes in a copy item     */
+          /* (whose bytes we have just installed in the output), we are now   */
+          /* in a position to flush all the pending literal hashings that had */
+          /* been postponed for lack of bytes.                                */
+          if (literals>0)
+            {
+             register UBYTE *r = p_ziv - literals;;
+             UPDATE_I(HASH(r),r);
+             if (literals==2)
+                {r++; UPDATE_I(HASH(r),r);}
+             literals=0;
+            }
+
+          /* In any case, we can immediately update the hash table with the   */
+          /* current position. We don't need to do a HASH(...) to work out    */
+          /* where to put the pointer, as the compressor just told us!!!      */
+          UPDATE_I(index&(~DEPTH_MASK),p_ziv);
+         }
+       else
+         {
+          /* Literal item. */
+
+          /* Copy over the literal byte. */
+          *p_dst++=*p_src++;
+	  src_len--;
+
+          /* If we now have three literals waiting to be hashed into the hash */
+          /* table, we can do one of them now (because there are three).      */
+          if (++literals == 3)
+             {register UBYTE *p=p_dst-3;
+              UPDATE_I(HASH(p),p); literals=2;}
+         }
+
+       /* Shift the control buffer so the next control bit is in bit 0. */
+       control>>=1;
+
+      } /* End unrolled inner loop. */
+
+   } /* End of outer loop */
+
+#if 0
+   if(src_len < 0) return 0;
+   return (p_src-p_src_first);
+#else
+   return p_dst - p_dst_first;
+#endif
+}
+#endif
+
+/******************************************************************************/
+/*                              End of LZRW3-A.C                              */
+/******************************************************************************/
diff -urN linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/rlzrw3a.S linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/rlzrw3a.S
--- linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/rlzrw3a.S	
+++ linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/rlzrw3a.S	
@@ -0,0 +1,350 @@
+/*	
+ *	LZRW3A decompression written in assembly.
+ *
+ *	Written by Antoine de Maricourt (dumesnil@etca.fr)
+ *	                17 Mar 1995
+ *
+ *	NOTE: The use of this algorithm may be restricted by some
+ *	      patent. Please check if this is the case in your 
+ *	      country before using it. As far as I know LZRW3A is
+ *	      patended in the USA.
+ *
+ *	In order to be used, the compression routine (file lrzw3a.c)
+ *	must be updated to use the following hash function :
+ *
+ *	#define HASH(PTR) (\
+ *	  (((((*(PTR)<<3)^(*((PTR)+1)))<<3)^(*((PTR)+2)))&HASH_MASK)\
+ *	  << HASH_TABLE_DEPTH_BITS)
+ *
+ *	The hash table depth is hardwired to 8.
+ *
+ *	Interface :
+ *	-----------
+ *
+ *	   int rLZRW3A (char *ib, char *ob, int il, int ol);
+ *
+ *              ib = input buffer (compressed data)
+ *              ob = output buffer (uncompressed data)
+ *		il = number of bytes in the input buffer
+ *		ol = number of bytes to be uncompressed
+ *
+ *	The routine may write more (i.e., ???) bytes than requested
+ *	The returned value is the number of bytes written to output
+ *	buffer.
+ *
+ *	The algorithm and the coding method have been taken from
+ *	file lzrw3a.c originaly written by Ross Williams.
+ *
+ *	-----
+ *	Copyright (c) 1995 Antoine de Maricourt. Redistribution
+ *	of this file is permitted under the GNU Public License.
+ */
+
+#include <linux/linkage.h>
+
+#define A0	32
+#define A1	36
+#if 0
+#define A2	40
+#define A3	44
+#else
+#define A2	44
+#define A3	48
+#endif
+#define L0
+
+#if 0
+#define HTAB	SYMBOL_NAME(ext2_lzrw3a_htab)
+#else
+#define HTAB	40(%esp)
+#endif
+
+#if 0
+.comm HTAB, 4				# hash table
+#endif
+
+LC0:	.ascii "123456789012345678\0"
+
+	/* for i386 */
+#define bswap rol $16,
+
+/*
+ *	Initialize the hash table. Some might want to do
+ *	it with an unrolled loop. It would not be faster
+ *	on my system.
+ */
+
+#define InitTable()			\
+	movl HTAB, %edi;		\
+	movl $4096, %ecx;		\
+	movl $LC0, %eax;		\
+	rep; stosl
+
+#define CopyOneByte			\
+	movb (%esi), %dh;		\
+	movb %dh, 3(%edi)
+
+#define CopyByte(o1,o2)			\
+	movb o1(%esi), %dh;		\
+	movb %dh, o2(%edi)
+
+/*
+ *	Update the hash key with the given byte. Note that
+ *	the key is shifted after the xor, and not before.
+ *	This will make it easier to add the cycle count.
+ */
+
+#define UpdateHashKey			\
+	bswap %ebx;			\
+	xorb %dh, %bl;			\
+	andw $0x1ff, %bx;		\
+	shlw $3, %bx;			\
+	bswap %ebx
+
+/*
+ *	Update the hashtable with the current position. The
+ *	cycle count is incremented.
+ */
+
+#define UpdateHashTable			\
+	andl $7, %edx;			\
+	bswap %ebx;			\
+	addw %bx, %dx;			\
+	movl %edi, (%ebp,%edx,4);	\
+	incb %dl;			\
+	bswap %ebx
+
+/*
+ *	Copy a byte from the input buffer to the output
+ *	and remember the value. This will be used instead
+ *	of movsb when we need the value to update the hash
+ *	key.
+ */
+
+#define CopyLiteral			\
+	CopyOneByte;			\
+	incl %esi;			\
+	incl %edi;			\
+	UpdateHashKey
+
+	.text
+
+ENTRY(ext2_LZRW3A_decompress)
+	pushl %ebp
+	pushl %edi
+	pushl %esi
+	pushl %ebx			# be safe
+	pushl %ecx
+	pushl %edx
+	subl $4, %esp
+
+	InitTable ()
+
+	movl A0(%esp), %esi		# esi = input buffer
+	movl A1(%esp), %edi		# edi = output buffer
+	subl $3, %edi
+	addl %esi, A2(%esp)		# input limit
+	movl A3(%esp), %eax
+	addl %edi, %eax	
+	movl %eax, A3(%esp)		# output limit
+	subl $288, %eax
+	movl %eax, L0(%esp)
+
+	/*
+	 *	eax = control word
+	 *	ebx = hash key (high) + literal count (bl) + loop count (bh)
+	 *	ecx = tmp data
+	 *	edx = cycle count (dl) + tmp data (dh)
+	 *	esi = source pointer
+	 *	edi = destination pointer
+	 *	ebp = hash table address
+	 */
+
+	xorl %eax, %eax			# we need a control word
+	movl %eax, %ebx			# hash key is 0
+	movl %eax, %edx			# cycle is 0
+	movl HTAB, %ebp			# get pointer to hash table
+	movb $3, %bl	
+
+	/*
+	 *	Load a fresh control word if needed
+	 */
+
+L10:	cmpl %esi, A2(%esp)		# check for input overflow
+	jna L40
+
+	cmp $1, %eax
+	ja L11
+	movb (%esi), %al
+	movb 1(%esi), %ah
+	lea 2(%esi), %esi
+	orl $0x10000, %eax
+
+L11:	movb $16, %bh
+	cmpl L0(%esp), %edi
+	jbe L12
+	movb $1, %bh
+
+L12:	shrl $1, %eax
+	jc L20				# test control bit
+
+	/*
+	 *	This is a literal
+	 */
+
+	CopyLiteral
+
+	decb %bl
+	jne L13
+	UpdateHashTable
+	incb %bl
+
+L13:	decb %bh			# loop 
+	jne L12
+
+	cmpl A3(%esp), %edi		# check for output overflow
+	jb L10				# and continue
+	jmp L40
+
+	/*
+	 *	This is a copy item
+	 */
+
+
+	ALIGN
+L20:
+	/*
+	 *	Load the index into ecx, and the len into dh
+	 */
+
+	xorl %ecx, %ecx			# clear high part of ecx
+	movb (%esi), %ch		# load 4 high bits of index
+	movb 1(%esi), %cl		# load 8 low bits of index
+	shrb $4, %ch			# adjust index
+
+	movl (%ebp,%ecx,4), %ecx	# get pointer to item
+	xchg %ecx, %esi			# put it into esi, save esi into ecx
+
+	/*
+	 *	Copy first byte
+         */
+
+	CopyLiteral
+	decb %bl
+	jne L22
+	UpdateHashTable
+	incb %bl
+
+	/*
+	 *	Copy second byte
+         */
+
+L22:	CopyLiteral
+	decb %bl
+	jne L23
+	UpdateHashTable
+
+	/*
+	 *	Copy third byte
+	 */
+
+L23:	CopyLiteral
+	UpdateHashTable			# do not need to test bl.
+	movb $3, %bl
+
+	/*
+	 *	Copy the remaining bytes
+	 */
+	
+	testb $1, (%ecx)
+	je L24
+	CopyOneByte
+	incl %esi
+	incl %edi
+
+L24:	testb $2, (%ecx)
+	je L25
+
+	CopyByte (0, 3)
+	CopyByte (1, 4)
+
+	lea 2(%esi), %esi
+	lea 2(%edi), %edi
+
+L25:	cmp %esi, %edi
+	ja L30
+
+	testb $4, (%ecx)
+	je L26
+
+	CopyByte (0, 3)
+	CopyByte (1, 4)
+	CopyByte (2, 5)
+	CopyByte (3, 6)
+
+	lea 4(%esi), %esi
+	lea 4(%edi), %edi
+
+L26:	testb $8, (%ecx)
+	je L27
+
+	CopyByte (0, 3)
+	CopyByte (1, 4)
+	CopyByte (2, 5)
+	CopyByte (3, 6)
+	CopyByte (4, 7)
+	CopyByte (5, 8)
+	CopyByte (6, 9)
+	CopyByte (7, 10)
+
+	lea 8(%esi), %esi
+	lea 8(%edi), %edi
+
+L27:	lea 2(%ecx), %esi		# restore input pointer
+
+	decb %bh			# loop 
+	jne L12
+
+	cmpl A3(%esp), %edi		# check for output overflow
+	jb L10				# and continue
+	jmp L40
+
+	/*
+	 *	Copy the remaining bytes, but using movsl
+	 *	when we know the strings does not overlap.
+	 */
+	
+	ALIGN
+
+L30:	lea 3(%edi), %edi
+	testb $4, (%ecx)
+	je L31
+	movsl
+L31:	testb $8, (%ecx)
+	je L32
+	movsl
+	movsl
+
+L32:	lea -3(%edi), %edi
+	lea  2(%ecx), %esi		# restore input pointer
+	decb %bh			# loop 
+	jne L12
+
+	cmpl A3(%esp), %edi		# check for output overflow
+	jb L10				# and continue
+	
+	/*
+	 *	The end.
+	 */
+
+L40:	lea 3(%edi), %eax
+	subl A1(%esp),%eax
+
+	addl $4, %esp
+	popl %edx
+	popl %ecx
+	popl %ebx
+	popl %esi
+	popl %edi
+	popl %ebp
+	ret
diff -urN linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/wlzrw3a.c linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/wlzrw3a.c
--- linux-2.2.5-e2c0.4.30/fs/ext2/lzrw/wlzrw3a.c	
+++ linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/lzrw/wlzrw3a.c	
@@ -0,0 +1,784 @@
+/******************************************************************************/
+/*                                                                            */
+/*                                   LZRW3-A.C                                */
+/*                                                                            */
+/******************************************************************************/
+/*                                                                            */
+/* Author  : Ross Williams.                                                   */
+/* Date    : 15-Jul-1991.                                                     */
+/* Release : 1.                                                               */
+/*                                                                            */
+/******************************************************************************/
+/*                                                                            */
+/* This file contains an implementation of the LZRW3-A data compression       */
+/* algorithm in the C programming language.                                   */
+/*                                                                            */
+/* The LZRW3-A algorithm has the following features:                          */
+/*                                                                            */
+/*    1 Requires only 16K of memory (for both compression and decompression). */
+/*    2 The compressor   runs about two   times faster than Unix compress's.  */
+/*    3 The decompressor runs about three times faster than Unix compress's.  */
+/*    4 Yields a few percent better compression than Unix compress for        */
+/*      most files.                                                           */
+/*    5 Allows you to dial up extra compression at a speed cost in the        */
+/*      compressor. The speed of the decompressor is not affected.            */
+/*    6 Algorithm is deterministic.                                           */
+/*    8 This implementation in C is in the public domain.                     */
+/*                                                                            */
+/* (Timing tests for the speed comparison were performed on a Pyramid 9820.)  */
+/*                                                                            */
+/* LZRW3-A is LZRW3 with a deepened hash table. This simple change yields     */
+/* about a 6% (absolute) improvement in compression.                          */
+/*                                                                            */
+/* Here are the results of applying this code, compiled under THINK C 4.0     */
+/* and running on a Mac-SE (8MHz 68000), to the standard calgary corpus.      */
+/*                                                                            */
+/*     +----------------------------------------------------------------+     */
+/*     | DATA COMPRESSION TEST                                          |     */
+/*     | =====================                                          |     */
+/*     | Time of run     : Mon 15-Jul-1991 05:29PM                      |     */
+/*     | Timing accuracy : One part in 100                              |     */
+/*     | Context length  : 262144 bytes (= 256.0000K)                   |     */
+/*     | Test suite      : Calgary Corpus Suite                         |     */
+/*     | Files in suite  : 14                                           |     */
+/*     | Algorithm       : LZRW3-A                                      |     */
+/*     | Note: All averages are calculated from the un-rounded values.  |     */
+/*     +----------------------------------------------------------------+     */
+/*     | File Name   Length  CxB  ComLen  %Remn  Bits  Com K/s  Dec K/s |     */
+/*     | ----------  ------  ---  ------  -----  ----  -------  ------- |     */
+/*     | rpus:Bib.D  111261    1   49044   44.1  3.53     8.47    31.19 |     */
+/*     | us:Book1.D  768771    3  420464   54.7  4.38     7.27    30.07 |     */
+/*     | us:Book2.D  610856    3  277955   45.5  3.64     8.51    33.40 |     */
+/*     | rpus:Geo.D  102400    1   84218   82.2  6.58     4.23    15.04 |     */
+/*     | pus:News.D  377109    2  192880   51.1  4.09     7.08    25.89 |     */
+/*     | pus:Obj1.D   21504    1   12651   58.8  4.71     5.23    17.44 |     */
+/*     | pus:Obj2.D  246814    1  108044   43.8  3.50     8.01    28.11 |     */
+/*     | s:Paper1.D   53161    1   24526   46.1  3.69     8.11    30.24 |     */
+/*     | s:Paper2.D   82199    1   39483   48.0  3.84     8.11    32.04 |     */
+/*     | rpus:Pic.D  513216    2  111622   21.7  1.74    10.64    49.31 |     */
+/*     | us:Progc.D   39611    1   17923   45.2  3.62     8.06    29.01 |     */
+/*     | us:Progl.D   71646    1   24362   34.0  2.72    10.74    39.51 |     */
+/*     | us:Progp.D   49379    1   16805   34.0  2.72    10.64    37.58 |     */
+/*     | us:Trans.D   93695    1   30296   32.3  2.59    11.02    38.06 |     */
+/*     +----------------------------------------------------------------+     */
+/*     | Average     224401    1  100733   45.8  3.67     8.29    31.21 |     */
+/*     +----------------------------------------------------------------+     */
+/*                                                                            */
+/******************************************************************************/
+
+#include "lzrw.h"
+/******************************************************************************/
+
+/* The following structure is returned by the "compress" function below when  */
+/* the user asks the function to return identifying information.              */
+/* The most important field in the record is the working memory field which   */
+/* tells the calling program how much working memory should be passed to      */
+/* "compress" when it is called to perform a compression or decompression.    */
+/* LZRW3-A uses the same amount of memory during compression and              */
+/* decompression. For more information on this structure see "lzrw.h".        */
+/* The alignment fudge below really only needs to be 4 (but I play it safe!). */
+/* The id looks non-random, but it really was generated by coin tossing!      */
+
+#define U(X)            ((ULONG) X)
+#define SIZE_P_BYTE     (U(sizeof(UBYTE *)))
+#define ALIGNMENT_FUDGE (U(16))
+#define MEM_REQ ( U(4096)*(SIZE_P_BYTE) + ALIGNMENT_FUDGE )
+
+/*static struct compress_identity identity =
+{
+ U(0x01B90B91),                            * Algorithm identification number. * 
+ MEM_REQ,                                  * Working memory (bytes) required. * 
+ "LZRW3-A",                                * Name of algorithm.               * 
+ "1.0",                                    * Version number of algorithm.     * 
+ "15-Jul-1990",                            * Date of algorithm.               * 
+ "Ross N. Williams",                       * Author of algorithm.             * 
+ "Renaissance Software",                   * Affiliation of author.           * 
+};*/
+
+/******************************************************************************/
+/*                                                                            */
+/* BRIEF DESCRIPTION OF THE LZRW3-A ALGORITHM                                 */
+/* ==========================================                                 */
+/* Note: Before attempting to understand this algorithm, you should first     */
+/* understand the LZRW3 algorithm from which this algorithm is derived.       */
+/*                                                                            */
+/* The LZRW3-A algorithm is identical to the LZRW3 algorithm except that the  */
+/* hash table has been "deepened". The LZRW3 algorithm has a hash table of    */
+/* 4096 pointers which point to strings in the buffer. LZRW3-A generalizes    */
+/* this to 4096/(2^n) partitions each of which contains (2^n) pointers.       */
+/* In LZRW3-A, the hash function hashes to a partition number.                */
+/*                                                                            */
+/* During the processing of each phrase, LZRW3 overwrites the pointer in the  */
+/* position selected by the hash function. LZRW3-A overwrites one of the      */
+/* pointers in the partition that was selected by the hash function.          */
+/*                                                                            */
+/* When searching for a match, LZRW3-A matches against all (2^n) strings      */
+/* pointed to by the pointers in the target partition.                        */
+/*                                                                            */
+/* Deep hash tables were used in early versions of LZRW1 in late 1989, but    */
+/* were discarded in an effort to increase speed (which was the primary       */
+/* requirement for LZRW1). They were revived for use in LZRW3-A in order to   */
+/* produce an algorithm with compression performance competitive with Unix    */
+/* compress.                                                                  */
+/*                                                                            */
+/* Until 14-Jul-1991, deep hash tables used in prototype LZRW* algorithms     */
+/* used a queue discipline within each partition. Upon the arrival of a new   */
+/* pointer, the pointers in the partition would be block copied back one      */
+/* position (with the oldest pointer being overwritten) and the new pointer   */
+/* being inserted in the space at the front (the youngest position).          */
+/* This meant that pointers to the (2^n) most recent phrases corresponding to */
+/* each hash was kept. The only flaw in this system was the time-consuming    */
+/* block copy operation which was cheap for shallow tables but expensive for  */
+/* deep tables.                                                               */
+/*                                                                            */
+/* The traditional solution to ring buffer block copy problems is to maintain */
+/* a cyclic counter which points to the "head" of the queue. However, this    */
+/* would have required one counter to be stored for each partition and would  */
+/* have been slightly messy. After some thought (on 14-Jul-1991) a better     */
+/* solution was found. Instead of maintaining a counter for each partition,   */
+/* LZRW3-A maintains a single counter for all partitions! This counter is     */
+/* maintained in both the compressor and decompressor and means that the      */
+/* algorithm (effectively) overwrites a RANDOM element of the partition to be */
+/* updated. The result was to increase the speed of the compressor and        */
+/* decompressor, to make the decompressor's speed independent from whatever   */
+/* depth was selected, and to impair compression by less than 1% absolute.    */
+/*                                                                            */
+/* Setting the depth is a speed/compression tradeoff. The table below gives   */
+/* the tradeoff observed for a typical 50K text file on a Mac-SE.             */
+/* Note: %Rem=Percentage Remaining (after compression).                       */
+/*                                                                            */
+/*      Depth    %Rem    CmpK/s  DecK/s                                       */
+/*          1    45.2    14.77   32.24                                        */
+/*          2    42.6    12.12   31.26                                        */
+/*          4    40.9    10.28   31.91                                        */
+/*          8    40.0     7.81   32.36                                        */
+/*         16    39.5     5.30   32.47                                        */
+/*         32    39.0     3.23   32.59                                        */
+/*                                                                            */
+/* I have chosen a depth of 8 as the "default" depth for LZRW3-A. If you use  */
+/* a depth different to this (e.g. 4), you should use the name LZRW3-A(4) to  */
+/* indicate that a different depth is being used. LZRW3-A(8) is an acceptable */
+/* longhand for LZRW3-A.                                                      */
+/*                                                                            */
+/* To change the depth, search for "HERE IT IS" in the rest of this file.     */
+/*                                                                            */
+/*                                  +---+                                     */
+/*                                  |___|4095                                 */
+/*                                  |===|                                     */
+/*              +---------------------*_|<---+   /----+---\                   */
+/*              |                   |___|    +---|Hash    |                   */
+/*              |    512 partitions |___|        |Function|                   */
+/*              |    of 8 pointers  |===|        \--------/                   */
+/*              |    each (or any   |___|0            ^                       */
+/*              |    a*b=4096)      +---+             |                       */
+/*              |                   Hash        +-----+                       */
+/*              |                   Table       |                             */
+/*              |                              ---                            */
+/*              v                              ^^^                            */
+/*      +-------------------------------------|----------------+              */
+/*      ||||||||||||||||||||||||||||||||||||||||||||||||||||||||              */
+/*      +-------------------------------------|----------------+              */
+/*      |                                     |1......18|      |              */
+/*      |<------- Lempel=History ------------>|<--Ziv-->|      |              */
+/*      |     (=bytes already processed)      |<-Still to go-->|              */
+/*      |<-------------------- INPUT BLOCK ------------------->|              */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+/*                                                                            */
+/*                     DEFINITION OF COMPRESSED FILE FORMAT                   */
+/*                     ====================================                   */
+/*    The file consists of zero  */
+/*    or more GROUPS, each of which represents one or more bytes.             */
+/*  * Each group consists of two bytes of CONTROL information followed by     */
+/*    sixteen ITEMs except for the last group which can contain from one      */
+/*    to sixteen items.                                                       */
+/*  * An item can be either a LITERAL item or a COPY item.                    */
+/*  * Each item corresponds to a bit in the control bytes.                    */
+/*  * The first control byte corresponds to the first 8 items in the group    */
+/*    with bit 0 corresponding to the first item in the group and bit 7 to    */
+/*    the eighth item in the group.                                           */
+/*  * The second control byte corresponds to the second 8 items in the group  */
+/*    with bit 0 corresponding to the ninth item in the group and bit 7 to    */
+/*    the sixteenth item in the group.                                        */
+/*  * A zero bit in a control word means that the corresponding item is a     */
+/*    literal item. A one bit corresponds to a copy item.                     */
+/*  * A literal item consists of a single byte which represents itself.       */
+/*  * A copy item consists of two bytes that represent from 3 to 18 bytes.    */
+/*  * The first  byte in a copy item will be denoted C1.                      */
+/*  * The second byte in a copy item will be denoted C2.                      */
+/*  * Bits will be selected using square brackets.                            */
+/*    For example: C1[0..3] is the low nibble of the first control byte.      */
+/*    of copy item C1.                                                        */
+/*  * The LENGTH of a copy item is defined to be C1[0..3]+3 which is a number */
+/*    in the range [3,18].                                                    */
+/*  * The INDEX of a copy item is defined to be C1[4..7]*256+C2[0..8] which   */
+/*    is a number in the range [0,4095].                                      */
+/*  * A copy item represents the sequence of bytes                            */
+/*       text[POS-OFFSET..POS-OFFSET+LENGTH-1] where                          */
+/*          text   is the entire text of the uncompressed string.             */
+/*          POS    is the index in the text of the character following the    */
+/*                   string represented by all the items preceeding the item  */
+/*                   being defined.                                           */
+/*          OFFSET is obtained from INDEX by looking up the hash table.       */
+/*                                                                            */
+/******************************************************************************/
+
+/* When I first started to get concerned about the portability of my C code,  */
+/* I switched over to using only macro defined types UBYTE, UWORD, ULONG and  */
+/* one or two others. While, these are useful for most purposes, they impair  */
+/* efficiency as, if I have a variable whose range will be [0,1000], I will   */
+/* declare it as a UWORD. This will translate into (say) "short int" and      */
+/* hence may be less efficient than just an "int" which represents the        */
+/* natural size of the machine. Before releasing LZRW3-A, I realized this     */
+/* mistake. Unfortunately, I can't access the ftp archive with my portability */
+/* header in it in time for this algorithm's release and so I am including an */
+/* extra definition. The definition UCARD stands for an unsigned (cardinal)   */
+/* type that can hold values in the range [0,32767]. This is within the ANSI  */
+/* range of a standard int or unsigned. No assumption about overflow of this  */
+/* type is made in the code (i.e. all usages are within range and I do not    */
+/* use the value -1 to detect the end of loops.).                             */
+/* You can use either "unsigned" or just "int" here depending on which is     */
+/* more efficient in your environment (both the same probably).               */
+#define UCARD unsigned
+
+/* The following constant defines the maximum length of an uncompressed item. */
+/* This definition must not be changed; its value is hardwired into the code. */
+/* The longest number of bytes that can be spanned by a single item is 18     */
+/* for the longest copy item.                                                 */
+#define MAX_RAW_ITEM (18)
+
+/* The following constant defines the maximum length of a compressed group.   */
+/* This definition must not be changed; its value is hardwired into the code. */
+/* A compressed group consists of two control bytes followed by up to 16      */
+/* compressed items each of which can have a maximum length of two bytes.     */
+#define MAX_CMP_GROUP (2+16*2)
+
+/* This constant defines the number of pointers in the hash table. The number */
+/* of partitions multiplied by the number of pointers in each partition must  */
+/* multiply out to this value of 4096. In LZRW1, LZRW1-A, and LZRW2, this     */
+/* table length value can be changed. However, in LZRW3-A (and LZRW3), the    */
+/* table length cannot be changed because it is connected directly to the     */
+/* coding scheme which is hardwired (the table index of a single pointer is   */
+/* transmitted in the 12-bit index field). So don't change this constant!     */
+#define HASH_TABLE_LENGTH (4096)
+
+/* HERE IT IS: THE PLACE TO CHANGE THE HASH TABLE DEPTH!                      */
+/* The following definition is the log_2 of the depth of the hash table. This */
+/* constant can be in the range [0,1,2,3,...,12]. Increasing the depth        */
+/* increases compression at the expense of speed. However, you are not likely */
+/* to see much of a compression improvement (e.g. not more than 0.5%) above a */
+/* value of 6 and the algorithm will start to get very slow. See the table in */
+/* the earlier comments block for an idea of the trade-off involved.          */
+/* Note: The parentheses are to avoid macro substitution funnies.             */
+/* Note: The LZRW3-A default is a value of (3).                               */
+/* Note: If you end up choosing a value of 0, you should use LZRW3 instead.   */
+/* Note: Changing the value of HASH_TABLE_DEPTH_BITS is the ONLY thing you    */
+/* have to do to change the depth, so go ahead and recompile now!             */
+/* Note: I have tested LZRW3-A for DEPTH_BITS=0,1,2,3,4 and a few other       */
+/* values. However, I have not tested it for 12 as I can't wait that long!    */
+#define HASH_TABLE_DEPTH_BITS (3)      /* Must be in range [0,12].            */
+
+/* The following definitions are all self-explanatory and follow from the     */
+/* definition of HASH_TABLE_DEPTH_BITS and the hardwired requirement that the */
+/* hash table contain exactly 4096 pointers.                                  */
+#define PARTITION_LENGTH_BITS (12-HASH_TABLE_DEPTH_BITS)
+#define PARTITION_LENGTH      (1<<PARTITION_LENGTH_BITS)
+#define HASH_TABLE_DEPTH      (1<<HASH_TABLE_DEPTH_BITS )
+#define HASH_MASK             (PARTITION_LENGTH-1)
+#define DEPTH_MASK            (HASH_TABLE_DEPTH-1)
+
+/* LZRW3-A, unlike LZRW1(-A), must initialize its hash table so as to enable  */
+/* the compressor and decompressor to stay in step maintaining identical hash */
+/* tables. In an early version of LZRW3, the tables were simply               */
+/* initialized to zero and a check for zero was included just before the      */
+/* matching code. However, this test costs time. A better solution is to      */
+/* initialize all the entries in the hash table to point to a constant        */
+/* string. The decompressor does the same. This solution requires no extra    */
+/* test. The contents of the string do not matter so long as the string is    */
+/* the same for the compressor and decompressor and contains at least         */
+/* MAX_RAW_ITEM bytes. I chose consecutive decimal digits because they do not */
+/* have white space problems (e.g. there is no chance that the compiler will  */
+/* replace more than one space by a TAB) and because they make the length of  */
+/* the string obvious by inspection.                                          */
+#define START_STRING_18 ((UBYTE *) "123456789012345678")
+
+/* The following macro accepts a pointer PTR to three consecutive bytes in    */
+/* memory and hashes them into an integer that is a hash table index that     */
+/* points to the zeroth (first) element of a partition. Thus, the hash        */
+/* function really hashes to a partition number but, for convenience,         */
+/* multiplies it up to yield a hash table index. From all this, we see that   */
+/* the resultant number is in the range [0,HASH_TABLE_LENGTH-1] and is a      */
+/* multiple of HASH_TABLE_DEPTH.                                              */
+/* A macro is used, because in LZRW3-A we have to hash more than once.        */
+#if 0
+#define HASH(PTR) \
+ ( \
+     (((40543*(((*(PTR))<<8)^((*((PTR)+1))<<4)^(*((PTR)+2))))>>4) & HASH_MASK) \
+  << HASH_TABLE_DEPTH_BITS \
+ )
+
+#else
+#define HASH(PTR) \
+ ( \
+     ( ((((*(PTR)<<3)^(*((PTR)+1)))<<3)^(*((PTR)+2))) & HASH_MASK) \
+  << HASH_TABLE_DEPTH_BITS \
+ )
+#endif
+
+/* Another operation that is performed more than once is the updating of the  */
+/* hash table. Here two macros are defined to simplify update operations.     */
+/* Updating consists of identifying and overwriting a pointer in a partition  */
+/* with a newer pointer and then updating the global cycle value.             */
+/* These macros accept the new pointer (NEWPTR) and either a pointer to       */
+/* (P_BASE) or the index of (I_BASE) the zeroth (first, or base) pointer in   */
+/* the partition that is to be updated. The macros use the 'cycle' variable   */
+/* to locate and overwrite a pointer and then update the cycle value.         */
+/* Note: Hardcoding 'cycle' in this macro is naughty (it should really be a   */
+/* macro parameter), but I have done so because it neatens up the code.       */
+#define UPDATE_P(P_BASE,NEWPTR) \
+{(P_BASE)[cycle++]=(NEWPTR); cycle&=DEPTH_MASK;}
+
+#define UPDATE_I(I_BASE,NEWPTR) \
+{hash[(I_BASE)+cycle++]=(NEWPTR); cycle&=DEPTH_MASK;}
+
+/* This constant supplies a legal (in-range) hash table index for use when    */
+/* a legal-but-don't-care index is required.                                  */
+#define ANY_HASH_INDEX (0)
+
+/******************************************************************************/
+#if 0
+void *ext2_lzrw3a_htab;
+#endif
+
+EXPORT int ext2_LZRW3A_compress
+           (p_src_first,p_dst_first,heap,src_len,p_dst_len)
+/* Input  : Specify input block using p_src_first and src_len.                */
+/* Input  : Point p_dst_first to the start of the output zone (OZ).           */
+/* Input  : Point p_dst_len to a ULONG to receive the output length.          */
+/* Input  : Input block and output zone must not overlap.                     */
+/* Output : Length of output block written to *p_dst_len.                     */
+/* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. May   */
+/* Output : write in OZ=Mem[p_dst_first..p_dst_first+src_len+MAX_CMP_GROUP-1].*/
+/* Output : Upon completion *p_dst_len contains final size or 0               */
+UBYTE *p_src_first;
+UBYTE *p_dst_first;
+void *heap;
+int  src_len;
+int p_dst_len;
+{
+ /* p_src and p_dst step through the source and destination blocks.           */
+ UBYTE *p_src = p_src_first;
+ UBYTE *p_dst = p_dst_first;
+
+ /* The following variables are never modified and are used in the            */
+ /* calculations that determine when the main loop terminates.                */
+ UBYTE *p_src_post  = p_src_first+src_len;
+ UBYTE *p_dst_post  = p_dst_first+p_dst_len;
+ UBYTE *p_src_max1  = p_src_first+src_len-MAX_RAW_ITEM;
+ UBYTE *p_src_max16 = p_src_first+src_len-MAX_RAW_ITEM*16;
+
+ /* The variables 'p_control' and 'control' are used to buffer control bits.  */
+ /* Before each group is processed, the next two bytes of the output block    */
+ /* are set aside for the control word for the group about to be processed.   */
+ /* 'p_control' is set to point to the first byte of that word. Meanwhile,    */
+ /* 'control' buffers the control bits being generated during the processing  */
+ /* of the group. Instead of having a counter to keep track of how many items */
+ /* have been processed (=the number of bits in the control word), at the     */
+ /* start of each group, the top word of 'control' is filled with 1 bits.     */
+ /* As 'control' is shifted for each item, the 1 bits in the top word are     */
+ /* absorbed or destroyed. When they all run out (i.e. when the top word is   */
+ /* all zero bits, we know that we are at the end of a group.                 */
+ #define TOPWORD 0xFFFF0000
+ UBYTE *p_control;
+ ULONG control=TOPWORD;
+
+ /* The variable 'hash' always points to the first element of the hash table. */
+#if 0
+ UBYTE **hash= (UBYTE **) ext2_lzrw3a_htab;
+#else
+ UBYTE **hash= (UBYTE **) heap;
+#endif
+
+ /* The following two variables represent the literal buffer. p_h1 points to  */
+ /* the partition (i.e. the zero'th (first) element of the partition)         */
+ /* corresponding to the youngest literal. p_h2 points to the partition       */
+ /* corresponding to the second youngest literal.                             */
+ /* The value zero denotes an "empty" buffer value with p_h1=0 => p_h2=0.     */
+ UBYTE **p_h1=0;
+ UBYTE **p_h2=0;
+
+ /* The following variable holds the current 'cycle' value. This value cycles */
+ /* through the range [0,HASH_TABLE_DEPTH-1], being incremented every time    */
+ /* the hash table is updated. The value gives the within-partition number of */
+ /* the next pointer to be overwritten. The decompressor maintains a cycle    */
+ /* value in synchrony.                                                       */
+ UCARD cycle=0;
+
+ /* Reserve the first word of output as the control word for the first group. */
+ /* Note: This is undone at the end if the input block is empty.              */
+ p_control=p_dst; p_dst+=2;
+
+ /* Initialize all elements of the hash table to point to a constant string.  */
+ /* Use of an unrolled loop speeds this up considerably.                      */
+ /* These variables should really be declared "register", but I am worried    */
+ /* about the possibility that extra register declarations will tempt stupid  */
+ /* compilers to allocate all registers before they get to the innermostloop. */
+ {UCARD i; UBYTE **p_h=hash;
+  #define ZH *p_h++=START_STRING_18
+  for (i=0;i<256;i++)     /* 256=HASH_TABLE_LENGTH/16. */
+    {ZH;ZH;ZH;ZH;
+     ZH;ZH;ZH;ZH;
+     ZH;ZH;ZH;ZH;
+     ZH;ZH;ZH;ZH;}
+ }
+
+ /* The main loop processes either 1 or 16 items per iteration. As its        */
+ /* termination logic is complicated, I have opted for an infinite loop       */
+ /* structure containing 'break' and 'goto' statements.                       */
+ while (TRUE)
+   {/* Begin main processing loop. */
+
+    /* Note: All the variables here except unroll should be defined within    */
+    /*       the inner loop. Unfortunately the loop hasn't got a block.       */
+     UBYTE *p_ziv;              /* Points to first byte of current Ziv.       */
+     UCARD unroll;              /* Loop counter for unrolled inner loop.      */
+     UCARD index;               /* Index of current partition.                */
+     UBYTE **p_h0;              /* Pointer to current partition.              */
+     register UCARD d;          /* Depth looping variable.                    */
+     register UCARD bestlen;    /* Holds the best length seen so far.         */
+     register UCARD bestpos;    /* Holds number of best pointer seen so far.  */
+
+    /* Test for overrun and jump to overrun code if necessary.                */
+    if (p_dst>p_dst_post)
+       goto overrun;
+
+    /* The following cascade of if statements efficiently catches and deals   */
+    /* with varying degrees of closeness to the end of the input block.       */
+    /* When we get very close to the end, we stop updating the table and      */
+    /* code the remaining bytes as literals. This makes the code simpler.     */
+    unroll=16;
+    if (p_src>p_src_max16)
+      {
+       unroll=1;
+       if (p_src>p_src_max1)
+         {
+          if (p_src==p_src_post)
+             break;
+          else
+             {p_h0=&hash[ANY_HASH_INDEX]; /* Avoid undefined pointer. */
+              goto literal;}
+         }
+      }
+
+    /* This inner unrolled loop processes 'unroll' (whose value is either 1   */
+    /* or 16) items. I have chosen to implement this loop with labels and     */
+    /* gotos to heighten the ease with which the loop may be implemented with */
+    /* a single decrement and branch instruction in assembly language and     */
+    /* also because the labels act as highly readable place markers.          */
+    /* (Also because we jump into the loop for endgame literals (see above)). */
+
+    begin_unrolled_loop:
+
+       p_ziv=p_src;
+
+       /* To process the next phrase, we hash the next three bytes to obtain  */
+       /* an index to the zeroth (first) pointer in a target partition. We    */
+       /* get the pointer.                                                    */
+       index=HASH(p_src);
+       p_h0=&hash[index];
+
+       /* This next part runs through the pointers in the partition matching  */
+       /* the bytes they point to in the Lempel with the bytes in the Ziv.    */
+       /* The length (bestlen) and within-partition pointer number (bestpos)  */
+       /* of the longest match so far is maintained and is the output of this */
+       /* segment of code. The s[bestlen]==... is an optimization only.       */
+       bestlen=0;
+       bestpos=0;
+       for (d=0;d<HASH_TABLE_DEPTH;d++)
+         {
+          register UBYTE *s=p_src;
+          register UBYTE *p=p_h0[d];
+          register UCARD len;
+          if (s[bestlen] == p[bestlen])
+            {
+             #define PS *p++!=*s++
+             (void) (PS || PS || PS || PS || PS || PS || PS || PS || PS ||
+                     PS || PS || PS || PS || PS || PS || PS || PS || PS || s++);
+             len=s-p_src-1;
+             if (len>bestlen)
+               {
+                bestpos=d;
+                bestlen=len;
+               }
+            }
+         }
+
+       /* The length of the longest match determines whether we code a */
+       /* literal item or a copy item.                                 */
+
+       if (bestlen<3)
+         {
+          /* Literal. */
+
+          /* Code the literal byte as itself and a zero control bit.          */
+          literal: *p_dst++=*p_src++; control&=0xFFFEFFFF;
+
+          /* We have just coded a literal. If we had two pending ones, that   */
+          /* makes three and we can update the hash table.                    */
+          if (p_h2!=0)
+             {UPDATE_P(p_h2,p_ziv-2);}
+
+          /* In any case, rotate the hash table pointers for next time. */
+          p_h2=p_h1; p_h1=p_h0;
+
+         }
+       else
+         {
+          /* Copy */
+
+          /* To code a copy item, we construct a hash table index of the      */
+          /* winning pointer (index+=bestpos) and code it and the best length */
+          /* into a 2 byte code word. Bump up p_src.                          */
+          index+=bestpos;
+          *p_dst++=((index&0xF00)>>4)|(bestlen-3);
+          *p_dst++=index&0xFF;
+          p_src+=bestlen;
+
+          /* As we have just coded three bytes, we are now in a position to   */
+          /* update the hash table with the literal bytes that were pending   */
+          /* upon the arrival of extra context bytes.                         */
+          if (p_h1!=0)
+            {
+             if (p_h2!=0)
+               {UPDATE_P(p_h2,p_ziv-2); p_h2=0;}
+             UPDATE_P(p_h1,p_ziv-1); p_h1=0;
+            }
+
+          /* In any case, we can update the hash table based on the current   */
+          /* position as we just coded at least three bytes in a copy items.  */
+          UPDATE_P(p_h0,p_ziv);
+         }
+       control>>=1;
+
+       /* This loop is all set up for a decrement and jump instruction! */
+    if (--unroll) goto begin_unrolled_loop;
+
+    /* At this point it will nearly always be the end of a group in which     */
+    /* case, we have to do some control-word processing. However, near the    */
+    /* end of the input block, the inner unrolled loop is only executed once. */
+    /* This necessitates the 'if' test.                                       */
+    if ((control&TOPWORD)==0)
+      {
+       /* Write the control word to the place we saved for it in the output. */
+       *p_control++=  control     &0xFF;
+       *p_control  = (control>>8) &0xFF;
+
+       /* Reserve the next word in the output block for the control word */
+       /* for the group about to be processed.                           */
+       p_control=p_dst; p_dst+=2;
+
+       /* Reset the control bits buffer. */
+       control=TOPWORD;
+      }
+
+   } /* End main processing loop. */
+
+ /* After the main processing loop has executed, all the input bytes have     */
+ /* been processed. However, the control word has still to be written to the  */
+ /* word reserved for it in the output at the start of the most recent group. */
+ /* Before writing, the control word has to be shifted so that all the bits   */
+ /* are in the right place. The "empty" bit positions are filled with 1s      */
+ /* which partially fill the top word.                                        */
+ while(control&TOPWORD) control>>=1;
+ *p_control++= control     &0xFF;
+ *p_control++=(control>>8) &0xFF;
+
+ /* If the last group contained no items, delete the control word too.        */
+ if (p_control==p_dst) p_dst-=2;
+
+ /* Write the length of the output block to the dst_len parameter and return. */
+ return p_dst-p_dst_first;
+
+ /* Jump here as soon as an overrun is detected. An overrun is defined to     */
+ /* have occurred if p_dst>p_dst_first+*p_dst_len as set by caller. */
+ /* The algorithm checks for overruns at least at the end of each group       */
+ /* which means that the maximum overrun is MAX_CMP_GROUP bytes.              */
+ /* Once an overrun occurs, the only thing to do is to return an error        */
+ overrun:
+ return 0;
+}
+
+/******************************************************************************/
+
+#if 0
+EXPORT int ext2_LZRW3A_decompress
+           (p_src_first, p_dst, src_len, dst_len)
+/* Input  : Specify input block using p_src_first.                */
+/* Input  : Point p_dst to the start of the output zone.                */
+/* Input  : dst_len contains output length */
+/* Input  : Input block and output zone must not overlap. User knows          */
+/* Input  : upperbound on output block length from earlier compression.       */
+/* Input  : In any case, maximum expansion possible is nine times.            */
+/* Input  : src_len contains max input length */
+/* Output : Writes only  in Mem[p_dst..p_dst+dst_len-1].       */
+UBYTE *p_src_first;
+UBYTE *p_dst;
+int src_len;
+int dst_len;
+{
+ UBYTE *p_dst_first = p_dst;
+
+ /* Byte pointers scan through the input and output blocks.   */
+ register UBYTE *p_src = p_src_first;
+
+ /* The following two variables are never modified and are used to control    */
+ /* the main loop.                                                            */
+ UBYTE *p_dst_post  = p_dst+dst_len;
+ UBYTE *p_dst_max16 = p_dst+dst_len-MAX_RAW_ITEM*16;
+
+ /* The hash table is the only resident of the working memory. The hash table */
+ /* contains HASH_TABLE_LENGTH=4096 pointers to positions in the history. To  */
+ /* keep Macintoshes happy, it is longword aligned.                           */
+ UBYTE **hash = (UBYTE **) ext2_lzrw3a_htab;
+
+ /* The variable 'control' is used to buffer the control bits which appear in */
+ /* groups of 16 bits (control words) at the start of each compressed group.  */
+ /* When each group is read, bit 16 of the register is set to one. Whenever   */
+ /* a new bit is needed, the register is shifted right. When the value of the */
+ /* register becomes 1, we know that we have reached the end of a group.      */
+ /* Initializing the register to 1 thus instructs the code to follow that it  */
+ /* should read a new control word immediately.                               */
+ register ULONG control=1;
+
+ /* The value of 'literals' is always in the range 0..3. It is the number of  */
+ /* consecutive literal items just seen. We have to record this number so as  */
+ /* to know when to update the hash table. When literals gets to 3, there     */
+ /* have been three consecutive literals and we can update at the position of */
+ /* the oldest of the three.                                                  */
+ register UCARD literals=0;
+
+ /* The following variable holds the current 'cycle' value. This value cycles */
+ /* through the range [0,HASH_TABLE_DEPTH-1], being incremented every time    */
+ /* the hash table is updated. The value give the within-partition number of  */
+ /* the next pointer to be overwritten. The compressor maintains a cycle      */
+ /* value in synchrony.                                                       */
+ UCARD cycle=0;
+
+ /* Initialize all elements of the hash table to point to a constant string.  */
+ /* Use of an unrolled loop speeds this up considerably.                      */
+ /* The comment about register declarations above similar code in the         */
+ /* compressor applies here too.                                              */
+ {UCARD i; UBYTE **p_h=hash;
+  #define ZJ *p_h++=START_STRING_18
+  for (i=0;i<256;i++)     /* 256=HASH_TABLE_LENGTH/16. */
+    {ZJ;ZJ;ZJ;ZJ;
+     ZJ;ZJ;ZJ;ZJ;
+     ZJ;ZJ;ZJ;ZJ;
+     ZJ;ZJ;ZJ;ZJ;}
+ }
+
+ /* The outer loop processes either 1 or 16 items per iteration depending on  */
+ /* how close p_dst is to the end of the output block.                         */
+ while (p_dst < p_dst_post && src_len >= 0)
+   {/* Start of outer loop */
+
+    register UCARD unroll;   /* Counts unrolled loop executions.              */
+
+    /* When 'control' has the value 1, it means that the 16 buffered control  */
+    /* bits that were read in at the start of the current group have all been */
+    /* shifted out and that all that is left is the 1 bit that was injected   */
+    /* into bit 16 at the start of the current group. When we reach the end   */
+    /* of a group, we have to load a new control word and inject a new 1 bit. */
+    if (control==1)
+      {
+       control=0x10000|*p_src++;
+       control|=(*p_src++)<<8;
+       src_len -= 2;
+      }
+
+    /* If it is possible that we are within 16 groups from the end of the     */
+    /* input, execute the unrolled loop only once, else process a whole group */
+    /* of 16 items by looping 16 times.                                       */
+    unroll= p_dst<=p_dst_max16 ? 16 : 1;
+
+    /* This inner loop processes one phrase (item) per iteration. */
+    while (unroll--)
+      { /* Begin unrolled inner loop. */
+
+       /* Process a literal or copy item depending on the next control bit. */
+       if (control&1)
+         {
+          /* Copy item. */
+
+          register UBYTE *p;           /* Points to place from which to copy. */
+          register UCARD lenmt;        /* Length of copy item minus three.    */
+          register UBYTE *p_ziv=p_dst; /* Pointer to start of current Ziv.    */
+          register UCARD index;        /* Index of hash table copy pointer.   */
+
+          /* Read and dismantle the copy word. Work out from where to copy.   */
+          lenmt=*p_src++;
+          index=((lenmt&0xF0)<<4)|*p_src++;
+	  src_len -= 2;
+          p=hash[index];
+          lenmt&=0xF;
+
+          /* Now perform the copy using a half unrolled loop. */
+          *p_dst++=*p++;
+          *p_dst++=*p++;
+          *p_dst++=*p++;
+          while (lenmt--)
+             *p_dst++=*p++;
+
+          /* Because we have just received 3 or more bytes in a copy item     */
+          /* (whose bytes we have just installed in the output), we are now   */
+          /* in a position to flush all the pending literal hashings that had */
+          /* been postponed for lack of bytes.                                */
+          if (literals>0)
+            {
+             register UBYTE *r=p_ziv-literals;;
+             UPDATE_I(HASH(r),r);
+             if (literals==2)
+                {r++; UPDATE_I(HASH(r),r);}
+             literals=0;
+            }
+
+          /* In any case, we can immediately update the hash table with the   */
+          /* current position. We don't need to do a HASH(...) to work out    */
+          /* where to put the pointer, as the compressor just told us!!!      */
+          UPDATE_I(index&(~DEPTH_MASK),p_ziv);
+         }
+       else
+         {
+          /* Literal item. */
+
+          /* Copy over the literal byte. */
+          *p_dst++=*p_src++;
+	  src_len--;
+
+          /* If we now have three literals waiting to be hashed into the hash */
+          /* table, we can do one of them now (because there are three).      */
+          if (++literals == 3)
+             {register UBYTE *p=p_dst-3;
+              UPDATE_I(HASH(p),p); literals=2;}
+         }
+
+       /* Shift the control buffer so the next control bit is in bit 0. */
+       control>>=1;
+
+      } /* End unrolled inner loop. */
+
+   } /* End of outer loop */
+
+#if 0
+   if(src_len < 0) return 0;
+   return (p_src-p_src_first);
+#else
+   return p_dst - p_dst_first;
+#endif
+}
+#endif
+
+/******************************************************************************/
+/*                              End of LZRW3-A.C                              */
+/******************************************************************************/
diff -urN linux-2.2.5-e2c0.4.30/fs/ext2/new-method-howto.c linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/new-method-howto.c
--- linux-2.2.5-e2c0.4.30/fs/ext2/new-method-howto.c	
+++ linux-2.2.5-e2c0.4.30-lzrw/fs/ext2/new-method-howto.c	
@@ -118,10 +118,9 @@
      in fs/ext2/Makefile.
 
      Otherwise `mkdir fs/ext2/foo', and put a Makefile in it.  If you
-     have .S files, lzrw/Makefile (see the separate LZRW patch on
-     <http://debs.fuller.edu/e2compr/software-04x.html#lzrw>) is a 
-     good starting point, otherwise gzip/Makefile.  Add foo to the 
-     definition of SUB_DIRS in fs/ext2/Makefile.
+     have .S files, lzrw/Makefile is a good starting point, otherwise
+     gzip/Makefile.  Add foo to the definition of SUB_DIRS in
+     fs/ext2/Makefile.
 
    + Edit fs/Config.in.  Search for `LZV' (there should be two such
      lines), duplicate each line, and change LZV to FOO.
diff -urN linux-2.2.5-e2c0.4.30/include/linux/ext2_fs_c.h linux-2.2.5-e2c0.4.30-lzrw/include/linux/ext2_fs_c.h
--- linux-2.2.5-e2c0.4.30/include/linux/ext2_fs_c.h	
+++ linux-2.2.5-e2c0.4.30-lzrw/include/linux/ext2_fs_c.h	
@@ -157,7 +157,11 @@
 # else
 #  define _ext2_lzv1_builtin 0
 # endif
-# define _ext2_lzrw3a_builtin 0
+# ifdef CONFIG_EXT2_HAVE_LZRW3A
+#  define _ext2_lzrw3a_builtin (1 << EXT2_LZRW3A_ALG)
+# else
+#  define _ext2_lzrw3a_builtin 0
+# endif
 # ifdef CONFIG_EXT2_HAVE_GZIP
 #  define _ext2_gzip_builtin (1 << EXT2_GZIP_ALG)
 # else
@@ -179,7 +183,11 @@
 # else
 #  define _ext2_lzv1_module 0
 # endif
-# define _ext2_lzrw3a_module 0
+# ifdef CONFIG_EXT2_HAVE_LZRW3A_MODULE
+#  define _ext2_lzrw3a_module (1 << EXT2_LZRW3A_ALG)
+# else
+#  define _ext2_lzrw3a_module 0
+# endif
 # ifdef CONFIG_EXT2_HAVE_GZIP_MODULE
 #  define _ext2_gzip_module (1 << EXT2_GZIP_ALG)
 # else
@@ -317,6 +325,7 @@
 
 extern size_t ext2_iLZV1   (int);
 extern size_t ext2_iLZV2   (int);
+extern size_t ext2_iLZRW3A (int);
 extern size_t ext2_iNONE   (int);
 extern size_t ext2_iGZIP   (int);
 extern size_t ext2_iBZIP2  (int);
@@ -324,6 +333,7 @@
 
 extern size_t ext2_wLZV1   (__u8*, __u8*, void*, size_t, size_t, int);
 extern size_t ext2_wLZV2   (__u8*, __u8*, void*, size_t, size_t, int);
+extern size_t ext2_wLZRW3A (__u8*, __u8*, void*, size_t, size_t, int);
 extern size_t ext2_wNONE   (__u8*, __u8*, void*, size_t, size_t, int);
 extern size_t ext2_wGZIP   (__u8*, __u8*, void*, size_t, size_t, int);
 extern size_t ext2_wBZIP2  (__u8*, __u8*, void*, size_t, size_t, int);
@@ -331,6 +341,7 @@
 
 extern size_t ext2_rLZV1   (__u8*, __u8*, void*, size_t, size_t, int);
 extern size_t ext2_rLZV2   (__u8*, __u8*, void*, size_t, size_t, int);
+extern size_t ext2_rLZRW3A (__u8*, __u8*, void*, size_t, size_t, int);
 extern size_t ext2_rNONE   (__u8*, __u8*, void*, size_t, size_t, int);
 extern size_t ext2_rGZIP   (__u8*, __u8*, void*, size_t, size_t, int);
 extern size_t ext2_rBZIP2  (__u8*, __u8*, void*, size_t, size_t, int);
