<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">--- a/jffsX-utils/Makemodule.am
+++ b/jffsX-utils/Makemodule.am
@@ -4,11 +4,19 @@ mkfs_jffs2_SOURCES = \
 	jffsX-utils/compr_zlib.c \
 	jffsX-utils/compr.h \
 	jffsX-utils/rbtree.c \
-	jffsX-utils/compr_lzo.c \
+	jffsX-utils/compr_lzma.c \
+	jffsX-utils/lzma/LzFind.c \
+	jffsX-utils/lzma/LzmaEnc.c \
+	jffsX-utils/lzma/LzmaDec.c \
 	jffsX-utils/compr.c \
 	jffsX-utils/compr_rtime.c
+
+if !WITHOUT_LZO
+mkfs_jffs2_SOURCES += jffsX-utils/compr_lzo.c
+endif
+
 mkfs_jffs2_LDADD = libmtd.a $(ZLIB_LIBS) $(LZO_LIBS)
-mkfs_jffs2_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) $(LZO_CFLAGS)
+mkfs_jffs2_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) $(LZO_CFLAGS) -I./include/linux/lzma
 
 jffs2reader_SOURCES = jffsX-utils/jffs2reader.c
 jffs2reader_LDADD = libmtd.a $(ZLIB_LIBS) $(LZO_LIBS)
--- a/jffsX-utils/compr.c
+++ b/jffsX-utils/compr.c
@@ -520,6 +520,9 @@ int jffs2_compressors_init(void)
 #ifdef CONFIG_JFFS2_LZO
 	jffs2_lzo_init();
 #endif
+#ifdef CONFIG_JFFS2_LZMA
+	jffs2_lzma_init();
+#endif
 	return 0;
 }
 
@@ -534,5 +537,8 @@ int jffs2_compressors_exit(void)
 #ifdef CONFIG_JFFS2_LZO
 	jffs2_lzo_exit();
 #endif
+#ifdef CONFIG_JFFS2_LZMA
+	jffs2_lzma_exit();
+#endif
 	return 0;
 }
--- a/jffsX-utils/compr.h
+++ b/jffsX-utils/compr.h
@@ -18,13 +18,14 @@
 
 #define CONFIG_JFFS2_ZLIB
 #define CONFIG_JFFS2_RTIME
-#define CONFIG_JFFS2_LZO
+#define CONFIG_JFFS2_LZMA
 
 #define JFFS2_RUBINMIPS_PRIORITY 10
 #define JFFS2_DYNRUBIN_PRIORITY  20
 #define JFFS2_RTIME_PRIORITY     50
-#define JFFS2_ZLIB_PRIORITY      60
-#define JFFS2_LZO_PRIORITY       80
+#define JFFS2_LZMA_PRIORITY      70
+#define JFFS2_ZLIB_PRIORITY      80
+#define JFFS2_LZO_PRIORITY       90
 
 #define JFFS2_COMPR_MODE_NONE       0
 #define JFFS2_COMPR_MODE_PRIORITY   1
@@ -115,5 +116,10 @@ void jffs2_rtime_exit(void);
 int jffs2_lzo_init(void);
 void jffs2_lzo_exit(void);
 #endif
+#ifdef CONFIG_JFFS2_LZMA
+int jffs2_lzma_init(void);
+void jffs2_lzma_exit(void);
+#endif
+
 
 #endif /* __JFFS2_COMPR_H__ */
--- /dev/null
+++ b/jffsX-utils/compr_lzma.c
@@ -0,0 +1,128 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ * JFFS2 wrapper to the LZMA C SDK
+ *
+ */
+
+#include &lt;linux/lzma.h&gt;
+#include "compr.h"
+
+#ifdef __KERNEL__
+	static DEFINE_MUTEX(deflate_mutex);
+#endif
+
+CLzmaEncHandle *p;
+Byte propsEncoded[LZMA_PROPS_SIZE];
+SizeT propsSize = sizeof(propsEncoded);
+
+STATIC void lzma_free_workspace(void)
+{
+	LzmaEnc_Destroy(p, &amp;lzma_alloc, &amp;lzma_alloc);
+}
+
+STATIC int INIT lzma_alloc_workspace(CLzmaEncProps *props)
+{
+	if ((p = (CLzmaEncHandle *)LzmaEnc_Create(&amp;lzma_alloc)) == NULL)
+	{
+		PRINT_ERROR("Failed to allocate lzma deflate workspace\n");
+		return -ENOMEM;
+	}
+
+	if (LzmaEnc_SetProps(p, props) != SZ_OK)
+	{
+		lzma_free_workspace();
+		return -1;
+	}
+	
+	if (LzmaEnc_WriteProperties(p, propsEncoded, &amp;propsSize) != SZ_OK)
+	{
+		lzma_free_workspace();
+		return -1;
+	}
+
+	return 0;
+}
+
+STATIC int jffs2_lzma_compress(unsigned char *data_in, unsigned char *cpage_out,
+			      uint32_t *sourcelen, uint32_t *dstlen)
+{
+	SizeT compress_size = (SizeT)(*dstlen);
+	int ret;
+
+	#ifdef __KERNEL__
+		mutex_lock(&amp;deflate_mutex);
+	#endif
+
+	ret = LzmaEnc_MemEncode(p, cpage_out, &amp;compress_size, data_in, *sourcelen,
+		0, NULL, &amp;lzma_alloc, &amp;lzma_alloc);
+
+	#ifdef __KERNEL__
+		mutex_unlock(&amp;deflate_mutex);
+	#endif
+
+	if (ret != SZ_OK)
+		return -1;
+
+	*dstlen = (uint32_t)compress_size;
+
+	return 0;
+}
+
+STATIC int jffs2_lzma_decompress(unsigned char *data_in, unsigned char *cpage_out,
+				 uint32_t srclen, uint32_t destlen)
+{
+	int ret;
+	SizeT dl = (SizeT)destlen;
+	SizeT sl = (SizeT)srclen;
+	ELzmaStatus status;
+	
+	ret = LzmaDecode(cpage_out, &amp;dl, data_in, &amp;sl, propsEncoded,
+		propsSize, LZMA_FINISH_ANY, &amp;status, &amp;lzma_alloc);
+
+	if (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (SizeT)destlen)
+		return -1;
+
+	return 0;
+}
+
+static struct jffs2_compressor jffs2_lzma_comp = {
+	.priority = JFFS2_LZMA_PRIORITY,
+	.name = "lzma",
+	.compr = JFFS2_COMPR_LZMA,
+	.compress = &amp;jffs2_lzma_compress,
+	.decompress = &amp;jffs2_lzma_decompress,
+	.disabled = 0,
+};
+
+int INIT jffs2_lzma_init(void)
+{
+	int ret;
+	CLzmaEncProps props;
+	LzmaEncProps_Init(&amp;props);
+
+	props.dictSize = LZMA_BEST_DICT(0x2000);
+	props.level = LZMA_BEST_LEVEL;
+	props.lc = LZMA_BEST_LC;
+	props.lp = LZMA_BEST_LP;
+	props.pb = LZMA_BEST_PB;
+	props.fb = LZMA_BEST_FB;
+
+	ret = lzma_alloc_workspace(&amp;props);
+	if (ret &lt; 0)
+		return ret;
+
+	ret = jffs2_register_compressor(&amp;jffs2_lzma_comp);
+	if (ret)
+		lzma_free_workspace();
+	
+	return ret;
+}
+
+void jffs2_lzma_exit(void)
+{
+	jffs2_unregister_compressor(&amp;jffs2_lzma_comp);
+	lzma_free_workspace();
+}
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -47,6 +47,7 @@
 #define JFFS2_COMPR_DYNRUBIN	0x05
 #define JFFS2_COMPR_ZLIB	0x06
 #define JFFS2_COMPR_LZO		0x07
+#define JFFS2_COMPR_LZMA	0x08
 /* Compatibility flags. */
 #define JFFS2_COMPAT_MASK 0xc000      /* What do to if an unknown nodetype is found */
 #define JFFS2_NODE_ACCURATE 0x2000
--- /dev/null
+++ b/include/linux/lzma.h
@@ -0,0 +1,61 @@
+#ifndef __LZMA_H__
+#define __LZMA_H__
+
+#ifdef __KERNEL__
+	#include &lt;linux/kernel.h&gt;
+	#include &lt;linux/sched.h&gt;
+	#include &lt;linux/slab.h&gt;
+	#include &lt;linux/vmalloc.h&gt;
+	#include &lt;linux/init.h&gt;
+	#define LZMA_MALLOC vmalloc
+	#define LZMA_FREE vfree
+	#define PRINT_ERROR(msg) printk(KERN_WARNING #msg)
+	#define INIT __init
+	#define STATIC static
+#else
+	#include &lt;stdint.h&gt;
+	#include &lt;stdlib.h&gt;
+	#include &lt;stdio.h&gt;
+	#include &lt;unistd.h&gt;
+	#include &lt;string.h&gt;
+	#include &lt;errno.h&gt;
+	#include &lt;linux/jffs2.h&gt;
+	#ifndef PAGE_SIZE
+		extern int page_size;
+		#define PAGE_SIZE page_size
+	#endif
+	#define LZMA_MALLOC malloc
+	#define LZMA_FREE free
+	#define PRINT_ERROR(msg) fprintf(stderr, msg)
+	#define INIT
+	#define STATIC static
+#endif
+
+#include "lzma/LzmaDec.h"
+#include "lzma/LzmaEnc.h"
+
+#define LZMA_BEST_LEVEL (9)
+#define LZMA_BEST_LC    (0)
+#define LZMA_BEST_LP    (0)
+#define LZMA_BEST_PB    (0)
+#define LZMA_BEST_FB  (273)
+
+#define LZMA_BEST_DICT(n) (((int)((n) / 2)) * 2)
+
+static void *p_lzma_malloc(void *p, size_t size)
+{
+	if (size == 0)
+		return NULL;
+
+	return LZMA_MALLOC(size);
+}
+
+static void p_lzma_free(void *p, void *address)
+{
+	if (address != NULL)
+		LZMA_FREE(address);
+}
+
+static ISzAlloc lzma_alloc = {p_lzma_malloc, p_lzma_free};
+
+#endif
--- /dev/null
+++ b/include/linux/lzma/LzFind.h
@@ -0,0 +1,116 @@
+/* LzFind.h  -- Match finder for LZ algorithms
+2008-04-04
+Copyright (c) 1999-2008 Igor Pavlov
+You can use any of the following license options:
+  1) GNU Lesser General Public License (GNU LGPL)
+  2) Common Public License (CPL)
+  3) Common Development and Distribution License (CDDL) Version 1.0 
+  4) Igor Pavlov, as the author of this code, expressly permits you to 
+     statically or dynamically link your code (or bind by name) to this file, 
+     while you keep this file unmodified.
+*/
+
+#ifndef __LZFIND_H
+#define __LZFIND_H
+
+#include "Types.h"
+
+typedef UInt32 CLzRef;
+
+typedef struct _CMatchFinder
+{
+  Byte *buffer;
+  UInt32 pos;
+  UInt32 posLimit;
+  UInt32 streamPos;
+  UInt32 lenLimit;
+
+  UInt32 cyclicBufferPos;
+  UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
+
+  UInt32 matchMaxLen;
+  CLzRef *hash;
+  CLzRef *son;
+  UInt32 hashMask;
+  UInt32 cutValue;
+
+  Byte *bufferBase;
+  ISeqInStream *stream;
+  int streamEndWasReached;
+
+  UInt32 blockSize;
+  UInt32 keepSizeBefore;
+  UInt32 keepSizeAfter;
+
+  UInt32 numHashBytes;
+  int directInput;
+  int btMode;
+  /* int skipModeBits; */
+  int bigHash;
+  UInt32 historySize;
+  UInt32 fixedHashSize;
+  UInt32 hashSizeSum;
+  UInt32 numSons;
+  SRes result;
+  UInt32 crc[256];
+} CMatchFinder;
+
+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)-&gt;buffer)
+#define Inline_MatchFinder_GetIndexByte(p, index) ((p)-&gt;buffer[(Int32)(index)])
+
+#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)-&gt;streamPos - (p)-&gt;pos)
+
+int MatchFinder_NeedMove(CMatchFinder *p);
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
+void MatchFinder_MoveBlock(CMatchFinder *p);
+void MatchFinder_ReadIfRequired(CMatchFinder *p);
+
+void MatchFinder_Construct(CMatchFinder *p);
+
+/* Conditions:
+     historySize &lt;= 3 GB
+     keepAddBufferBefore + matchMaxLen + keepAddBufferAfter &lt; 511MB
+*/
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, 
+    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+    ISzAlloc *alloc);
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, 
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, 
+    UInt32 *distances, UInt32 maxLen);
+
+/* 
+Conditions:
+  Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
+  Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
+*/
+
+typedef void (*Mf_Init_Func)(void *object);
+typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
+typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
+typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
+typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
+typedef void (*Mf_Skip_Func)(void *object, UInt32);
+
+typedef struct _IMatchFinder
+{
+  Mf_Init_Func Init;
+  Mf_GetIndexByte_Func GetIndexByte;
+  Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
+  Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
+  Mf_GetMatches_Func GetMatches;
+  Mf_Skip_Func Skip;
+} IMatchFinder;
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
+
+void MatchFinder_Init(CMatchFinder *p);
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+
+#endif
--- /dev/null
+++ b/include/linux/lzma/LzHash.h
@@ -0,0 +1,56 @@
+/* LzHash.h  -- HASH functions for LZ algorithms
+2008-03-26
+Copyright (c) 1999-2008 Igor Pavlov
+Read LzFind.h for license options */
+
+#ifndef __LZHASH_H
+#define __LZHASH_H
+
+#define kHash2Size (1 &lt;&lt; 10)
+#define kHash3Size (1 &lt;&lt; 16)
+#define kHash4Size (1 &lt;&lt; 20)
+
+#define kFix3HashSize (kHash2Size)
+#define kFix4HashSize (kHash2Size + kHash3Size)
+#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
+
+#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] &lt;&lt; 8);
+
+#define HASH3_CALC { \
+  UInt32 temp = p-&gt;crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp &amp; (kHash2Size - 1); \
+  hashValue = (temp ^ ((UInt32)cur[2] &lt;&lt; 8)) &amp; p-&gt;hashMask; }
+
+#define HASH4_CALC { \
+  UInt32 temp = p-&gt;crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp &amp; (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] &lt;&lt; 8)) &amp; (kHash3Size - 1); \
+  hashValue = (temp ^ ((UInt32)cur[2] &lt;&lt; 8) ^ (p-&gt;crc[cur[3]] &lt;&lt; 5)) &amp; p-&gt;hashMask; }
+
+#define HASH5_CALC { \
+  UInt32 temp = p-&gt;crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp &amp; (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] &lt;&lt; 8)) &amp; (kHash3Size - 1); \
+  hash4Value = (temp ^ ((UInt32)cur[2] &lt;&lt; 8) ^ (p-&gt;crc[cur[3]] &lt;&lt; 5)); \
+  hashValue = (hash4Value ^ (p-&gt;crc[cur[4]] &lt;&lt; 3)) &amp; p-&gt;hashMask; \
+  hash4Value &amp;= (kHash4Size - 1); }
+
+/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] &lt;&lt; 8)) ^ p-&gt;crc[cur[2]]) &amp; 0xFFFF; */
+#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] &lt;&lt; 8)) ^ p-&gt;crc[cur[1]]) &amp; 0xFFFF;
+
+
+#define MT_HASH2_CALC \
+  hash2Value = (p-&gt;crc[cur[0]] ^ cur[1]) &amp; (kHash2Size - 1);
+
+#define MT_HASH3_CALC { \
+  UInt32 temp = p-&gt;crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp &amp; (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] &lt;&lt; 8)) &amp; (kHash3Size - 1); }
+
+#define MT_HASH4_CALC { \
+  UInt32 temp = p-&gt;crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp &amp; (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] &lt;&lt; 8)) &amp; (kHash3Size - 1); \
+  hash4Value = (temp ^ ((UInt32)cur[2] &lt;&lt; 8) ^ (p-&gt;crc[cur[3]] &lt;&lt; 5)) &amp; (kHash4Size - 1); }
+
+#endif
--- /dev/null
+++ b/include/linux/lzma/LzmaDec.h
@@ -0,0 +1,232 @@
+/* LzmaDec.h -- LZMA Decoder
+2008-04-29
+Copyright (c) 1999-2008 Igor Pavlov
+You can use any of the following license options:
+  1) GNU Lesser General Public License (GNU LGPL)
+  2) Common Public License (CPL)
+  3) Common Development and Distribution License (CDDL) Version 1.0 
+  4) Igor Pavlov, as the author of this code, expressly permits you to 
+     statically or dynamically link your code (or bind by name) to this file, 
+     while you keep this file unmodified.
+*/
+
+#ifndef __LZMADEC_H
+#define __LZMADEC_H
+
+#include "Types.h"
+
+/* #define _LZMA_PROB32 */
+/* _LZMA_PROB32 can increase the speed on some CPUs, 
+   but memory usage for CLzmaDec::probs will be doubled in that case */
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+
+/* ---------- LZMA Properties ---------- */  
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaProps
+{
+  unsigned lc, lp, pb;
+  UInt32 dicSize;
+} CLzmaProps;
+
+/* LzmaProps_Decode - decodes properties
+Returns:
+  SZ_OK
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
+
+
+/* ---------- LZMA Decoder state ---------- */  
+
+/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
+   Num bits = log2((2^11 / 31) ^ 22) + 26 &lt; 134 + 26 = 160; */
+
+#define LZMA_REQUIRED_INPUT_MAX 20
+
+typedef struct
+{
+  CLzmaProps prop;
+  CLzmaProb *probs;
+  Byte *dic;
+  const Byte *buf;
+  UInt32 range, code;
+  SizeT dicPos;
+  SizeT dicBufSize;
+  UInt32 processedPos;
+  UInt32 checkDicSize;
+  unsigned state;
+  UInt32 reps[4];
+  unsigned remainLen;
+  int needFlush;
+  int needInitState;
+  UInt32 numProbs;
+  unsigned tempBufSize;
+  Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
+} CLzmaDec;
+
+#define LzmaDec_Construct(p) { (p)-&gt;dic = 0; (p)-&gt;probs = 0; }
+
+void LzmaDec_Init(CLzmaDec *p);
+
+/* There are two types of LZMA streams:
+     0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
+     1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
+
+typedef enum 
+{
+  LZMA_FINISH_ANY,   /* finish at any point */      
+  LZMA_FINISH_END    /* block must be finished at the end */
+} ELzmaFinishMode;
+
+/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
+
+   You must use LZMA_FINISH_END, when you know that current output buffer 
+   covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
+
+   If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
+   and output value of destLen will be less than output buffer size limit.
+   You can check status result also.
+
+   You can use multiple checks to test data integrity after full decompression:
+     1) Check Result and "status" variable.
+     2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
+     3) Check that output(srcLen) = compressedSize, if you know real compressedSize. 
+        You must use correct finish mode in that case. */ 
+
+typedef enum 
+{
+  LZMA_STATUS_NOT_SPECIFIED,               /* use main error code instead */
+  LZMA_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */
+  LZMA_STATUS_NOT_FINISHED,                /* stream was not finished */
+  LZMA_STATUS_NEEDS_MORE_INPUT,            /* you must provide more input bytes */   
+  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK  /* there is probability that stream was finished without end mark */
+} ELzmaStatus;
+
+/* ELzmaStatus is used only as output value for function call */
+
+
+/* ---------- Interfaces ---------- */  
+
+/* There are 3 levels of interfaces:
+     1) Dictionary Interface
+     2) Buffer Interface
+     3) One Call Interface
+   You can select any of these interfaces, but don't mix functions from different 
+   groups for same object. */
+
+
+/* There are two variants to allocate state for Dictionary Interface:
+     1) LzmaDec_Allocate / LzmaDec_Free
+     2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
+   You can use variant 2, if you set dictionary buffer manually. 
+   For Buffer Interface you must always use variant 1. 
+
+LzmaDec_Allocate* can return:
+  SZ_OK
+  SZ_ERROR_MEM         - Memory allocation error
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+   
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
+
+SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
+
+/* ---------- Dictionary Interface ---------- */  
+
+/* You can use it, if you want to eliminate the overhead for data copying from 
+   dictionary to some other external buffer.
+   You must work with CLzmaDec variables directly in this interface.
+
+   STEPS:
+     LzmaDec_Constr()
+     LzmaDec_Allocate()
+     for (each new stream)
+     {
+       LzmaDec_Init()
+       while (it needs more decompression)
+       {
+         LzmaDec_DecodeToDic()
+         use data from CLzmaDec::dic and update CLzmaDec::dicPos
+       }
+     }
+     LzmaDec_Free()
+*/
+
+/* LzmaDec_DecodeToDic
+   
+   The decoding to internal dictionary buffer (CLzmaDec::dic).
+   You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! 
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (dicLimit).
+  LZMA_FINISH_ANY - Decode just dicLimit bytes.
+  LZMA_FINISH_END - Stream must be finished after dicLimit.
+
+Returns:
+  SZ_OK
+    status:
+      LZMA_STATUS_FINISHED_WITH_MARK
+      LZMA_STATUS_NOT_FINISHED 
+      LZMA_STATUS_NEEDS_MORE_INPUT
+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+  SZ_ERROR_DATA - Data error
+*/
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, 
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- Buffer Interface ---------- */  
+
+/* It's zlib-like interface.
+   See LzmaDec_DecodeToDic description for information about STEPS and return results,
+   but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
+   to work with CLzmaDec variables manually.
+
+finishMode: 
+  It has meaning only if the decoding reaches output limit (*destLen).
+  LZMA_FINISH_ANY - Decode just destLen bytes.
+  LZMA_FINISH_END - Stream must be finished after (*destLen).
+*/
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, 
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- One Call Interface ---------- */  
+
+/* LzmaDecode
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (*destLen).
+  LZMA_FINISH_ANY - Decode just destLen bytes.
+  LZMA_FINISH_END - Stream must be finished after (*destLen).
+
+Returns:
+  SZ_OK
+    status:
+      LZMA_STATUS_FINISHED_WITH_MARK
+      LZMA_STATUS_NOT_FINISHED 
+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+  SZ_ERROR_DATA - Data error
+  SZ_ERROR_MEM  - Memory allocation error
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
+*/
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 
+    ELzmaStatus *status, ISzAlloc *alloc);
+
+#endif
--- /dev/null
+++ b/include/linux/lzma/LzmaEnc.h
@@ -0,0 +1,74 @@
+/*  LzmaEnc.h -- LZMA Encoder
+2008-04-27
+Copyright (c) 1999-2008 Igor Pavlov
+Read LzFind.h for license options */
+
+#ifndef __LZMAENC_H
+#define __LZMAENC_H
+
+#include "Types.h"
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaEncProps
+{
+  int level;       /*  0 &lt;= level &lt;= 9 */ 
+  UInt32 dictSize; /* (1 &lt;&lt; 12) &lt;= dictSize &lt;= (1 &lt;&lt; 27) for 32-bit version
+                      (1 &lt;&lt; 12) &lt;= dictSize &lt;= (1 &lt;&lt; 30) for 64-bit version 
+                       default = (1 &lt;&lt; 24) */
+  int lc;          /* 0 &lt;= lc &lt;= 8, default = 3 */ 
+  int lp;          /* 0 &lt;= lp &lt;= 4, default = 0 */ 
+  int pb;          /* 0 &lt;= pb &lt;= 4, default = 2 */ 
+  int algo;        /* 0 - fast, 1 - normal, default = 1 */
+  int fb;          /* 5 &lt;= fb &lt;= 273, default = 32 */
+  int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
+  int numHashBytes; /* 2, 3 or 4, default = 4 */
+  UInt32 mc;        /* 1 &lt;= mc &lt;= (1 &lt;&lt; 30), default = 32 */
+  unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
+  int numThreads;  /* 1 or 2, default = 2 */
+} CLzmaEncProps;
+
+void LzmaEncProps_Init(CLzmaEncProps *p);
+void LzmaEncProps_Normalize(CLzmaEncProps *p);
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
+
+
+/* ---------- CLzmaEncHandle Interface ---------- */
+
+/* LzmaEnc_* functions can return the following exit codes:
+Returns:
+  SZ_OK           - OK
+  SZ_ERROR_MEM    - Memory allocation error 
+  SZ_ERROR_PARAM  - Incorrect paramater in props
+  SZ_ERROR_WRITE  - Write callback error.
+  SZ_ERROR_PROGRESS - some break from progress callback
+  SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
+*/
+
+typedef void * CLzmaEncHandle;
+
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
+SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
+SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, 
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+
+/* ---------- One Call Interface ---------- */
+
+/* LzmaEncode
+Return code:
+  SZ_OK               - OK
+  SZ_ERROR_MEM        - Memory allocation error 
+  SZ_ERROR_PARAM      - Incorrect paramater
+  SZ_ERROR_OUTPUT_EOF - output buffer overflow
+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)
+*/
+
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, 
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+
+#endif
--- /dev/null
+++ b/include/linux/lzma/Types.h
@@ -0,0 +1,130 @@
+/* Types.h -- Basic types
+2008-04-11
+Igor Pavlov
+Public domain */
+
+#ifndef __7Z_TYPES_H
+#define __7Z_TYPES_H
+
+#define SZ_OK 0
+
+#define SZ_ERROR_DATA 1
+#define SZ_ERROR_MEM 2
+#define SZ_ERROR_CRC 3
+#define SZ_ERROR_UNSUPPORTED 4
+#define SZ_ERROR_PARAM 5
+#define SZ_ERROR_INPUT_EOF 6
+#define SZ_ERROR_OUTPUT_EOF 7
+#define SZ_ERROR_READ 8
+#define SZ_ERROR_WRITE 9
+#define SZ_ERROR_PROGRESS 10
+#define SZ_ERROR_FAIL 11
+#define SZ_ERROR_THREAD 12
+
+#define SZ_ERROR_ARCHIVE 16
+#define SZ_ERROR_NO_ARCHIVE 17
+
+typedef int SRes;
+
+#ifndef RINOK
+#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
+#endif
+
+typedef unsigned char Byte;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef long Int32;
+typedef unsigned long UInt32;
+#else
+typedef int Int32;
+typedef unsigned int UInt32;
+#endif
+
+/* #define _SZ_NO_INT_64 */
+/* define it if your compiler doesn't support 64-bit integers */
+
+#ifdef _SZ_NO_INT_64
+
+typedef long Int64;
+typedef unsigned long UInt64;
+
+#else
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#endif
+
+#endif
+
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+#include &lt;stddef.h&gt;
+typedef size_t SizeT;
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+
+#ifdef _MSC_VER
+
+#if _MSC_VER &gt;= 1300
+#define MY_NO_INLINE __declspec(noinline)
+#else
+#define MY_NO_INLINE
+#endif
+
+#define MY_CDECL __cdecl
+#define MY_STD_CALL __stdcall 
+#define MY_FAST_CALL MY_NO_INLINE __fastcall 
+
+#else
+
+#define MY_CDECL
+#define MY_STD_CALL
+#define MY_FAST_CALL
+
+#endif
+
+
+/* The following interfaces use first parameter as pointer to structure */
+
+typedef struct
+{
+  SRes (*Read)(void *p, void *buf, size_t *size);
+    /* if (input(*size) != 0 &amp;&amp; output(*size) == 0) means end_of_stream.
+       (output(*size) &lt; input(*size)) is allowed */
+} ISeqInStream;
+
+typedef struct
+{
+  size_t (*Write)(void *p, const void *buf, size_t size);
+    /* Returns: result - the number of actually written bytes.
+      (result &lt; size) means error */
+} ISeqOutStream;
+
+typedef struct
+{
+  SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
+    /* Returns: result. (result != SZ_OK) means break.
+       Value (UInt64)(Int64)-1 for size means unknown value. */
+} ICompressProgress;
+
+typedef struct
+{
+  void *(*Alloc)(void *p, size_t size);
+  void (*Free)(void *p, void *address); /* address can be 0 */
+} ISzAlloc;
+
+#define IAlloc_Alloc(p, size) (p)-&gt;Alloc((p), size)
+#define IAlloc_Free(p, a) (p)-&gt;Free((p), a)
+
+#endif
--- /dev/null
+++ b/jffsX-utils/lzma/LzFind.c
@@ -0,0 +1,753 @@
+/* LzFind.c  -- Match finder for LZ algorithms
+2008-04-04
+Copyright (c) 1999-2008 Igor Pavlov
+Read LzFind.h for license options */
+
+#include &lt;string.h&gt;
+
+#include "LzFind.h"
+#include "LzHash.h"
+
+#define kEmptyHashValue 0
+#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
+#define kNormalizeStepMin (1 &lt;&lt; 10) /* it must be power of 2 */
+#define kNormalizeMask (~(kNormalizeStepMin - 1))
+#define kMaxHistorySize ((UInt32)3 &lt;&lt; 30)
+
+#define kStartMaxLen 3
+
+static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+  if (!p-&gt;directInput)
+  {
+    alloc-&gt;Free(alloc, p-&gt;bufferBase);
+    p-&gt;bufferBase = 0;
+  }
+}
+
+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be &lt; 4G) */
+
+static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
+{
+  UInt32 blockSize = p-&gt;keepSizeBefore + p-&gt;keepSizeAfter + keepSizeReserv;
+  if (p-&gt;directInput)
+  {
+    p-&gt;blockSize = blockSize;
+    return 1;
+  }
+  if (p-&gt;bufferBase == 0 || p-&gt;blockSize != blockSize)
+  {
+    LzInWindow_Free(p, alloc);
+    p-&gt;blockSize = blockSize;
+    p-&gt;bufferBase = (Byte *)alloc-&gt;Alloc(alloc, (size_t)blockSize);
+  }
+  return (p-&gt;bufferBase != 0);
+}
+
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p-&gt;buffer; }
+static Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p-&gt;buffer[index]; }
+
+static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p-&gt;streamPos - p-&gt;pos; }
+
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
+{
+  p-&gt;posLimit -= subValue;
+  p-&gt;pos -= subValue;
+  p-&gt;streamPos -= subValue;
+}
+
+static void MatchFinder_ReadBlock(CMatchFinder *p)
+{
+  if (p-&gt;streamEndWasReached || p-&gt;result != SZ_OK)
+    return;
+  for (;;)
+  {
+    Byte *dest = p-&gt;buffer + (p-&gt;streamPos - p-&gt;pos);
+    size_t size = (p-&gt;bufferBase + p-&gt;blockSize - dest);
+    if (size == 0)
+      return;
+    p-&gt;result = p-&gt;stream-&gt;Read(p-&gt;stream, dest, &amp;size);
+    if (p-&gt;result != SZ_OK)
+      return;
+    if (size == 0)
+    {
+      p-&gt;streamEndWasReached = 1;
+      return;
+    }
+    p-&gt;streamPos += (UInt32)size;
+    if (p-&gt;streamPos - p-&gt;pos &gt; p-&gt;keepSizeAfter)
+      return;
+  }
+}
+
+void MatchFinder_MoveBlock(CMatchFinder *p)
+{
+  memmove(p-&gt;bufferBase, 
+    p-&gt;buffer - p-&gt;keepSizeBefore, 
+    (size_t)(p-&gt;streamPos - p-&gt;pos + p-&gt;keepSizeBefore));
+  p-&gt;buffer = p-&gt;bufferBase + p-&gt;keepSizeBefore;
+}
+
+int MatchFinder_NeedMove(CMatchFinder *p)
+{
+  /* if (p-&gt;streamEndWasReached) return 0; */
+  return ((size_t)(p-&gt;bufferBase + p-&gt;blockSize - p-&gt;buffer) &lt;= p-&gt;keepSizeAfter);
+}
+
+void MatchFinder_ReadIfRequired(CMatchFinder *p)
+{
+  if (p-&gt;streamEndWasReached) 
+    return;
+  if (p-&gt;keepSizeAfter &gt;= p-&gt;streamPos - p-&gt;pos)
+    MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
+{
+  if (MatchFinder_NeedMove(p))
+    MatchFinder_MoveBlock(p);
+  MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
+{
+  p-&gt;cutValue = 32;
+  p-&gt;btMode = 1;
+  p-&gt;numHashBytes = 4;
+  /* p-&gt;skipModeBits = 0; */
+  p-&gt;directInput = 0;
+  p-&gt;bigHash = 0;
+}
+
+#define kCrcPoly 0xEDB88320
+
+void MatchFinder_Construct(CMatchFinder *p)
+{
+  UInt32 i;
+  p-&gt;bufferBase = 0;
+  p-&gt;directInput = 0;
+  p-&gt;hash = 0;
+  MatchFinder_SetDefaultSettings(p);
+
+  for (i = 0; i &lt; 256; i++)
+  {
+    UInt32 r = i;
+    int j;
+    for (j = 0; j &lt; 8; j++)
+      r = (r &gt;&gt; 1) ^ (kCrcPoly &amp; ~((r &amp; 1) - 1));
+    p-&gt;crc[i] = r;
+  }
+}
+
+static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
+{
+  alloc-&gt;Free(alloc, p-&gt;hash);
+  p-&gt;hash = 0;
+}
+
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+  MatchFinder_FreeThisClassMemory(p, alloc);
+  LzInWindow_Free(p, alloc);
+}
+
+static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
+{
+  size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
+  if (sizeInBytes / sizeof(CLzRef) != num)
+    return 0;
+  return (CLzRef *)alloc-&gt;Alloc(alloc, sizeInBytes);
+}
+
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, 
+    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+    ISzAlloc *alloc)
+{
+  UInt32 sizeReserv;
+  if (historySize &gt; kMaxHistorySize)
+  {
+    MatchFinder_Free(p, alloc);
+    return 0;
+  }
+  sizeReserv = historySize &gt;&gt; 1;
+  if (historySize &gt; ((UInt32)2 &lt;&lt; 30))
+    sizeReserv = historySize &gt;&gt; 2;
+  sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 &lt;&lt; 19);
+
+  p-&gt;keepSizeBefore = historySize + keepAddBufferBefore + 1; 
+  p-&gt;keepSizeAfter = matchMaxLen + keepAddBufferAfter;
+  /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
+  if (LzInWindow_Create(p, sizeReserv, alloc))
+  {
+    UInt32 newCyclicBufferSize = (historySize /* &gt;&gt; p-&gt;skipModeBits */) + 1;
+    UInt32 hs;
+    p-&gt;matchMaxLen = matchMaxLen;
+    {
+      p-&gt;fixedHashSize = 0;
+      if (p-&gt;numHashBytes == 2)
+        hs = (1 &lt;&lt; 16) - 1;
+      else
+      {
+        hs = historySize - 1;
+        hs |= (hs &gt;&gt; 1);
+        hs |= (hs &gt;&gt; 2);
+        hs |= (hs &gt;&gt; 4);
+        hs |= (hs &gt;&gt; 8);
+        hs &gt;&gt;= 1;
+        /* hs &gt;&gt;= p-&gt;skipModeBits; */
+        hs |= 0xFFFF; /* don't change it! It's required for Deflate */
+        if (hs &gt; (1 &lt;&lt; 24))
+        {
+          if (p-&gt;numHashBytes == 3)
+            hs = (1 &lt;&lt; 24) - 1;
+          else
+            hs &gt;&gt;= 1;
+        }
+      }
+      p-&gt;hashMask = hs;
+      hs++;
+      if (p-&gt;numHashBytes &gt; 2) p-&gt;fixedHashSize += kHash2Size;
+      if (p-&gt;numHashBytes &gt; 3) p-&gt;fixedHashSize += kHash3Size;
+      if (p-&gt;numHashBytes &gt; 4) p-&gt;fixedHashSize += kHash4Size;
+      hs += p-&gt;fixedHashSize;
+    }
+
+    {
+      UInt32 prevSize = p-&gt;hashSizeSum + p-&gt;numSons;
+      UInt32 newSize;
+      p-&gt;historySize = historySize;
+      p-&gt;hashSizeSum = hs;
+      p-&gt;cyclicBufferSize = newCyclicBufferSize;
+      p-&gt;numSons = (p-&gt;btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
+      newSize = p-&gt;hashSizeSum + p-&gt;numSons;
+      if (p-&gt;hash != 0 &amp;&amp; prevSize == newSize)
+        return 1;
+      MatchFinder_FreeThisClassMemory(p, alloc);
+      p-&gt;hash = AllocRefs(newSize, alloc);
+      if (p-&gt;hash != 0)
+      {
+        p-&gt;son = p-&gt;hash + p-&gt;hashSizeSum;
+        return 1;
+      }
+    }
+  }
+  MatchFinder_Free(p, alloc);
+  return 0;
+}
+
+static void MatchFinder_SetLimits(CMatchFinder *p)
+{
+  UInt32 limit = kMaxValForNormalize - p-&gt;pos;
+  UInt32 limit2 = p-&gt;cyclicBufferSize - p-&gt;cyclicBufferPos;
+  if (limit2 &lt; limit) 
+    limit = limit2;
+  limit2 = p-&gt;streamPos - p-&gt;pos;
+  if (limit2 &lt;= p-&gt;keepSizeAfter)
+  {
+    if (limit2 &gt; 0)
+      limit2 = 1;
+  }
+  else
+    limit2 -= p-&gt;keepSizeAfter;
+  if (limit2 &lt; limit) 
+    limit = limit2;
+  {
+    UInt32 lenLimit = p-&gt;streamPos - p-&gt;pos;
+    if (lenLimit &gt; p-&gt;matchMaxLen)
+      lenLimit = p-&gt;matchMaxLen;
+    p-&gt;lenLimit = lenLimit;
+  }
+  p-&gt;posLimit = p-&gt;pos + limit;
+}
+
+void MatchFinder_Init(CMatchFinder *p)
+{
+  UInt32 i;
+  for(i = 0; i &lt; p-&gt;hashSizeSum; i++)
+    p-&gt;hash[i] = kEmptyHashValue;
+  p-&gt;cyclicBufferPos = 0;
+  p-&gt;buffer = p-&gt;bufferBase;
+  p-&gt;pos = p-&gt;streamPos = p-&gt;cyclicBufferSize;
+  p-&gt;result = SZ_OK;
+  p-&gt;streamEndWasReached = 0;
+  MatchFinder_ReadBlock(p);
+  MatchFinder_SetLimits(p);
+}
+
+static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) 
+{ 
+  return (p-&gt;pos - p-&gt;historySize - 1) &amp; kNormalizeMask; 
+}
+
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
+{
+  UInt32 i;
+  for (i = 0; i &lt; numItems; i++)
+  {
+    UInt32 value = items[i];
+    if (value &lt;= subValue)
+      value = kEmptyHashValue;
+    else
+      value -= subValue;
+    items[i] = value;
+  }
+}
+
+static void MatchFinder_Normalize(CMatchFinder *p)
+{
+  UInt32 subValue = MatchFinder_GetSubValue(p);
+  MatchFinder_Normalize3(subValue, p-&gt;hash, p-&gt;hashSizeSum + p-&gt;numSons);
+  MatchFinder_ReduceOffsets(p, subValue);
+}
+
+static void MatchFinder_CheckLimits(CMatchFinder *p)
+{
+  if (p-&gt;pos == kMaxValForNormalize)
+    MatchFinder_Normalize(p);
+  if (!p-&gt;streamEndWasReached &amp;&amp; p-&gt;keepSizeAfter == p-&gt;streamPos - p-&gt;pos)
+    MatchFinder_CheckAndMoveAndRead(p);
+  if (p-&gt;cyclicBufferPos == p-&gt;cyclicBufferSize)
+    p-&gt;cyclicBufferPos = 0;
+  MatchFinder_SetLimits(p);
+}
+
+static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, 
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, 
+    UInt32 *distances, UInt32 maxLen)
+{
+  son[_cyclicBufferPos] = curMatch;
+  for (;;)
+  {
+    UInt32 delta = pos - curMatch;
+    if (cutValue-- == 0 || delta &gt;= _cyclicBufferSize)
+      return distances;
+    {
+      const Byte *pb = cur - delta;
+      curMatch = son[_cyclicBufferPos - delta + ((delta &gt; _cyclicBufferPos) ? _cyclicBufferSize : 0)];
+      if (pb[maxLen] == cur[maxLen] &amp;&amp; *pb == *cur)
+      {
+        UInt32 len = 0;
+        while(++len != lenLimit)
+          if (pb[len] != cur[len])
+            break;
+        if (maxLen &lt; len)
+        {
+          *distances++ = maxLen = len;
+          *distances++ = delta - 1;
+          if (len == lenLimit)
+            return distances;
+        }
+      }
+    }
+  }
+}
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, 
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, 
+    UInt32 *distances, UInt32 maxLen)
+{
+  CLzRef *ptr0 = son + (_cyclicBufferPos &lt;&lt; 1) + 1;
+  CLzRef *ptr1 = son + (_cyclicBufferPos &lt;&lt; 1);
+  UInt32 len0 = 0, len1 = 0;
+  for (;;)
+  {
+    UInt32 delta = pos - curMatch;
+    if (cutValue-- == 0 || delta &gt;= _cyclicBufferSize)
+    {
+      *ptr0 = *ptr1 = kEmptyHashValue;
+      return distances;
+    }
+    {
+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta &gt; _cyclicBufferPos) ? _cyclicBufferSize : 0)) &lt;&lt; 1);
+      const Byte *pb = cur - delta;
+      UInt32 len = (len0 &lt; len1 ? len0 : len1);
+      if (pb[len] == cur[len])
+      {
+        if (++len != lenLimit &amp;&amp; pb[len] == cur[len])
+          while(++len != lenLimit)
+            if (pb[len] != cur[len])
+              break;
+        if (maxLen &lt; len)
+        {
+          *distances++ = maxLen = len;
+          *distances++ = delta - 1;
+          if (len == lenLimit)
+          {
+            *ptr1 = pair[0];
+            *ptr0 = pair[1];
+            return distances;
+          }
+        }
+      }
+      if (pb[len] &lt; cur[len])
+      {
+        *ptr1 = curMatch;
+        ptr1 = pair + 1;
+        curMatch = *ptr1;
+        len1 = len;
+      }
+      else
+      {
+        *ptr0 = curMatch;
+        ptr0 = pair;
+        curMatch = *ptr0;
+        len0 = len;
+      }
+    }
+  }
+}
+
+static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, 
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
+{
+  CLzRef *ptr0 = son + (_cyclicBufferPos &lt;&lt; 1) + 1;
+  CLzRef *ptr1 = son + (_cyclicBufferPos &lt;&lt; 1);
+  UInt32 len0 = 0, len1 = 0;
+  for (;;)
+  {
+    UInt32 delta = pos - curMatch;
+    if (cutValue-- == 0 || delta &gt;= _cyclicBufferSize)
+    {
+      *ptr0 = *ptr1 = kEmptyHashValue;
+      return;
+    }
+    {
+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta &gt; _cyclicBufferPos) ? _cyclicBufferSize : 0)) &lt;&lt; 1);
+      const Byte *pb = cur - delta;
+      UInt32 len = (len0 &lt; len1 ? len0 : len1);
+      if (pb[len] == cur[len])
+      {
+        while(++len != lenLimit)
+          if (pb[len] != cur[len])
+            break;
+        {
+          if (len == lenLimit)
+          {
+            *ptr1 = pair[0];
+            *ptr0 = pair[1];
+            return;
+          }
+        }
+      }
+      if (pb[len] &lt; cur[len])
+      {
+        *ptr1 = curMatch;
+        ptr1 = pair + 1;
+        curMatch = *ptr1;
+        len1 = len;
+      }
+      else
+      {
+        *ptr0 = curMatch;
+        ptr0 = pair;
+        curMatch = *ptr0;
+        len0 = len;
+      }
+    }
+  }
+}
+
+#define MOVE_POS \
+  ++p-&gt;cyclicBufferPos; \
+  p-&gt;buffer++; \
+  if (++p-&gt;pos == p-&gt;posLimit) MatchFinder_CheckLimits(p);
+
+#define MOVE_POS_RET MOVE_POS return offset;
+
+static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
+
+#define GET_MATCHES_HEADER2(minLen, ret_op) \
+  UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
+  lenLimit = p-&gt;lenLimit; { if (lenLimit &lt; minLen) { MatchFinder_MovePos(p); ret_op; }} \
+  cur = p-&gt;buffer;
+
+#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
+#define SKIP_HEADER(minLen)        GET_MATCHES_HEADER2(minLen, continue)
+
+#define MF_PARAMS(p) p-&gt;pos, p-&gt;buffer, p-&gt;son, p-&gt;cyclicBufferPos, p-&gt;cyclicBufferSize, p-&gt;cutValue
+
+#define GET_MATCHES_FOOTER(offset, maxLen) \
+  offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
+  distances + offset, maxLen) - distances); MOVE_POS_RET;
+
+#define SKIP_FOOTER \
+  SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
+
+static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 offset;
+  GET_MATCHES_HEADER(2)
+  HASH2_CALC;
+  curMatch = p-&gt;hash[hashValue];
+  p-&gt;hash[hashValue] = p-&gt;pos;
+  offset = 0;
+  GET_MATCHES_FOOTER(offset, 1)
+}
+
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 offset;
+  GET_MATCHES_HEADER(3)
+  HASH_ZIP_CALC;
+  curMatch = p-&gt;hash[hashValue];
+  p-&gt;hash[hashValue] = p-&gt;pos;
+  offset = 0;
+  GET_MATCHES_FOOTER(offset, 2)
+}
+
+static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 hash2Value, delta2, maxLen, offset;
+  GET_MATCHES_HEADER(3)
+
+  HASH3_CALC;
+
+  delta2 = p-&gt;pos - p-&gt;hash[hash2Value];
+  curMatch = p-&gt;hash[kFix3HashSize + hashValue];
+  
+  p-&gt;hash[hash2Value] = 
+  p-&gt;hash[kFix3HashSize + hashValue] = p-&gt;pos;
+
+
+  maxLen = 2;
+  offset = 0;
+  if (delta2 &lt; p-&gt;cyclicBufferSize &amp;&amp; *(cur - delta2) == *cur)
+  {
+    for (; maxLen != lenLimit; maxLen++)
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+        break;
+    distances[0] = maxLen;
+    distances[1] = delta2 - 1;
+    offset = 2;
+    if (maxLen == lenLimit)
+    {
+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+      MOVE_POS_RET; 
+    }
+  }
+  GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+  GET_MATCHES_HEADER(4)
+
+  HASH4_CALC;
+
+  delta2 = p-&gt;pos - p-&gt;hash[                hash2Value];
+  delta3 = p-&gt;pos - p-&gt;hash[kFix3HashSize + hash3Value];
+  curMatch = p-&gt;hash[kFix4HashSize + hashValue];
+  
+  p-&gt;hash[                hash2Value] =
+  p-&gt;hash[kFix3HashSize + hash3Value] =
+  p-&gt;hash[kFix4HashSize + hashValue] = p-&gt;pos;
+
+  maxLen = 1;
+  offset = 0;
+  if (delta2 &lt; p-&gt;cyclicBufferSize &amp;&amp; *(cur - delta2) == *cur)
+  {
+    distances[0] = maxLen = 2;
+    distances[1] = delta2 - 1;
+    offset = 2;
+  }
+  if (delta2 != delta3 &amp;&amp; delta3 &lt; p-&gt;cyclicBufferSize &amp;&amp; *(cur - delta3) == *cur)
+  {
+    maxLen = 3;
+    distances[offset + 1] = delta3 - 1;
+    offset += 2;
+    delta2 = delta3;
+  }
+  if (offset != 0)
+  {
+    for (; maxLen != lenLimit; maxLen++)
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+        break;
+    distances[offset - 2] = maxLen;
+    if (maxLen == lenLimit)
+    {
+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+      MOVE_POS_RET; 
+    }
+  }
+  if (maxLen &lt; 3)
+    maxLen = 3;
+  GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+  GET_MATCHES_HEADER(4)
+
+  HASH4_CALC;
+
+  delta2 = p-&gt;pos - p-&gt;hash[                hash2Value];
+  delta3 = p-&gt;pos - p-&gt;hash[kFix3HashSize + hash3Value];
+  curMatch = p-&gt;hash[kFix4HashSize + hashValue];
+
+  p-&gt;hash[                hash2Value] =
+  p-&gt;hash[kFix3HashSize + hash3Value] =
+  p-&gt;hash[kFix4HashSize + hashValue] = p-&gt;pos;
+
+  maxLen = 1;
+  offset = 0;
+  if (delta2 &lt; p-&gt;cyclicBufferSize &amp;&amp; *(cur - delta2) == *cur)
+  {
+    distances[0] = maxLen = 2;
+    distances[1] = delta2 - 1;
+    offset = 2;
+  }
+  if (delta2 != delta3 &amp;&amp; delta3 &lt; p-&gt;cyclicBufferSize &amp;&amp; *(cur - delta3) == *cur)
+  {
+    maxLen = 3;
+    distances[offset + 1] = delta3 - 1;
+    offset += 2;
+    delta2 = delta3;
+  }
+  if (offset != 0)
+  {
+    for (; maxLen != lenLimit; maxLen++)
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+        break;
+    distances[offset - 2] = maxLen;
+    if (maxLen == lenLimit)
+    {
+      p-&gt;son[p-&gt;cyclicBufferPos] = curMatch;
+      MOVE_POS_RET; 
+    }
+  }
+  if (maxLen &lt; 3)
+    maxLen = 3;
+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+    distances + offset, maxLen) - (distances));
+  MOVE_POS_RET
+}
+
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 offset;
+  GET_MATCHES_HEADER(3)
+  HASH_ZIP_CALC;
+  curMatch = p-&gt;hash[hashValue];
+  p-&gt;hash[hashValue] = p-&gt;pos;
+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+    distances, 2) - (distances));
+  MOVE_POS_RET
+}
+
+static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    SKIP_HEADER(2) 
+    HASH2_CALC;
+    curMatch = p-&gt;hash[hashValue];
+    p-&gt;hash[hashValue] = p-&gt;pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    SKIP_HEADER(3)
+    HASH_ZIP_CALC;
+    curMatch = p-&gt;hash[hashValue];
+    p-&gt;hash[hashValue] = p-&gt;pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    UInt32 hash2Value;
+    SKIP_HEADER(3)
+    HASH3_CALC;
+    curMatch = p-&gt;hash[kFix3HashSize + hashValue];
+    p-&gt;hash[hash2Value] =
+    p-&gt;hash[kFix3HashSize + hashValue] = p-&gt;pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    UInt32 hash2Value, hash3Value;
+    SKIP_HEADER(4) 
+    HASH4_CALC;
+    curMatch = p-&gt;hash[kFix4HashSize + hashValue];
+    p-&gt;hash[                hash2Value] =
+    p-&gt;hash[kFix3HashSize + hash3Value] = p-&gt;pos;
+    p-&gt;hash[kFix4HashSize + hashValue] = p-&gt;pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    UInt32 hash2Value, hash3Value;
+    SKIP_HEADER(4)
+    HASH4_CALC;
+    curMatch = p-&gt;hash[kFix4HashSize + hashValue];
+    p-&gt;hash[                hash2Value] =
+    p-&gt;hash[kFix3HashSize + hash3Value] =
+    p-&gt;hash[kFix4HashSize + hashValue] = p-&gt;pos;
+    p-&gt;son[p-&gt;cyclicBufferPos] = curMatch;
+    MOVE_POS
+  }
+  while (--num != 0);
+}
+
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    SKIP_HEADER(3)
+    HASH_ZIP_CALC;
+    curMatch = p-&gt;hash[hashValue];
+    p-&gt;hash[hashValue] = p-&gt;pos;
+    p-&gt;son[p-&gt;cyclicBufferPos] = curMatch;
+    MOVE_POS
+  }
+  while (--num != 0);
+}
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
+{
+  vTable-&gt;Init = (Mf_Init_Func)MatchFinder_Init;
+  vTable-&gt;GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
+  vTable-&gt;GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
+  vTable-&gt;GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
+  if (!p-&gt;btMode)
+  {
+    vTable-&gt;GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
+    vTable-&gt;Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
+  }
+  else if (p-&gt;numHashBytes == 2)
+  {
+    vTable-&gt;GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
+    vTable-&gt;Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
+  }
+  else if (p-&gt;numHashBytes == 3)
+  {
+    vTable-&gt;GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
+    vTable-&gt;Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
+  }
+  else
+  {
+    vTable-&gt;GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
+    vTable-&gt;Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
+  }
+}
--- /dev/null
+++ b/jffsX-utils/lzma/LzmaDec.c
@@ -0,0 +1,1014 @@
+/* LzmaDec.c -- LZMA Decoder
+2008-04-29
+Copyright (c) 1999-2008 Igor Pavlov
+Read LzmaDec.h for license options */
+
+#include "LzmaDec.h"
+
+#include &lt;string.h&gt;
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 &lt;&lt; kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 &lt;&lt; kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_INIT_SIZE 5
+
+#define NORMALIZE if (range &lt; kTopValue) { range &lt;&lt;= 8; code = (code &lt;&lt; 8) | (*buf++); }
+
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range &gt;&gt; kNumBitModelTotalBits) * ttt; if (code &lt; bound)
+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) &gt;&gt; kNumMoveBits));
+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt &gt;&gt; kNumMoveBits));
+#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
+  { UPDATE_0(p); i = (i + i); A0; } else \
+  { UPDATE_1(p); i = (i + i) + 1; A1; } 
+#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)               
+
+#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
+#define TREE_DECODE(probs, limit, i) \
+  { i = 1; do { TREE_GET_BIT(probs, i); } while (i &lt; limit); i -= limit; }
+
+/* #define _LZMA_SIZE_OPT */
+
+#ifdef _LZMA_SIZE_OPT
+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 &lt;&lt; 6), i)
+#else
+#define TREE_6_DECODE(probs, i) \
+  { i = 1; \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  i -= 0x40; }
+#endif
+
+#define NORMALIZE_CHECK if (range &lt; kTopValue) { if (buf &gt;= bufLimit) return DUMMY_ERROR; range &lt;&lt;= 8; code = (code &lt;&lt; 8) | (*buf++); }
+
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range &gt;&gt; kNumBitModelTotalBits) * ttt; if (code &lt; bound)
+#define UPDATE_0_CHECK range = bound;
+#define UPDATE_1_CHECK range -= bound; code -= bound;
+#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
+  { UPDATE_0_CHECK; i = (i + i); A0; } else \
+  { UPDATE_1_CHECK; i = (i + i) + 1; A1; } 
+#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)               
+#define TREE_DECODE_CHECK(probs, limit, i) \
+  { i = 1; do { GET_BIT_CHECK(probs + i, i) } while(i &lt; limit); i -= limit; }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 &lt;&lt; kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 &lt;&lt; kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 &lt;&lt; kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 &lt;&lt; kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax &lt;&lt; kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax &lt;&lt; kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols) 
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 &lt;&lt; (kEndPosModelIndex &gt;&gt; 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 &lt;&lt; kNumAlignBits)
+
+#define kMatchMinLen 2
+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates &lt;&lt; kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates &lt;&lt; kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates &lt;&lt; kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE &lt;&lt; ((p)-&gt;lc + (p)-&gt;lp)))
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+/*
+#define LZMA_STREAM_WAS_FINISHED_ID (-1)
+#define LZMA_SPEC_LEN_OFFSET (-3)
+*/
+
+Byte kLiteralNextStates[kNumStates * 2] = 
+{
+  0, 0, 0, 0, 1, 2, 3,  4,  5,  6,  4,  5, 
+  7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
+};
+
+#define LZMA_DIC_MIN (1 &lt;&lt; 12)
+
+/* First LZMA-symbol is always decoded. 
+And it decodes new LZMA-symbols while (buf &lt; bufLimit), but "buf" is without last normalization 
+Out:
+  Result:
+    0 - OK
+    1 - Error
+  p-&gt;remainLen:
+    &lt; kMatchSpecLenStart : normal remain
+    = kMatchSpecLenStart : finished
+    = kMatchSpecLenStart + 1 : Flush marker
+    = kMatchSpecLenStart + 2 : State Init Marker
+*/
+
+static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+  CLzmaProb *probs = p-&gt;probs;
+
+  unsigned state = p-&gt;state;
+  UInt32 rep0 = p-&gt;reps[0], rep1 = p-&gt;reps[1], rep2 = p-&gt;reps[2], rep3 = p-&gt;reps[3];
+  unsigned pbMask = ((unsigned)1 &lt;&lt; (p-&gt;prop.pb)) - 1;
+  unsigned lpMask = ((unsigned)1 &lt;&lt; (p-&gt;prop.lp)) - 1;
+  unsigned lc = p-&gt;prop.lc;
+
+  Byte *dic = p-&gt;dic;
+  SizeT dicBufSize = p-&gt;dicBufSize;
+  SizeT dicPos = p-&gt;dicPos;
+  
+  UInt32 processedPos = p-&gt;processedPos;
+  UInt32 checkDicSize = p-&gt;checkDicSize;
+  unsigned len = 0;
+
+  const Byte *buf = p-&gt;buf;
+  UInt32 range = p-&gt;range;
+  UInt32 code = p-&gt;code;
+
+  do
+  {
+    CLzmaProb *prob;
+    UInt32 bound;
+    unsigned ttt;
+    unsigned posState = processedPos &amp; pbMask;
+
+    prob = probs + IsMatch + (state &lt;&lt; kNumPosBitsMax) + posState;
+    IF_BIT_0(prob)
+    {
+      unsigned symbol;
+      UPDATE_0(prob);
+      prob = probs + Literal;
+      if (checkDicSize != 0 || processedPos != 0)
+        prob += (LZMA_LIT_SIZE * (((processedPos &amp; lpMask) &lt;&lt; lc) + 
+        (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] &gt;&gt; (8 - lc))));
+
+      if (state &lt; kNumLitStates)
+      {
+        symbol = 1;
+        do { GET_BIT(prob + symbol, symbol) } while (symbol &lt; 0x100);
+      }
+      else
+      {
+        unsigned matchByte = p-&gt;dic[(dicPos - rep0) + ((dicPos &lt; rep0) ? dicBufSize : 0)];
+        unsigned offs = 0x100;
+        symbol = 1;
+        do
+        {
+          unsigned bit;
+          CLzmaProb *probLit;
+          matchByte &lt;&lt;= 1;
+          bit = (matchByte &amp; offs);
+          probLit = prob + offs + bit + symbol;
+          GET_BIT2(probLit, symbol, offs &amp;= ~bit, offs &amp;= bit)
+        }
+        while (symbol &lt; 0x100);
+      }
+      dic[dicPos++] = (Byte)symbol;
+      processedPos++;
+
+      state = kLiteralNextStates[state];
+      /* if (state &lt; 4) state = 0; else if (state &lt; 10) state -= 3; else state -= 6; */
+      continue;
+    }
+    else             
+    {
+      UPDATE_1(prob);
+      prob = probs + IsRep + state;
+      IF_BIT_0(prob)
+      {
+        UPDATE_0(prob);
+        state += kNumStates;
+        prob = probs + LenCoder;
+      }
+      else
+      {
+        UPDATE_1(prob);
+        if (checkDicSize == 0 &amp;&amp; processedPos == 0)
+          return SZ_ERROR_DATA;
+        prob = probs + IsRepG0 + state;
+        IF_BIT_0(prob)
+        {
+          UPDATE_0(prob);
+          prob = probs + IsRep0Long + (state &lt;&lt; kNumPosBitsMax) + posState;
+          IF_BIT_0(prob)
+          {
+            UPDATE_0(prob);
+            dic[dicPos] = dic[(dicPos - rep0) + ((dicPos &lt; rep0) ? dicBufSize : 0)];
+            dicPos++;
+            processedPos++;
+            state = state &lt; kNumLitStates ? 9 : 11;
+            continue;
+          }
+          UPDATE_1(prob);
+        }
+        else
+        {
+          UInt32 distance;
+          UPDATE_1(prob);
+          prob = probs + IsRepG1 + state;
+          IF_BIT_0(prob)
+          {
+            UPDATE_0(prob);
+            distance = rep1;
+          }
+          else 
+          {
+            UPDATE_1(prob);
+            prob = probs + IsRepG2 + state;
+            IF_BIT_0(prob)
+            {
+              UPDATE_0(prob);
+              distance = rep2;
+            }
+            else
+            {
+              UPDATE_1(prob);
+              distance = rep3;
+              rep3 = rep2;
+            }
+            rep2 = rep1;
+          }
+          rep1 = rep0;
+          rep0 = distance;
+        }
+        state = state &lt; kNumLitStates ? 8 : 11;
+        prob = probs + RepLenCoder;
+      }
+      {
+        unsigned limit, offset;
+        CLzmaProb *probLen = prob + LenChoice;
+        IF_BIT_0(probLen)
+        {
+          UPDATE_0(probLen);
+          probLen = prob + LenLow + (posState &lt;&lt; kLenNumLowBits);
+          offset = 0;
+          limit = (1 &lt;&lt; kLenNumLowBits);
+        }
+        else
+        {
+          UPDATE_1(probLen);
+          probLen = prob + LenChoice2;
+          IF_BIT_0(probLen)
+          {
+            UPDATE_0(probLen);
+            probLen = prob + LenMid + (posState &lt;&lt; kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            limit = (1 &lt;&lt; kLenNumMidBits);
+          }
+          else
+          {
+            UPDATE_1(probLen);
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            limit = (1 &lt;&lt; kLenNumHighBits);
+          }
+        }
+        TREE_DECODE(probLen, limit, len);
+        len += offset;
+      }
+
+      if (state &gt;= kNumStates)
+      {
+        UInt32 distance;
+        prob = probs + PosSlot +
+            ((len &lt; kNumLenToPosStates ? len : kNumLenToPosStates - 1) &lt;&lt; kNumPosSlotBits);
+        TREE_6_DECODE(prob, distance);
+        if (distance &gt;= kStartPosModelIndex)
+        {
+          unsigned posSlot = (unsigned)distance; 
+          int numDirectBits = (int)(((distance &gt;&gt; 1) - 1));
+          distance = (2 | (distance &amp; 1));
+          if (posSlot &lt; kEndPosModelIndex)
+          {
+            distance &lt;&lt;= numDirectBits;
+            prob = probs + SpecPos + distance - posSlot - 1;
+            {
+              UInt32 mask = 1;
+              unsigned i = 1;
+              do
+              {
+                GET_BIT2(prob + i, i, ; , distance |= mask);
+                mask &lt;&lt;= 1;
+              }
+              while(--numDirectBits != 0);
+            }
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              NORMALIZE
+              range &gt;&gt;= 1;
+              
+              {
+                UInt32 t;
+                code -= range;
+                t = (0 - ((UInt32)code &gt;&gt; 31)); /* (UInt32)((Int32)code &gt;&gt; 31) */
+                distance = (distance &lt;&lt; 1) + (t + 1);
+                code += range &amp; t;
+              }
+              /*
+              distance &lt;&lt;= 1;
+              if (code &gt;= range)
+              {
+                code -= range;
+                distance |= 1;
+              }
+              */
+            }
+            while (--numDirectBits != 0);
+            prob = probs + Align;
+            distance &lt;&lt;= kNumAlignBits;
+            {
+              unsigned i = 1;
+              GET_BIT2(prob + i, i, ; , distance |= 1);
+              GET_BIT2(prob + i, i, ; , distance |= 2);
+              GET_BIT2(prob + i, i, ; , distance |= 4);
+              GET_BIT2(prob + i, i, ; , distance |= 8);
+            }
+            if (distance == (UInt32)0xFFFFFFFF)
+            {
+              len += kMatchSpecLenStart;
+              state -= kNumStates;
+              break;
+            }
+          }
+        }
+        rep3 = rep2;
+        rep2 = rep1;
+        rep1 = rep0;
+        rep0 = distance + 1; 
+        if (checkDicSize == 0)
+        {
+          if (distance &gt;= processedPos)
+            return SZ_ERROR_DATA;
+        }
+        else if (distance &gt;= checkDicSize)
+          return SZ_ERROR_DATA;
+        state = (state &lt; kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
+        /* state = kLiteralNextStates[state]; */
+      }
+
+      len += kMatchMinLen;
+
+      {
+        SizeT rem = limit - dicPos;
+        unsigned curLen = ((rem &lt; len) ? (unsigned)rem : len);
+        SizeT pos = (dicPos - rep0) + ((dicPos &lt; rep0) ? dicBufSize : 0);
+
+        processedPos += curLen;
+
+        len -= curLen;
+        if (pos + curLen &lt;= dicBufSize)
+        {
+          Byte *dest = dic + dicPos;
+          ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
+          const Byte *lim = dest + curLen;
+          dicPos += curLen;
+          do 
+            *(dest) = (Byte)*(dest + src); 
+          while (++dest != lim);
+        }
+        else
+        {
+          do
+          {
+            dic[dicPos++] = dic[pos];
+            if (++pos == dicBufSize)
+              pos = 0;
+          }
+          while (--curLen != 0);
+        }
+      }
+    }
+  }
+  while (dicPos &lt; limit &amp;&amp; buf &lt; bufLimit);
+  NORMALIZE;
+  p-&gt;buf = buf;
+  p-&gt;range = range;
+  p-&gt;code = code;
+  p-&gt;remainLen = len;
+  p-&gt;dicPos = dicPos;
+  p-&gt;processedPos = processedPos;
+  p-&gt;reps[0] = rep0;
+  p-&gt;reps[1] = rep1;
+  p-&gt;reps[2] = rep2;
+  p-&gt;reps[3] = rep3;
+  p-&gt;state = state;
+
+  return SZ_OK;
+}
+
+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
+{
+  if (p-&gt;remainLen != 0 &amp;&amp; p-&gt;remainLen &lt; kMatchSpecLenStart)
+  {
+    Byte *dic = p-&gt;dic;
+    SizeT dicPos = p-&gt;dicPos;
+    SizeT dicBufSize = p-&gt;dicBufSize;
+    unsigned len = p-&gt;remainLen;
+    UInt32 rep0 = p-&gt;reps[0];
+    if (limit - dicPos &lt; len)
+      len = (unsigned)(limit - dicPos);
+
+    if (p-&gt;checkDicSize == 0 &amp;&amp; p-&gt;prop.dicSize - p-&gt;processedPos &lt;= len)
+      p-&gt;checkDicSize = p-&gt;prop.dicSize;
+
+    p-&gt;processedPos += len;
+    p-&gt;remainLen -= len;
+    while (len-- != 0)
+    {
+      dic[dicPos] = dic[(dicPos - rep0) + ((dicPos &lt; rep0) ? dicBufSize : 0)];
+      dicPos++;
+    }
+    p-&gt;dicPos = dicPos;
+  }
+}
+
+/* LzmaDec_DecodeReal2 decodes LZMA-symbols and sets p-&gt;needFlush and p-&gt;needInit, if required. */
+
+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+  do
+  {
+    SizeT limit2 = limit;
+    if (p-&gt;checkDicSize == 0)
+    {
+      UInt32 rem = p-&gt;prop.dicSize - p-&gt;processedPos;
+      if (limit - p-&gt;dicPos &gt; rem)
+        limit2 = p-&gt;dicPos + rem;
+    }
+    RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
+    if (p-&gt;processedPos &gt;= p-&gt;prop.dicSize)
+      p-&gt;checkDicSize = p-&gt;prop.dicSize;
+    LzmaDec_WriteRem(p, limit);
+  }
+  while (p-&gt;dicPos &lt; limit &amp;&amp; p-&gt;buf &lt; bufLimit &amp;&amp; p-&gt;remainLen &lt; kMatchSpecLenStart);
+
+  if (p-&gt;remainLen &gt; kMatchSpecLenStart)
+  {
+    p-&gt;remainLen = kMatchSpecLenStart;
+  }
+  return 0;
+}
+
+typedef enum 
+{
+  DUMMY_ERROR, /* unexpected end of input stream */
+  DUMMY_LIT,
+  DUMMY_MATCH,
+  DUMMY_REP
+} ELzmaDummy;
+
+static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
+{
+  UInt32 range = p-&gt;range;
+  UInt32 code = p-&gt;code;
+  const Byte *bufLimit = buf + inSize;
+  CLzmaProb *probs = p-&gt;probs;
+  unsigned state = p-&gt;state;
+  ELzmaDummy res;
+
+  {
+    CLzmaProb *prob;
+    UInt32 bound;
+    unsigned ttt;
+    unsigned posState = (p-&gt;processedPos) &amp; ((1 &lt;&lt; p-&gt;prop.pb) - 1);
+
+    prob = probs + IsMatch + (state &lt;&lt; kNumPosBitsMax) + posState;
+    IF_BIT_0_CHECK(prob)
+    {
+      UPDATE_0_CHECK
+
+      /* if (bufLimit - buf &gt;= 7) return DUMMY_LIT; */
+
+      prob = probs + Literal;
+      if (p-&gt;checkDicSize != 0 || p-&gt;processedPos != 0)
+        prob += (LZMA_LIT_SIZE * 
+          ((((p-&gt;processedPos) &amp; ((1 &lt;&lt; (p-&gt;prop.lp)) - 1)) &lt;&lt; p-&gt;prop.lc) + 
+          (p-&gt;dic[(p-&gt;dicPos == 0 ? p-&gt;dicBufSize : p-&gt;dicPos) - 1] &gt;&gt; (8 - p-&gt;prop.lc))));
+
+      if (state &lt; kNumLitStates)
+      {
+        unsigned symbol = 1;
+        do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol &lt; 0x100);
+      }
+      else
+      {
+        unsigned matchByte = p-&gt;dic[p-&gt;dicPos - p-&gt;reps[0] + 
+            ((p-&gt;dicPos &lt; p-&gt;reps[0]) ? p-&gt;dicBufSize : 0)];
+        unsigned offs = 0x100;
+        unsigned symbol = 1;
+        do
+        {
+          unsigned bit;
+          CLzmaProb *probLit;
+          matchByte &lt;&lt;= 1;
+          bit = (matchByte &amp; offs);
+          probLit = prob + offs + bit + symbol;
+          GET_BIT2_CHECK(probLit, symbol, offs &amp;= ~bit, offs &amp;= bit)
+        }
+        while (symbol &lt; 0x100);
+      }
+      res = DUMMY_LIT;
+    }
+    else             
+    {
+      unsigned len;
+      UPDATE_1_CHECK;
+
+      prob = probs + IsRep + state;
+      IF_BIT_0_CHECK(prob)
+      {
+        UPDATE_0_CHECK;
+        state = 0;
+        prob = probs + LenCoder;
+        res = DUMMY_MATCH;
+      }
+      else
+      {
+        UPDATE_1_CHECK;
+        res = DUMMY_REP;
+        prob = probs + IsRepG0 + state;
+        IF_BIT_0_CHECK(prob)
+        {
+          UPDATE_0_CHECK;
+          prob = probs + IsRep0Long + (state &lt;&lt; kNumPosBitsMax) + posState;
+          IF_BIT_0_CHECK(prob)
+          {
+            UPDATE_0_CHECK;
+            NORMALIZE_CHECK;
+            return DUMMY_REP;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+          }
+        }
+        else
+        {
+          UPDATE_1_CHECK;
+          prob = probs + IsRepG1 + state;
+          IF_BIT_0_CHECK(prob)
+          {
+            UPDATE_0_CHECK;
+          }
+          else 
+          {
+            UPDATE_1_CHECK;
+            prob = probs + IsRepG2 + state;
+            IF_BIT_0_CHECK(prob)
+            {
+              UPDATE_0_CHECK;
+            }
+            else
+            {
+              UPDATE_1_CHECK;
+            }
+          }
+        }
+        state = kNumStates;
+        prob = probs + RepLenCoder;
+      }
+      {
+        unsigned limit, offset;
+        CLzmaProb *probLen = prob + LenChoice;
+        IF_BIT_0_CHECK(probLen)
+        {
+          UPDATE_0_CHECK;
+          probLen = prob + LenLow + (posState &lt;&lt; kLenNumLowBits);
+          offset = 0;
+          limit = 1 &lt;&lt; kLenNumLowBits;
+        }
+        else
+        {
+          UPDATE_1_CHECK;
+          probLen = prob + LenChoice2;
+          IF_BIT_0_CHECK(probLen)
+          {
+            UPDATE_0_CHECK;
+            probLen = prob + LenMid + (posState &lt;&lt; kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            limit = 1 &lt;&lt; kLenNumMidBits;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            limit = 1 &lt;&lt; kLenNumHighBits;
+          }
+        }
+        TREE_DECODE_CHECK(probLen, limit, len);
+        len += offset;
+      }
+
+      if (state &lt; 4)
+      {
+        unsigned posSlot;
+        prob = probs + PosSlot +
+            ((len &lt; kNumLenToPosStates ? len : kNumLenToPosStates - 1) &lt;&lt; 
+            kNumPosSlotBits);
+        TREE_DECODE_CHECK(prob, 1 &lt;&lt; kNumPosSlotBits, posSlot);
+        if (posSlot &gt;= kStartPosModelIndex)
+        {
+          int numDirectBits = ((posSlot &gt;&gt; 1) - 1);
+
+          /* if (bufLimit - buf &gt;= 8) return DUMMY_MATCH; */
+
+          if (posSlot &lt; kEndPosModelIndex)
+          {
+            prob = probs + SpecPos + ((2 | (posSlot &amp; 1)) &lt;&lt; numDirectBits) - posSlot - 1;
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              NORMALIZE_CHECK
+              range &gt;&gt;= 1;
+              code -= range &amp; (((code - range) &gt;&gt; 31) - 1);
+              /* if (code &gt;= range) code -= range; */
+            }
+            while (--numDirectBits != 0);
+            prob = probs + Align;
+            numDirectBits = kNumAlignBits;
+          }
+          {
+            unsigned i = 1;
+            do
+            {
+              GET_BIT_CHECK(prob + i, i);
+            }
+            while(--numDirectBits != 0);
+          }
+        }
+      }
+    }
+  }
+  NORMALIZE_CHECK;
+  return res;
+}
+
+
+static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
+{
+  p-&gt;code = ((UInt32)data[1] &lt;&lt; 24) | ((UInt32)data[2] &lt;&lt; 16) | ((UInt32)data[3] &lt;&lt; 8) | ((UInt32)data[4]);
+  p-&gt;range = 0xFFFFFFFF;
+  p-&gt;needFlush = 0;
+}
+
+static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) 
+{ 
+  p-&gt;needFlush = 1; 
+  p-&gt;remainLen = 0; 
+  p-&gt;tempBufSize = 0; 
+
+  if (initDic)
+  {
+    p-&gt;processedPos = 0;
+    p-&gt;checkDicSize = 0;
+    p-&gt;needInitState = 1;
+  }
+  if (initState)
+    p-&gt;needInitState = 1;
+}
+
+void LzmaDec_Init(CLzmaDec *p) 
+{ 
+  p-&gt;dicPos = 0; 
+  LzmaDec_InitDicAndState(p, True, True);
+}
+
+static void LzmaDec_InitStateReal(CLzmaDec *p)
+{
+  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE &lt;&lt; (p-&gt;prop.lc + p-&gt;prop.lp));
+  UInt32 i;
+  CLzmaProb *probs = p-&gt;probs;
+  for (i = 0; i &lt; numProbs; i++)
+    probs[i] = kBitModelTotal &gt;&gt; 1; 
+  p-&gt;reps[0] = p-&gt;reps[1] = p-&gt;reps[2] = p-&gt;reps[3] = 1;
+  p-&gt;state = 0;
+  p-&gt;needInitState = 0;
+}
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, 
+    ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+  SizeT inSize = *srcLen;
+  (*srcLen) = 0;
+  LzmaDec_WriteRem(p, dicLimit);
+  
+  *status = LZMA_STATUS_NOT_SPECIFIED;
+
+  while (p-&gt;remainLen != kMatchSpecLenStart)
+  {
+      int checkEndMarkNow;
+
+      if (p-&gt;needFlush != 0)
+      {
+        for (; inSize &gt; 0 &amp;&amp; p-&gt;tempBufSize &lt; RC_INIT_SIZE; (*srcLen)++, inSize--)
+          p-&gt;tempBuf[p-&gt;tempBufSize++] = *src++;
+        if (p-&gt;tempBufSize &lt; RC_INIT_SIZE)
+        {
+          *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+          return SZ_OK;
+        }
+        if (p-&gt;tempBuf[0] != 0)
+          return SZ_ERROR_DATA;
+
+        LzmaDec_InitRc(p, p-&gt;tempBuf);
+        p-&gt;tempBufSize = 0;
+      }
+
+      checkEndMarkNow = 0;
+      if (p-&gt;dicPos &gt;= dicLimit)
+      {
+        if (p-&gt;remainLen == 0 &amp;&amp; p-&gt;code == 0)
+        {
+          *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
+          return SZ_OK;
+        }
+        if (finishMode == LZMA_FINISH_ANY)
+        {
+          *status = LZMA_STATUS_NOT_FINISHED;
+          return SZ_OK;
+        }
+        if (p-&gt;remainLen != 0)
+        {
+          *status = LZMA_STATUS_NOT_FINISHED;
+          return SZ_ERROR_DATA;
+        }
+        checkEndMarkNow = 1;
+      }
+
+      if (p-&gt;needInitState)
+        LzmaDec_InitStateReal(p);
+  
+      if (p-&gt;tempBufSize == 0)
+      {
+        SizeT processed;
+        const Byte *bufLimit;
+        if (inSize &lt; LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+        {
+          int dummyRes = LzmaDec_TryDummy(p, src, inSize);
+          if (dummyRes == DUMMY_ERROR)
+          {
+            memcpy(p-&gt;tempBuf, src, inSize);
+            p-&gt;tempBufSize = (unsigned)inSize;
+            (*srcLen) += inSize;
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+            return SZ_OK;
+          }
+          if (checkEndMarkNow &amp;&amp; dummyRes != DUMMY_MATCH)
+          {
+            *status = LZMA_STATUS_NOT_FINISHED;
+            return SZ_ERROR_DATA;
+          }
+          bufLimit = src;
+        }
+        else
+          bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
+        p-&gt;buf = src;
+        if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
+          return SZ_ERROR_DATA;
+        processed = p-&gt;buf - src;
+        (*srcLen) += processed;
+        src += processed;
+        inSize -= processed;
+      }
+      else
+      {
+        unsigned rem = p-&gt;tempBufSize, lookAhead = 0;
+        while (rem &lt; LZMA_REQUIRED_INPUT_MAX &amp;&amp; lookAhead &lt; inSize)
+          p-&gt;tempBuf[rem++] = src[lookAhead++];
+        p-&gt;tempBufSize = rem;
+        if (rem &lt; LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+        {
+          int dummyRes = LzmaDec_TryDummy(p, p-&gt;tempBuf, rem);
+          if (dummyRes == DUMMY_ERROR)
+          {
+            (*srcLen) += lookAhead;
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+            return SZ_OK;
+          }
+          if (checkEndMarkNow &amp;&amp; dummyRes != DUMMY_MATCH)
+          {
+            *status = LZMA_STATUS_NOT_FINISHED;
+            return SZ_ERROR_DATA;
+          }
+        }
+        p-&gt;buf = p-&gt;tempBuf;
+        if (LzmaDec_DecodeReal2(p, dicLimit, p-&gt;buf) != 0)
+          return SZ_ERROR_DATA;
+        lookAhead -= (rem - (unsigned)(p-&gt;buf - p-&gt;tempBuf));
+        (*srcLen) += lookAhead;
+        src += lookAhead;
+        inSize -= lookAhead;
+        p-&gt;tempBufSize = 0;
+      }
+  }
+  if (p-&gt;code == 0) 
+    *status = LZMA_STATUS_FINISHED_WITH_MARK;
+  return (p-&gt;code == 0) ? SZ_OK : SZ_ERROR_DATA;
+}
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+  SizeT outSize = *destLen;
+  SizeT inSize = *srcLen;
+  *srcLen = *destLen = 0;
+  for (;;)
+  {
+    SizeT inSizeCur = inSize, outSizeCur, dicPos;
+    ELzmaFinishMode curFinishMode;
+    SRes res;
+    if (p-&gt;dicPos == p-&gt;dicBufSize)
+      p-&gt;dicPos = 0;
+    dicPos = p-&gt;dicPos;
+    if (outSize &gt; p-&gt;dicBufSize - dicPos)
+    {
+      outSizeCur = p-&gt;dicBufSize;
+      curFinishMode = LZMA_FINISH_ANY;
+    }
+    else
+    {
+      outSizeCur = dicPos + outSize;
+      curFinishMode = finishMode;
+    }
+
+    res = LzmaDec_DecodeToDic(p, outSizeCur, src, &amp;inSizeCur, curFinishMode, status);
+    src += inSizeCur;
+    inSize -= inSizeCur;
+    *srcLen += inSizeCur;
+    outSizeCur = p-&gt;dicPos - dicPos;
+    memcpy(dest, p-&gt;dic + dicPos, outSizeCur);
+    dest += outSizeCur;
+    outSize -= outSizeCur;
+    *destLen += outSizeCur;
+    if (res != 0)
+      return res;
+    if (outSizeCur == 0 || outSize == 0)
+      return SZ_OK;
+  }
+}
+
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) 
+{ 
+  alloc-&gt;Free(alloc, p-&gt;probs);  
+  p-&gt;probs = 0; 
+}
+
+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) 
+{ 
+  alloc-&gt;Free(alloc, p-&gt;dic); 
+  p-&gt;dic = 0; 
+}
+
+void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
+{
+  LzmaDec_FreeProbs(p, alloc);
+  LzmaDec_FreeDict(p, alloc);
+}
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
+{
+  UInt32 dicSize; 
+  Byte d;
+  
+  if (size &lt; LZMA_PROPS_SIZE)
+    return SZ_ERROR_UNSUPPORTED;
+  else
+    dicSize = data[1] | ((UInt32)data[2] &lt;&lt; 8) | ((UInt32)data[3] &lt;&lt; 16) | ((UInt32)data[4] &lt;&lt; 24);
+ 
+  if (dicSize &lt; LZMA_DIC_MIN)
+    dicSize = LZMA_DIC_MIN;
+  p-&gt;dicSize = dicSize;
+
+  d = data[0];
+  if (d &gt;= (9 * 5 * 5))
+    return SZ_ERROR_UNSUPPORTED;
+
+  p-&gt;lc = d % 9;
+  d /= 9;
+  p-&gt;pb = d / 5;
+  p-&gt;lp = d % 5;
+
+  return SZ_OK;
+}
+
+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
+{
+  UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
+  if (p-&gt;probs == 0 || numProbs != p-&gt;numProbs)
+  {
+    LzmaDec_FreeProbs(p, alloc);
+    p-&gt;probs = (CLzmaProb *)alloc-&gt;Alloc(alloc, numProbs * sizeof(CLzmaProb));
+    p-&gt;numProbs = numProbs;
+    if (p-&gt;probs == 0)
+      return SZ_ERROR_MEM;
+  }
+  return SZ_OK;
+}
+
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+  CLzmaProps propNew;
+  RINOK(LzmaProps_Decode(&amp;propNew, props, propsSize));
+  RINOK(LzmaDec_AllocateProbs2(p, &amp;propNew, alloc));
+  p-&gt;prop = propNew;
+  return SZ_OK;
+}
+
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+  CLzmaProps propNew;
+  SizeT dicBufSize;
+  RINOK(LzmaProps_Decode(&amp;propNew, props, propsSize));
+  RINOK(LzmaDec_AllocateProbs2(p, &amp;propNew, alloc));
+  dicBufSize = propNew.dicSize;
+  if (p-&gt;dic == 0 || dicBufSize != p-&gt;dicBufSize)
+  {
+    LzmaDec_FreeDict(p, alloc);
+    p-&gt;dic = (Byte *)alloc-&gt;Alloc(alloc, dicBufSize);
+    if (p-&gt;dic == 0)
+    {
+      LzmaDec_FreeProbs(p, alloc);
+      return SZ_ERROR_MEM;
+    }
+  }
+  p-&gt;dicBufSize = dicBufSize;
+  p-&gt;prop = propNew;
+  return SZ_OK;
+}
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 
+    ELzmaStatus *status, ISzAlloc *alloc)
+{
+  CLzmaDec p;
+  SRes res;
+  SizeT inSize = *srcLen;
+  SizeT outSize = *destLen;
+  *srcLen = *destLen = 0;
+  if (inSize &lt; RC_INIT_SIZE)
+    return SZ_ERROR_INPUT_EOF;
+
+  LzmaDec_Construct(&amp;p);
+  res = LzmaDec_AllocateProbs(&amp;p, propData, propSize, alloc);
+  if (res != 0)
+    return res;
+  p.dic = dest;
+  p.dicBufSize = outSize;
+
+  LzmaDec_Init(&amp;p);
+  
+  *srcLen = inSize;
+  res = LzmaDec_DecodeToDic(&amp;p, outSize, src, srcLen, finishMode, status);
+
+  if (res == SZ_OK &amp;&amp; *status == LZMA_STATUS_NEEDS_MORE_INPUT)
+    res = SZ_ERROR_INPUT_EOF;
+
+  (*destLen) = p.dicPos;
+  LzmaDec_FreeProbs(&amp;p, alloc);
+  return res;
+}
--- /dev/null
+++ b/jffsX-utils/lzma/LzmaEnc.c
@@ -0,0 +1,2335 @@
+/* LzmaEnc.c -- LZMA Encoder
+2008-04-28
+Copyright (c) 1999-2008 Igor Pavlov
+Read LzmaEnc.h for license options */
+
+#if defined(SHOW_STAT) || defined(SHOW_STAT2)
+#include &lt;stdio.h&gt;
+#endif
+
+#include &lt;string.h&gt;
+
+#include "LzmaEnc.h"
+
+#include "LzFind.h"
+#ifdef COMPRESS_MF_MT
+#include "LzFindMt.h"
+#endif
+
+/* #define SHOW_STAT */
+/* #define SHOW_STAT2 */
+
+#ifdef SHOW_STAT
+static int ttt = 0;
+#endif
+
+#define kBlockSizeMax ((1 &lt;&lt; LZMA_NUM_BLOCK_SIZE_BITS) - 1)
+
+#define kBlockSize (9 &lt;&lt; 10)
+#define kUnpackBlockSize (1 &lt;&lt; 18)
+#define kMatchArraySize (1 &lt;&lt; 21)
+#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
+
+#define kNumMaxDirectBits (31)
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 &lt;&lt; kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 &lt;&lt; kNumBitModelTotalBits)
+#define kNumMoveBits 5
+#define kProbInitValue (kBitModelTotal &gt;&gt; 1)
+
+#define kNumMoveReducingBits 4
+#define kNumBitPriceShiftBits 4
+#define kBitPrice (1 &lt;&lt; kNumBitPriceShiftBits)
+
+void LzmaEncProps_Init(CLzmaEncProps *p)
+{
+  p-&gt;level = 5;
+  p-&gt;dictSize = p-&gt;mc = 0;
+  p-&gt;lc = p-&gt;lp = p-&gt;pb = p-&gt;algo = p-&gt;fb = p-&gt;btMode = p-&gt;numHashBytes = p-&gt;numThreads = -1;
+  p-&gt;writeEndMark = 0;
+}
+
+void LzmaEncProps_Normalize(CLzmaEncProps *p)
+{
+  int level = p-&gt;level;
+  if (level &lt; 0) level = 5;
+  p-&gt;level = level;
+  if (p-&gt;dictSize == 0) p-&gt;dictSize = (level &lt;= 5 ? (1 &lt;&lt; (level * 2 + 14)) : (level == 6 ? (1 &lt;&lt; 25) : (1 &lt;&lt; 26)));
+  if (p-&gt;lc &lt; 0) p-&gt;lc = 3; 
+  if (p-&gt;lp &lt; 0) p-&gt;lp = 0; 
+  if (p-&gt;pb &lt; 0) p-&gt;pb = 2; 
+  if (p-&gt;algo &lt; 0) p-&gt;algo = (level &lt; 5 ? 0 : 1); 
+  if (p-&gt;fb &lt; 0) p-&gt;fb = (level &lt; 7 ? 32 : 64); 
+  if (p-&gt;btMode &lt; 0) p-&gt;btMode = (p-&gt;algo == 0 ? 0 : 1); 
+  if (p-&gt;numHashBytes &lt; 0) p-&gt;numHashBytes = 4; 
+  if (p-&gt;mc == 0)  p-&gt;mc = (16 + (p-&gt;fb &gt;&gt; 1)) &gt;&gt; (p-&gt;btMode ? 0 : 1);
+  if (p-&gt;numThreads &lt; 0) p-&gt;numThreads = ((p-&gt;btMode &amp;&amp; p-&gt;algo) ? 2 : 1);
+}
+
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
+{
+  CLzmaEncProps props = *props2;
+  LzmaEncProps_Normalize(&amp;props);
+  return props.dictSize;
+}
+
+/* #define LZMA_LOG_BSR */
+/* Define it for Intel's CPU */
+
+
+#ifdef LZMA_LOG_BSR
+
+#define kDicLogSizeMaxCompress 30
+
+#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&amp;i, (pos)); res = (i + i) + ((pos &gt;&gt; (i - 1)) &amp; 1); }
+
+UInt32 GetPosSlot1(UInt32 pos) 
+{ 
+  UInt32 res; 
+  BSR2_RET(pos, res); 
+  return res; 
+}
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos &lt; 2) res = pos; else BSR2_RET(pos, res); }
+
+#else
+
+#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
+#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
+
+static void LzmaEnc_FastPosInit(Byte *g_FastPos)
+{
+  int c = 2, slotFast;
+  g_FastPos[0] = 0;
+  g_FastPos[1] = 1;
+  
+  for (slotFast = 2; slotFast &lt; kNumLogBits * 2; slotFast++)
+  {
+    UInt32 k = (1 &lt;&lt; ((slotFast &gt;&gt; 1) - 1));
+    UInt32 j;
+    for (j = 0; j &lt; k; j++, c++)
+      g_FastPos[c] = (Byte)slotFast;
+  }
+}
+
+#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) &amp; \
+  (0 - (((((UInt32)1 &lt;&lt; (kNumLogBits + 6)) - 1) - pos) &gt;&gt; 31))); \
+  res = p-&gt;g_FastPos[pos &gt;&gt; i] + (i * 2); }
+/*
+#define BSR2_RET(pos, res) { res = (pos &lt; (1 &lt;&lt; (kNumLogBits + 6))) ? \
+  p-&gt;g_FastPos[pos &gt;&gt; 6] + 12 : \
+  p-&gt;g_FastPos[pos &gt;&gt; (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
+*/
+
+#define GetPosSlot1(pos) p-&gt;g_FastPos[pos]
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos &lt; kNumFullDistances) res = p-&gt;g_FastPos[pos]; else BSR2_RET(pos, res); }
+
+#endif
+
+
+#define LZMA_NUM_REPS 4
+
+typedef unsigned CState;
+
+typedef struct _COptimal
+{
+  UInt32 price;    
+
+  CState state;
+  int prev1IsChar;
+  int prev2;
+
+  UInt32 posPrev2;
+  UInt32 backPrev2;     
+
+  UInt32 posPrev;
+  UInt32 backPrev;     
+  UInt32 backs[LZMA_NUM_REPS];
+} COptimal;
+
+#define kNumOpts (1 &lt;&lt; 12)
+
+#define kNumLenToPosStates 4
+#define kNumPosSlotBits 6 
+#define kDicLogSizeMin 0 
+#define kDicLogSizeMax 32 
+#define kDistTableSizeMax (kDicLogSizeMax * 2)
+
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 &lt;&lt; kNumAlignBits)
+#define kAlignMask (kAlignTableSize - 1)
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
+
+#define kNumFullDistances (1 &lt;&lt; (kEndPosModelIndex / 2))
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+#define LZMA_PB_MAX 4
+#define LZMA_LC_MAX 8
+#define LZMA_LP_MAX 4
+
+#define LZMA_NUM_PB_STATES_MAX (1 &lt;&lt; LZMA_PB_MAX)
+
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 &lt;&lt; kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 &lt;&lt; kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 &lt;&lt; kLenNumHighBits)
+
+#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define LZMA_MATCH_LEN_MIN 2
+#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
+
+#define kNumStates 12
+
+typedef struct
+{
+  CLzmaProb choice;
+  CLzmaProb choice2;
+  CLzmaProb low[LZMA_NUM_PB_STATES_MAX &lt;&lt; kLenNumLowBits];
+  CLzmaProb mid[LZMA_NUM_PB_STATES_MAX &lt;&lt; kLenNumMidBits];
+  CLzmaProb high[kLenNumHighSymbols];
+} CLenEnc;
+
+typedef struct
+{
+  CLenEnc p;
+  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
+  UInt32 tableSize;
+  UInt32 counters[LZMA_NUM_PB_STATES_MAX];
+} CLenPriceEnc;
+
+typedef struct _CRangeEnc
+{
+  UInt32 range;
+  Byte cache;
+  UInt64 low;
+  UInt64 cacheSize;
+  Byte *buf;
+  Byte *bufLim;
+  Byte *bufBase;
+  ISeqOutStream *outStream;
+  UInt64 processed;
+  SRes res;
+} CRangeEnc;
+
+typedef struct _CSeqInStreamBuf
+{
+  ISeqInStream funcTable;
+  const Byte *data;
+  SizeT rem;
+} CSeqInStreamBuf;
+
+static SRes MyRead(void *pp, void *data, size_t *size)
+{
+  size_t curSize = *size;
+  CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp;
+  if (p-&gt;rem &lt; curSize)
+    curSize = p-&gt;rem;
+  memcpy(data, p-&gt;data, curSize);
+  p-&gt;rem -= curSize;
+  p-&gt;data += curSize;
+  *size = curSize;
+  return SZ_OK;
+}
+
+typedef struct 
+{
+  CLzmaProb *litProbs;
+
+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+  CLzmaProb isRep[kNumStates];
+  CLzmaProb isRepG0[kNumStates];
+  CLzmaProb isRepG1[kNumStates];
+  CLzmaProb isRepG2[kNumStates];
+  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+
+  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 &lt;&lt; kNumPosSlotBits];
+  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
+  CLzmaProb posAlignEncoder[1 &lt;&lt; kNumAlignBits];
+  
+  CLenPriceEnc lenEnc;
+  CLenPriceEnc repLenEnc;
+
+  UInt32 reps[LZMA_NUM_REPS];
+  UInt32 state;
+} CSaveState;
+
+typedef struct _CLzmaEnc
+{
+  IMatchFinder matchFinder;
+  void *matchFinderObj;
+
+  #ifdef COMPRESS_MF_MT
+  Bool mtMode;
+  CMatchFinderMt matchFinderMt;
+  #endif
+
+  CMatchFinder matchFinderBase;
+
+  #ifdef COMPRESS_MF_MT
+  Byte pad[128];
+  #endif
+  
+  UInt32 optimumEndIndex;
+  UInt32 optimumCurrentIndex;
+
+  Bool longestMatchWasFound;
+  UInt32 longestMatchLength;    
+  UInt32 numDistancePairs;
+
+  COptimal opt[kNumOpts];
+  
+  #ifndef LZMA_LOG_BSR
+  Byte g_FastPos[1 &lt;&lt; kNumLogBits];
+  #endif
+
+  UInt32 ProbPrices[kBitModelTotal &gt;&gt; kNumMoveReducingBits];
+  UInt32 matchDistances[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
+  UInt32 numFastBytes;
+  UInt32 additionalOffset;
+  UInt32 reps[LZMA_NUM_REPS];
+  UInt32 state;
+
+  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
+  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
+  UInt32 alignPrices[kAlignTableSize];
+  UInt32 alignPriceCount;
+
+  UInt32 distTableSize;
+
+  unsigned lc, lp, pb;
+  unsigned lpMask, pbMask;
+
+  CLzmaProb *litProbs;
+
+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+  CLzmaProb isRep[kNumStates];
+  CLzmaProb isRepG0[kNumStates];
+  CLzmaProb isRepG1[kNumStates];
+  CLzmaProb isRepG2[kNumStates];
+  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+
+  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 &lt;&lt; kNumPosSlotBits];
+  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
+  CLzmaProb posAlignEncoder[1 &lt;&lt; kNumAlignBits];
+  
+  CLenPriceEnc lenEnc;
+  CLenPriceEnc repLenEnc;
+
+  unsigned lclp;
+
+  Bool fastMode;
+  
+  CRangeEnc rc;
+
+  Bool writeEndMark;
+  UInt64 nowPos64;
+  UInt32 matchPriceCount;
+  Bool finished;
+  Bool multiThread;
+
+  SRes result;
+  UInt32 dictSize;
+  UInt32 matchFinderCycles;
+
+  ISeqInStream *inStream;
+  CSeqInStreamBuf seqBufInStream;
+
+  CSaveState saveState;
+} CLzmaEnc;
+
+static void LzmaEnc_SaveState(CLzmaEncHandle pp)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  CSaveState *dest = &amp;p-&gt;saveState;
+  int i;
+  dest-&gt;lenEnc = p-&gt;lenEnc;
+  dest-&gt;repLenEnc = p-&gt;repLenEnc;
+  dest-&gt;state = p-&gt;state;
+
+  for (i = 0; i &lt; kNumStates; i++)
+  {
+    memcpy(dest-&gt;isMatch[i], p-&gt;isMatch[i], sizeof(p-&gt;isMatch[i]));
+    memcpy(dest-&gt;isRep0Long[i], p-&gt;isRep0Long[i], sizeof(p-&gt;isRep0Long[i]));
+  }
+  for (i = 0; i &lt; kNumLenToPosStates; i++)
+    memcpy(dest-&gt;posSlotEncoder[i], p-&gt;posSlotEncoder[i], sizeof(p-&gt;posSlotEncoder[i]));
+  memcpy(dest-&gt;isRep, p-&gt;isRep, sizeof(p-&gt;isRep));
+  memcpy(dest-&gt;isRepG0, p-&gt;isRepG0, sizeof(p-&gt;isRepG0));
+  memcpy(dest-&gt;isRepG1, p-&gt;isRepG1, sizeof(p-&gt;isRepG1));
+  memcpy(dest-&gt;isRepG2, p-&gt;isRepG2, sizeof(p-&gt;isRepG2));
+  memcpy(dest-&gt;posEncoders, p-&gt;posEncoders, sizeof(p-&gt;posEncoders));
+  memcpy(dest-&gt;posAlignEncoder, p-&gt;posAlignEncoder, sizeof(p-&gt;posAlignEncoder));
+  memcpy(dest-&gt;reps, p-&gt;reps, sizeof(p-&gt;reps));
+  memcpy(dest-&gt;litProbs, p-&gt;litProbs, (0x300 &lt;&lt; p-&gt;lclp) * sizeof(CLzmaProb));
+}
+
+static void LzmaEnc_RestoreState(CLzmaEncHandle pp)
+{
+  CLzmaEnc *dest = (CLzmaEnc *)pp;
+  const CSaveState *p = &amp;dest-&gt;saveState;
+  int i;
+  dest-&gt;lenEnc = p-&gt;lenEnc;
+  dest-&gt;repLenEnc = p-&gt;repLenEnc;
+  dest-&gt;state = p-&gt;state;
+
+  for (i = 0; i &lt; kNumStates; i++)
+  {
+    memcpy(dest-&gt;isMatch[i], p-&gt;isMatch[i], sizeof(p-&gt;isMatch[i]));
+    memcpy(dest-&gt;isRep0Long[i], p-&gt;isRep0Long[i], sizeof(p-&gt;isRep0Long[i]));
+  }
+  for (i = 0; i &lt; kNumLenToPosStates; i++)
+    memcpy(dest-&gt;posSlotEncoder[i], p-&gt;posSlotEncoder[i], sizeof(p-&gt;posSlotEncoder[i]));
+  memcpy(dest-&gt;isRep, p-&gt;isRep, sizeof(p-&gt;isRep));
+  memcpy(dest-&gt;isRepG0, p-&gt;isRepG0, sizeof(p-&gt;isRepG0));
+  memcpy(dest-&gt;isRepG1, p-&gt;isRepG1, sizeof(p-&gt;isRepG1));
+  memcpy(dest-&gt;isRepG2, p-&gt;isRepG2, sizeof(p-&gt;isRepG2));
+  memcpy(dest-&gt;posEncoders, p-&gt;posEncoders, sizeof(p-&gt;posEncoders));
+  memcpy(dest-&gt;posAlignEncoder, p-&gt;posAlignEncoder, sizeof(p-&gt;posAlignEncoder));
+  memcpy(dest-&gt;reps, p-&gt;reps, sizeof(p-&gt;reps));
+  memcpy(dest-&gt;litProbs, p-&gt;litProbs, (0x300 &lt;&lt; dest-&gt;lclp) * sizeof(CLzmaProb));
+}
+
+SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  CLzmaEncProps props = *props2;
+  LzmaEncProps_Normalize(&amp;props);
+
+  if (props.lc &gt; LZMA_LC_MAX || props.lp &gt; LZMA_LP_MAX || props.pb &gt; LZMA_PB_MAX ||
+      props.dictSize &gt; (1 &lt;&lt; kDicLogSizeMaxCompress) || props.dictSize &gt; (1 &lt;&lt; 30))
+    return SZ_ERROR_PARAM;
+  p-&gt;dictSize = props.dictSize;
+  p-&gt;matchFinderCycles = props.mc;
+  {
+    unsigned fb = props.fb;
+    if (fb &lt; 5)
+      fb = 5;
+    if (fb &gt; LZMA_MATCH_LEN_MAX)
+      fb = LZMA_MATCH_LEN_MAX;
+    p-&gt;numFastBytes = fb;
+  }
+  p-&gt;lc = props.lc;
+  p-&gt;lp = props.lp;
+  p-&gt;pb = props.pb;
+  p-&gt;fastMode = (props.algo == 0);
+  p-&gt;matchFinderBase.btMode = props.btMode;
+  {
+    UInt32 numHashBytes = 4;
+    if (props.btMode)
+    {
+      if (props.numHashBytes &lt; 2)
+        numHashBytes = 2;
+      else if (props.numHashBytes &lt; 4)
+        numHashBytes = props.numHashBytes;
+    }
+    p-&gt;matchFinderBase.numHashBytes = numHashBytes;
+  }
+
+  p-&gt;matchFinderBase.cutValue = props.mc;
+
+  p-&gt;writeEndMark = props.writeEndMark;
+
+  #ifdef COMPRESS_MF_MT
+  /*
+  if (newMultiThread != _multiThread)
+  {
+    ReleaseMatchFinder();
+    _multiThread = newMultiThread;
+  }
+  */
+  p-&gt;multiThread = (props.numThreads &gt; 1);
+  #endif
+
+  return SZ_OK;
+}
+
+static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
+static const int kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+static const int kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+/*
+  void UpdateChar() { Index = kLiteralNextStates[Index]; }
+  void UpdateMatch() { Index = kMatchNextStates[Index]; }
+  void UpdateRep() { Index = kRepNextStates[Index]; }
+  void UpdateShortRep() { Index = kShortRepNextStates[Index]; }
+*/
+
+#define IsCharState(s) ((s) &lt; 7)
+
+
+#define GetLenToPosState(len) (((len) &lt; kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
+
+#define kInfinityPrice (1 &lt;&lt; 30)
+
+static void RangeEnc_Construct(CRangeEnc *p)
+{
+  p-&gt;outStream = 0;
+  p-&gt;bufBase = 0;
+}
+
+#define RangeEnc_GetProcessed(p) ((p)-&gt;processed + ((p)-&gt;buf - (p)-&gt;bufBase) + (p)-&gt;cacheSize)
+
+#define RC_BUF_SIZE (1 &lt;&lt; 16)
+static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
+{
+  if (p-&gt;bufBase == 0)
+  {
+    p-&gt;bufBase = (Byte *)alloc-&gt;Alloc(alloc, RC_BUF_SIZE);
+    if (p-&gt;bufBase == 0)
+      return 0;
+    p-&gt;bufLim = p-&gt;bufBase + RC_BUF_SIZE;
+  }
+  return 1;
+}
+
+static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
+{
+  alloc-&gt;Free(alloc, p-&gt;bufBase);
+  p-&gt;bufBase = 0;
+}
+
+static void RangeEnc_Init(CRangeEnc *p)
+{
+  /* Stream.Init(); */
+  p-&gt;low = 0;
+  p-&gt;range = 0xFFFFFFFF;
+  p-&gt;cacheSize = 1;
+  p-&gt;cache = 0;
+
+  p-&gt;buf = p-&gt;bufBase;
+
+  p-&gt;processed = 0;
+  p-&gt;res = SZ_OK;
+}
+
+static void RangeEnc_FlushStream(CRangeEnc *p)
+{
+  size_t num;
+  if (p-&gt;res != SZ_OK)
+    return;
+  num = p-&gt;buf - p-&gt;bufBase;
+  if (num != p-&gt;outStream-&gt;Write(p-&gt;outStream, p-&gt;bufBase, num))
+    p-&gt;res = SZ_ERROR_WRITE;
+  p-&gt;processed += num;
+  p-&gt;buf = p-&gt;bufBase;
+}
+
+static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
+{
+  if ((UInt32)p-&gt;low &lt; (UInt32)0xFF000000 || (int)(p-&gt;low &gt;&gt; 32) != 0) 
+  {
+    Byte temp = p-&gt;cache;
+    do
+    {
+      Byte *buf = p-&gt;buf;
+      *buf++ = (Byte)(temp + (Byte)(p-&gt;low &gt;&gt; 32));
+      p-&gt;buf = buf;
+      if (buf == p-&gt;bufLim)
+        RangeEnc_FlushStream(p);
+      temp = 0xFF;
+    }
+    while (--p-&gt;cacheSize != 0);
+    p-&gt;cache = (Byte)((UInt32)p-&gt;low &gt;&gt; 24);                      
+  } 
+  p-&gt;cacheSize++;                               
+  p-&gt;low = (UInt32)p-&gt;low &lt;&lt; 8;                           
+}
+
+static void RangeEnc_FlushData(CRangeEnc *p)
+{
+  int i;
+  for (i = 0; i &lt; 5; i++)
+    RangeEnc_ShiftLow(p);
+}
+
+static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
+{
+  do
+  {
+    p-&gt;range &gt;&gt;= 1;
+    p-&gt;low += p-&gt;range &amp; (0 - ((value &gt;&gt; --numBits) &amp; 1));
+    if (p-&gt;range &lt; kTopValue)
+    {
+      p-&gt;range &lt;&lt;= 8;
+      RangeEnc_ShiftLow(p);
+    }
+  }
+  while (numBits != 0);
+}
+
+static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
+{
+  UInt32 ttt = *prob;
+  UInt32 newBound = (p-&gt;range &gt;&gt; kNumBitModelTotalBits) * ttt;
+  if (symbol == 0)
+  {
+    p-&gt;range = newBound;
+    ttt += (kBitModelTotal - ttt) &gt;&gt; kNumMoveBits;
+  }
+  else
+  {
+    p-&gt;low += newBound;
+    p-&gt;range -= newBound;
+    ttt -= ttt &gt;&gt; kNumMoveBits;
+  }
+  *prob = (CLzmaProb)ttt;
+  if (p-&gt;range &lt; kTopValue)
+  {
+    p-&gt;range &lt;&lt;= 8;
+    RangeEnc_ShiftLow(p);
+  }
+}
+
+static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
+{
+  symbol |= 0x100;
+  do 
+  {
+    RangeEnc_EncodeBit(p, probs + (symbol &gt;&gt; 8), (symbol &gt;&gt; 7) &amp; 1);
+    symbol &lt;&lt;= 1;
+  }
+  while (symbol &lt; 0x10000);
+}
+
+static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
+{
+  UInt32 offs = 0x100;
+  symbol |= 0x100;
+  do 
+  {
+    matchByte &lt;&lt;= 1;
+    RangeEnc_EncodeBit(p, probs + (offs + (matchByte &amp; offs) + (symbol &gt;&gt; 8)), (symbol &gt;&gt; 7) &amp; 1);
+    symbol &lt;&lt;= 1;
+    offs &amp;= ~(matchByte ^ symbol);
+  }
+  while (symbol &lt; 0x10000);
+}
+
+static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
+{
+  UInt32 i;
+  for (i = (1 &lt;&lt; kNumMoveReducingBits) / 2; i &lt; kBitModelTotal; i += (1 &lt;&lt; kNumMoveReducingBits))
+  {
+    const int kCyclesBits = kNumBitPriceShiftBits;
+    UInt32 w = i;
+    UInt32 bitCount = 0;
+    int j;
+    for (j = 0; j &lt; kCyclesBits; j++)
+    {
+      w = w * w;
+      bitCount &lt;&lt;= 1;
+      while (w &gt;= ((UInt32)1 &lt;&lt; 16))
+      {
+        w &gt;&gt;= 1;
+        bitCount++;
+      }
+    }
+    ProbPrices[i &gt;&gt; kNumMoveReducingBits] = ((kNumBitModelTotalBits &lt;&lt; kCyclesBits) - 15 - bitCount);
+  }
+}
+
+
+#define GET_PRICE(prob, symbol) \
+  p-&gt;ProbPrices[((prob) ^ (((-(int)(symbol))) &amp; (kBitModelTotal - 1))) &gt;&gt; kNumMoveReducingBits];
+
+#define GET_PRICEa(prob, symbol) \
+  ProbPrices[((prob) ^ ((-((int)(symbol))) &amp; (kBitModelTotal - 1))) &gt;&gt; kNumMoveReducingBits];
+
+#define GET_PRICE_0(prob) p-&gt;ProbPrices[(prob) &gt;&gt; kNumMoveReducingBits]
+#define GET_PRICE_1(prob) p-&gt;ProbPrices[((prob) ^ (kBitModelTotal - 1)) &gt;&gt; kNumMoveReducingBits]
+
+#define GET_PRICE_0a(prob) ProbPrices[(prob) &gt;&gt; kNumMoveReducingBits]
+#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) &gt;&gt; kNumMoveReducingBits]
+
+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  symbol |= 0x100;
+  do
+  {
+    price += GET_PRICEa(probs[symbol &gt;&gt; 8], (symbol &gt;&gt; 7) &amp; 1);
+    symbol &lt;&lt;= 1;
+  }
+  while (symbol &lt; 0x10000);
+  return price;
+};
+
+static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  UInt32 offs = 0x100;
+  symbol |= 0x100;
+  do 
+  {
+    matchByte &lt;&lt;= 1;
+    price += GET_PRICEa(probs[offs + (matchByte &amp; offs) + (symbol &gt;&gt; 8)], (symbol &gt;&gt; 7) &amp; 1);
+    symbol &lt;&lt;= 1;
+    offs &amp;= ~(matchByte ^ symbol);
+  }
+  while (symbol &lt; 0x10000);
+  return price;
+};
+
+
+static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
+{
+  UInt32 m = 1;
+  int i;
+  for (i = numBitLevels; i != 0 ;)
+  {
+    UInt32 bit;
+    i--;
+    bit = (symbol &gt;&gt; i) &amp; 1;
+    RangeEnc_EncodeBit(rc, probs + m, bit);
+    m = (m &lt;&lt; 1) | bit;
+  }
+};
+
+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
+{
+  UInt32 m = 1;
+  int i;
+  for (i = 0; i &lt; numBitLevels; i++)
+  {
+    UInt32 bit = symbol &amp; 1;
+    RangeEnc_EncodeBit(rc, probs + m, bit);
+    m = (m &lt;&lt; 1) | bit;
+    symbol &gt;&gt;= 1;
+  }
+}
+
+static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  symbol |= (1 &lt;&lt; numBitLevels);
+  while (symbol != 1)
+  {
+    price += GET_PRICEa(probs[symbol &gt;&gt; 1], symbol &amp; 1);
+    symbol &gt;&gt;= 1;
+  }
+  return price;
+}
+
+static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  UInt32 m = 1;
+  int i;
+  for (i = numBitLevels; i != 0; i--)
+  {
+    UInt32 bit = symbol &amp; 1;
+    symbol &gt;&gt;= 1;
+    price += GET_PRICEa(probs[m], bit);
+    m = (m &lt;&lt; 1) | bit;
+  }
+  return price;
+}
+
+
+static void LenEnc_Init(CLenEnc *p)
+{
+  unsigned i;
+  p-&gt;choice = p-&gt;choice2 = kProbInitValue;
+  for (i = 0; i &lt; (LZMA_NUM_PB_STATES_MAX &lt;&lt; kLenNumLowBits); i++)
+    p-&gt;low[i] = kProbInitValue;
+  for (i = 0; i &lt; (LZMA_NUM_PB_STATES_MAX &lt;&lt; kLenNumMidBits); i++)
+    p-&gt;mid[i] = kProbInitValue;
+  for (i = 0; i &lt; kLenNumHighSymbols; i++)
+    p-&gt;high[i] = kProbInitValue;
+}
+
+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
+{
+  if (symbol &lt; kLenNumLowSymbols)
+  {
+    RangeEnc_EncodeBit(rc, &amp;p-&gt;choice, 0);
+    RcTree_Encode(rc, p-&gt;low + (posState &lt;&lt; kLenNumLowBits), kLenNumLowBits, symbol);
+  }
+  else
+  {
+    RangeEnc_EncodeBit(rc, &amp;p-&gt;choice, 1);
+    if (symbol &lt; kLenNumLowSymbols + kLenNumMidSymbols)
+    {
+      RangeEnc_EncodeBit(rc, &amp;p-&gt;choice2, 0);
+      RcTree_Encode(rc, p-&gt;mid + (posState &lt;&lt; kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
+    }
+    else
+    {
+      RangeEnc_EncodeBit(rc, &amp;p-&gt;choice2, 1);
+      RcTree_Encode(rc, p-&gt;high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
+    }
+  }
+}
+
+static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
+{
+  UInt32 a0 = GET_PRICE_0a(p-&gt;choice);
+  UInt32 a1 = GET_PRICE_1a(p-&gt;choice);
+  UInt32 b0 = a1 + GET_PRICE_0a(p-&gt;choice2);
+  UInt32 b1 = a1 + GET_PRICE_1a(p-&gt;choice2);
+  UInt32 i = 0;
+  for (i = 0; i &lt; kLenNumLowSymbols; i++)
+  {
+    if (i &gt;= numSymbols)
+      return;
+    prices[i] = a0 + RcTree_GetPrice(p-&gt;low + (posState &lt;&lt; kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
+  }
+  for (; i &lt; kLenNumLowSymbols + kLenNumMidSymbols; i++)
+  {
+    if (i &gt;= numSymbols)
+      return;
+    prices[i] = b0 + RcTree_GetPrice(p-&gt;mid + (posState &lt;&lt; kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
+  }
+  for (; i &lt; numSymbols; i++)
+    prices[i] = b1 + RcTree_GetPrice(p-&gt;high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
+}
+
+static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
+{
+  LenEnc_SetPrices(&amp;p-&gt;p, posState, p-&gt;tableSize, p-&gt;prices[posState], ProbPrices);
+  p-&gt;counters[posState] = p-&gt;tableSize;
+}
+
+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
+{
+  UInt32 posState;
+  for (posState = 0; posState &lt; numPosStates; posState++)
+    LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+}
+
+static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
+{
+  LenEnc_Encode(&amp;p-&gt;p, rc, symbol, posState);
+  if (updatePrice)
+    if (--p-&gt;counters[posState] == 0)
+      LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+}
+
+
+
+
+static void MovePos(CLzmaEnc *p, UInt32 num)
+{
+  #ifdef SHOW_STAT
+  ttt += num;
+  printf("\n MovePos %d", num);
+  #endif
+  if (num != 0)
+  {
+    p-&gt;additionalOffset += num;
+    p-&gt;matchFinder.Skip(p-&gt;matchFinderObj, num);
+  }
+}
+
+static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
+{
+  UInt32 lenRes = 0, numDistancePairs;
+  numDistancePairs = p-&gt;matchFinder.GetMatches(p-&gt;matchFinderObj, p-&gt;matchDistances);
+  #ifdef SHOW_STAT
+  printf("\n i = %d numPairs = %d    ", ttt, numDistancePairs / 2);
+  if (ttt &gt;= 61994)
+    ttt = ttt;
+
+  ttt++;
+  {
+    UInt32 i;
+  for (i = 0; i &lt; numDistancePairs; i += 2)
+    printf("%2d %6d   | ", p-&gt;matchDistances[i], p-&gt;matchDistances[i + 1]);
+  }
+  #endif
+  if (numDistancePairs &gt; 0)
+  {
+    lenRes = p-&gt;matchDistances[numDistancePairs - 2];
+    if (lenRes == p-&gt;numFastBytes)
+    {
+      UInt32 numAvail = p-&gt;matchFinder.GetNumAvailableBytes(p-&gt;matchFinderObj) + 1;
+      const Byte *pby = p-&gt;matchFinder.GetPointerToCurrentPos(p-&gt;matchFinderObj) - 1;
+      UInt32 distance = p-&gt;matchDistances[numDistancePairs - 1] + 1;
+      if (numAvail &gt; LZMA_MATCH_LEN_MAX)
+        numAvail = LZMA_MATCH_LEN_MAX;
+
+      {
+        const Byte *pby2 = pby - distance;
+        for (; lenRes &lt; numAvail &amp;&amp; pby[lenRes] == pby2[lenRes]; lenRes++);
+      }
+    }
+  }
+  p-&gt;additionalOffset++;
+  *numDistancePairsRes = numDistancePairs;
+  return lenRes;
+}
+
+
+#define MakeAsChar(p) (p)-&gt;backPrev = (UInt32)(-1); (p)-&gt;prev1IsChar = False;
+#define MakeAsShortRep(p) (p)-&gt;backPrev = 0; (p)-&gt;prev1IsChar = False;
+#define IsShortRep(p) ((p)-&gt;backPrev == 0)
+
+static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
+{
+  return 
+    GET_PRICE_0(p-&gt;isRepG0[state]) +
+    GET_PRICE_0(p-&gt;isRep0Long[state][posState]);
+}
+
+static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
+{
+  UInt32 price;
+  if (repIndex == 0)
+  {
+    price = GET_PRICE_0(p-&gt;isRepG0[state]);
+    price += GET_PRICE_1(p-&gt;isRep0Long[state][posState]);
+  }
+  else
+  {
+    price = GET_PRICE_1(p-&gt;isRepG0[state]);
+    if (repIndex == 1)
+      price += GET_PRICE_0(p-&gt;isRepG1[state]);
+    else
+    {
+      price += GET_PRICE_1(p-&gt;isRepG1[state]);
+      price += GET_PRICE(p-&gt;isRepG2[state], repIndex - 2);
+    }
+  }
+  return price;
+}
+
+static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
+{
+  return p-&gt;repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
+    GetPureRepPrice(p, repIndex, state, posState);
+}
+
+static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
+{
+  UInt32 posMem = p-&gt;opt[cur].posPrev;
+  UInt32 backMem = p-&gt;opt[cur].backPrev;
+  p-&gt;optimumEndIndex = cur;
+  do
+  {
+    if (p-&gt;opt[cur].prev1IsChar)
+    {
+      MakeAsChar(&amp;p-&gt;opt[posMem])
+      p-&gt;opt[posMem].posPrev = posMem - 1;
+      if (p-&gt;opt[cur].prev2)
+      {
+        p-&gt;opt[posMem - 1].prev1IsChar = False;
+        p-&gt;opt[posMem - 1].posPrev = p-&gt;opt[cur].posPrev2;
+        p-&gt;opt[posMem - 1].backPrev = p-&gt;opt[cur].backPrev2;
+      }
+    }
+    {
+      UInt32 posPrev = posMem;
+      UInt32 backCur = backMem;
+      
+      backMem = p-&gt;opt[posPrev].backPrev;
+      posMem = p-&gt;opt[posPrev].posPrev;
+      
+      p-&gt;opt[posPrev].backPrev = backCur;
+      p-&gt;opt[posPrev].posPrev = cur;
+      cur = posPrev;
+    }
+  }
+  while (cur != 0);
+  *backRes = p-&gt;opt[0].backPrev;
+  p-&gt;optimumCurrentIndex  = p-&gt;opt[0].posPrev;
+  return p-&gt;optimumCurrentIndex; 
+}
+
+#define LIT_PROBS(pos, prevByte) (p-&gt;litProbs + ((((pos) &amp; p-&gt;lpMask) &lt;&lt; p-&gt;lc) + ((prevByte) &gt;&gt; (8 - p-&gt;lc))) * 0x300)
+
+static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
+{
+  UInt32 numAvailableBytes, lenMain, numDistancePairs;
+  const Byte *data;
+  UInt32 reps[LZMA_NUM_REPS];
+  UInt32 repLens[LZMA_NUM_REPS];
+  UInt32 repMaxIndex, i;
+  UInt32 *matchDistances;
+  Byte currentByte, matchByte; 
+  UInt32 posState;
+  UInt32 matchPrice, repMatchPrice;
+  UInt32 lenEnd;
+  UInt32 len;
+  UInt32 normalMatchPrice;
+  UInt32 cur;
+  if (p-&gt;optimumEndIndex != p-&gt;optimumCurrentIndex)
+  {
+    const COptimal *opt = &amp;p-&gt;opt[p-&gt;optimumCurrentIndex];
+    UInt32 lenRes = opt-&gt;posPrev - p-&gt;optimumCurrentIndex;
+    *backRes = opt-&gt;backPrev;
+    p-&gt;optimumCurrentIndex = opt-&gt;posPrev;
+    return lenRes;
+  }
+  p-&gt;optimumCurrentIndex = p-&gt;optimumEndIndex = 0;
+  
+  numAvailableBytes = p-&gt;matchFinder.GetNumAvailableBytes(p-&gt;matchFinderObj);
+
+  if (!p-&gt;longestMatchWasFound)
+  {
+    lenMain = ReadMatchDistances(p, &amp;numDistancePairs);
+  }
+  else
+  {
+    lenMain = p-&gt;longestMatchLength;
+    numDistancePairs = p-&gt;numDistancePairs;
+    p-&gt;longestMatchWasFound = False;
+  }
+
+  data = p-&gt;matchFinder.GetPointerToCurrentPos(p-&gt;matchFinderObj) - 1;
+  if (numAvailableBytes &lt; 2)
+  {
+    *backRes = (UInt32)(-1);
+    return 1;
+  }
+  if (numAvailableBytes &gt; LZMA_MATCH_LEN_MAX)
+    numAvailableBytes = LZMA_MATCH_LEN_MAX;
+
+  repMaxIndex = 0;
+  for (i = 0; i &lt; LZMA_NUM_REPS; i++)
+  {
+    UInt32 lenTest;
+    const Byte *data2;
+    reps[i] = p-&gt;reps[i];
+    data2 = data - (reps[i] + 1);
+    if (data[0] != data2[0] || data[1] != data2[1])
+    {
+      repLens[i] = 0;
+      continue;
+    }
+    for (lenTest = 2; lenTest &lt; numAvailableBytes &amp;&amp; data[lenTest] == data2[lenTest]; lenTest++);
+    repLens[i] = lenTest;
+    if (lenTest &gt; repLens[repMaxIndex])
+      repMaxIndex = i;
+  }
+  if (repLens[repMaxIndex] &gt;= p-&gt;numFastBytes)
+  {
+    UInt32 lenRes;
+    *backRes = repMaxIndex;
+    lenRes = repLens[repMaxIndex];
+    MovePos(p, lenRes - 1);
+    return lenRes;
+  }
+
+  matchDistances = p-&gt;matchDistances;
+  if (lenMain &gt;= p-&gt;numFastBytes)
+  {
+    *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS; 
+    MovePos(p, lenMain - 1);
+    return lenMain;
+  }
+  currentByte = *data;
+  matchByte = *(data - (reps[0] + 1));
+
+  if (lenMain &lt; 2 &amp;&amp; currentByte != matchByte &amp;&amp; repLens[repMaxIndex] &lt; 2)
+  {
+    *backRes = (UInt32)-1;
+    return 1;
+  }
+
+  p-&gt;opt[0].state = (CState)p-&gt;state;
+
+  posState = (position &amp; p-&gt;pbMask);
+
+  {
+    const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+    p-&gt;opt[1].price = GET_PRICE_0(p-&gt;isMatch[p-&gt;state][posState]) + 
+        (!IsCharState(p-&gt;state) ? 
+          LitEnc_GetPriceMatched(probs, currentByte, matchByte, p-&gt;ProbPrices) :
+          LitEnc_GetPrice(probs, currentByte, p-&gt;ProbPrices));
+  }
+
+  MakeAsChar(&amp;p-&gt;opt[1]);
+
+  matchPrice = GET_PRICE_1(p-&gt;isMatch[p-&gt;state][posState]);
+  repMatchPrice = matchPrice + GET_PRICE_1(p-&gt;isRep[p-&gt;state]);
+
+  if (matchByte == currentByte)
+  {
+    UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p-&gt;state, posState);
+    if (shortRepPrice &lt; p-&gt;opt[1].price)
+    {
+      p-&gt;opt[1].price = shortRepPrice;
+      MakeAsShortRep(&amp;p-&gt;opt[1]);
+    }
+  }
+  lenEnd = ((lenMain &gt;= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
+
+  if (lenEnd &lt; 2)
+  {
+    *backRes = p-&gt;opt[1].backPrev;
+    return 1;
+  }
+
+  p-&gt;opt[1].posPrev = 0;
+  for (i = 0; i &lt; LZMA_NUM_REPS; i++)
+    p-&gt;opt[0].backs[i] = reps[i];
+
+  len = lenEnd;
+  do
+    p-&gt;opt[len--].price = kInfinityPrice;
+  while (len &gt;= 2);
+
+  for (i = 0; i &lt; LZMA_NUM_REPS; i++)
+  {
+    UInt32 repLen = repLens[i];
+    UInt32 price;
+    if (repLen &lt; 2)
+      continue;
+    price = repMatchPrice + GetPureRepPrice(p, i, p-&gt;state, posState);
+    do
+    {
+      UInt32 curAndLenPrice = price + p-&gt;repLenEnc.prices[posState][repLen - 2];
+      COptimal *opt = &amp;p-&gt;opt[repLen];
+      if (curAndLenPrice &lt; opt-&gt;price) 
+      {
+        opt-&gt;price = curAndLenPrice;
+        opt-&gt;posPrev = 0;
+        opt-&gt;backPrev = i;
+        opt-&gt;prev1IsChar = False;
+      }
+    }
+    while (--repLen &gt;= 2);
+  }
+
+  normalMatchPrice = matchPrice + GET_PRICE_0(p-&gt;isRep[p-&gt;state]);
+
+  len = ((repLens[0] &gt;= 2) ? repLens[0] + 1 : 2);
+  if (len &lt;= lenMain)
+  {
+    UInt32 offs = 0;
+    while (len &gt; matchDistances[offs])
+      offs += 2;
+    for (; ; len++)
+    {
+      COptimal *opt;
+      UInt32 distance = matchDistances[offs + 1];
+
+      UInt32 curAndLenPrice = normalMatchPrice + p-&gt;lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
+      UInt32 lenToPosState = GetLenToPosState(len);
+      if (distance &lt; kNumFullDistances)
+        curAndLenPrice += p-&gt;distancesPrices[lenToPosState][distance];
+      else
+      {
+        UInt32 slot;
+        GetPosSlot2(distance, slot);
+        curAndLenPrice += p-&gt;alignPrices[distance &amp; kAlignMask] + p-&gt;posSlotPrices[lenToPosState][slot];
+      }
+      opt = &amp;p-&gt;opt[len];
+      if (curAndLenPrice &lt; opt-&gt;price) 
+      {
+        opt-&gt;price = curAndLenPrice;
+        opt-&gt;posPrev = 0;
+        opt-&gt;backPrev = distance + LZMA_NUM_REPS;
+        opt-&gt;prev1IsChar = False;
+      }
+      if (len == matchDistances[offs])
+      {
+        offs += 2;
+        if (offs == numDistancePairs)
+          break;
+      }
+    }
+  }
+
+  cur = 0;
+
+    #ifdef SHOW_STAT2
+    if (position &gt;= 0)
+    {
+      unsigned i;
+      printf("\n pos = %4X", position);
+      for (i = cur; i &lt;= lenEnd; i++)
+      printf("\nprice[%4X] = %d", position - cur + i, p-&gt;opt[i].price);
+    }
+    #endif
+
+  for (;;)
+  {
+    UInt32 numAvailableBytesFull, newLen, numDistancePairs;
+    COptimal *curOpt;
+    UInt32 posPrev;
+    UInt32 state;
+    UInt32 curPrice;
+    Bool nextIsChar;
+    const Byte *data;
+    Byte currentByte, matchByte;
+    UInt32 posState;
+    UInt32 curAnd1Price;
+    COptimal *nextOpt;
+    UInt32 matchPrice, repMatchPrice;  
+    UInt32 numAvailableBytes;
+    UInt32 startLen;
+
+    cur++;
+    if (cur == lenEnd)
+      return Backward(p, backRes, cur);
+
+    numAvailableBytesFull = p-&gt;matchFinder.GetNumAvailableBytes(p-&gt;matchFinderObj);
+    newLen = ReadMatchDistances(p, &amp;numDistancePairs);
+    if (newLen &gt;= p-&gt;numFastBytes)
+    {
+      p-&gt;numDistancePairs = numDistancePairs;
+      p-&gt;longestMatchLength = newLen;
+      p-&gt;longestMatchWasFound = True;
+      return Backward(p, backRes, cur);
+    }
+    position++;
+    curOpt = &amp;p-&gt;opt[cur];
+    posPrev = curOpt-&gt;posPrev;
+    if (curOpt-&gt;prev1IsChar)
+    {
+      posPrev--;
+      if (curOpt-&gt;prev2)
+      {
+        state = p-&gt;opt[curOpt-&gt;posPrev2].state;
+        if (curOpt-&gt;backPrev2 &lt; LZMA_NUM_REPS)
+          state = kRepNextStates[state];
+        else
+          state = kMatchNextStates[state];
+      }
+      else
+        state = p-&gt;opt[posPrev].state;
+      state = kLiteralNextStates[state];
+    }
+    else
+      state = p-&gt;opt[posPrev].state;
+    if (posPrev == cur - 1)
+    {
+      if (IsShortRep(curOpt))
+        state = kShortRepNextStates[state];
+      else
+        state = kLiteralNextStates[state];
+    }
+    else
+    {
+      UInt32 pos;
+      const COptimal *prevOpt;
+      if (curOpt-&gt;prev1IsChar &amp;&amp; curOpt-&gt;prev2)
+      {
+        posPrev = curOpt-&gt;posPrev2;
+        pos = curOpt-&gt;backPrev2;
+        state = kRepNextStates[state];
+      }
+      else
+      {
+        pos = curOpt-&gt;backPrev;
+        if (pos &lt; LZMA_NUM_REPS)
+          state = kRepNextStates[state];
+        else
+          state = kMatchNextStates[state];
+      }
+      prevOpt = &amp;p-&gt;opt[posPrev];
+      if (pos &lt; LZMA_NUM_REPS)
+      {
+        UInt32 i;
+        reps[0] = prevOpt-&gt;backs[pos];
+        for (i = 1; i &lt;= pos; i++)
+          reps[i] = prevOpt-&gt;backs[i - 1];
+        for (; i &lt; LZMA_NUM_REPS; i++)
+          reps[i] = prevOpt-&gt;backs[i];
+      }
+      else
+      {
+        UInt32 i;
+        reps[0] = (pos - LZMA_NUM_REPS);
+        for (i = 1; i &lt; LZMA_NUM_REPS; i++)
+          reps[i] = prevOpt-&gt;backs[i - 1];
+      }
+    }
+    curOpt-&gt;state = (CState)state;
+
+    curOpt-&gt;backs[0] = reps[0];
+    curOpt-&gt;backs[1] = reps[1];
+    curOpt-&gt;backs[2] = reps[2];
+    curOpt-&gt;backs[3] = reps[3];
+
+    curPrice = curOpt-&gt;price; 
+    nextIsChar = False;
+    data = p-&gt;matchFinder.GetPointerToCurrentPos(p-&gt;matchFinderObj) - 1;
+    currentByte = *data;
+    matchByte = *(data - (reps[0] + 1));
+
+    posState = (position &amp; p-&gt;pbMask);
+
+    curAnd1Price = curPrice + GET_PRICE_0(p-&gt;isMatch[state][posState]);
+    {
+      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+      curAnd1Price += 
+        (!IsCharState(state) ? 
+          LitEnc_GetPriceMatched(probs, currentByte, matchByte, p-&gt;ProbPrices) :
+          LitEnc_GetPrice(probs, currentByte, p-&gt;ProbPrices));
+    }   
+
+    nextOpt = &amp;p-&gt;opt[cur + 1];
+
+    if (curAnd1Price &lt; nextOpt-&gt;price) 
+    {
+      nextOpt-&gt;price = curAnd1Price;
+      nextOpt-&gt;posPrev = cur;
+      MakeAsChar(nextOpt);
+      nextIsChar = True;
+    }
+
+    matchPrice = curPrice + GET_PRICE_1(p-&gt;isMatch[state][posState]);
+    repMatchPrice = matchPrice + GET_PRICE_1(p-&gt;isRep[state]);
+    
+    if (matchByte == currentByte &amp;&amp; !(nextOpt-&gt;posPrev &lt; cur &amp;&amp; nextOpt-&gt;backPrev == 0))
+    {
+      UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
+      if (shortRepPrice &lt;= nextOpt-&gt;price)
+      {
+        nextOpt-&gt;price = shortRepPrice;
+        nextOpt-&gt;posPrev = cur;
+        MakeAsShortRep(nextOpt);
+        nextIsChar = True;
+      }
+    }
+
+    {
+      UInt32 temp = kNumOpts - 1 - cur;
+      if (temp &lt;  numAvailableBytesFull)
+        numAvailableBytesFull = temp;
+    }
+    numAvailableBytes = numAvailableBytesFull;
+
+    if (numAvailableBytes &lt; 2)
+      continue;
+    if (numAvailableBytes &gt; p-&gt;numFastBytes)
+      numAvailableBytes = p-&gt;numFastBytes;
+    if (!nextIsChar &amp;&amp; matchByte != currentByte) /* speed optimization */
+    {
+      /* try Literal + rep0 */
+      UInt32 temp;
+      UInt32 lenTest2;
+      const Byte *data2 = data - (reps[0] + 1);
+      UInt32 limit = p-&gt;numFastBytes + 1;
+      if (limit &gt; numAvailableBytesFull)
+        limit = numAvailableBytesFull;
+
+      for (temp = 1; temp &lt; limit &amp;&amp; data[temp] == data2[temp]; temp++);
+      lenTest2 = temp - 1;
+      if (lenTest2 &gt;= 2)
+      {
+        UInt32 state2 = kLiteralNextStates[state];
+        UInt32 posStateNext = (position + 1) &amp; p-&gt;pbMask;
+        UInt32 nextRepMatchPrice = curAnd1Price + 
+            GET_PRICE_1(p-&gt;isMatch[state2][posStateNext]) +
+            GET_PRICE_1(p-&gt;isRep[state2]);
+        /* for (; lenTest2 &gt;= 2; lenTest2--) */
+        {
+          UInt32 curAndLenPrice;
+          COptimal *opt;
+          UInt32 offset = cur + 1 + lenTest2;
+          while (lenEnd &lt; offset)
+            p-&gt;opt[++lenEnd].price = kInfinityPrice;
+          curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+          opt = &amp;p-&gt;opt[offset];
+          if (curAndLenPrice &lt; opt-&gt;price) 
+          {
+            opt-&gt;price = curAndLenPrice;
+            opt-&gt;posPrev = cur + 1;
+            opt-&gt;backPrev = 0;
+            opt-&gt;prev1IsChar = True;
+            opt-&gt;prev2 = False;
+          }
+        }
+      }
+    }
+    
+    startLen = 2; /* speed optimization */
+    {
+    UInt32 repIndex;
+    for (repIndex = 0; repIndex &lt; LZMA_NUM_REPS; repIndex++)
+    {
+      UInt32 lenTest;
+      UInt32 lenTestTemp;
+      UInt32 price;
+      const Byte *data2 = data - (reps[repIndex] + 1);
+      if (data[0] != data2[0] || data[1] != data2[1])
+        continue;
+      for (lenTest = 2; lenTest &lt; numAvailableBytes &amp;&amp; data[lenTest] == data2[lenTest]; lenTest++);
+      while (lenEnd &lt; cur + lenTest)
+        p-&gt;opt[++lenEnd].price = kInfinityPrice;
+      lenTestTemp = lenTest;
+      price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
+      do
+      {
+        UInt32 curAndLenPrice = price + p-&gt;repLenEnc.prices[posState][lenTest - 2];
+        COptimal *opt = &amp;p-&gt;opt[cur + lenTest];
+        if (curAndLenPrice &lt; opt-&gt;price) 
+        {
+          opt-&gt;price = curAndLenPrice;
+          opt-&gt;posPrev = cur;
+          opt-&gt;backPrev = repIndex;
+          opt-&gt;prev1IsChar = False;
+        }
+      }
+      while (--lenTest &gt;= 2);
+      lenTest = lenTestTemp;
+      
+      if (repIndex == 0)
+        startLen = lenTest + 1;
+        
+      /* if (_maxMode) */
+        {
+          UInt32 lenTest2 = lenTest + 1;
+          UInt32 limit = lenTest2 + p-&gt;numFastBytes;
+          UInt32 nextRepMatchPrice;
+          if (limit &gt; numAvailableBytesFull)
+            limit = numAvailableBytesFull;
+          for (; lenTest2 &lt; limit &amp;&amp; data[lenTest2] == data2[lenTest2]; lenTest2++);
+          lenTest2 -= lenTest + 1;
+          if (lenTest2 &gt;= 2)
+          {
+            UInt32 state2 = kRepNextStates[state];
+            UInt32 posStateNext = (position + lenTest) &amp; p-&gt;pbMask;
+            UInt32 curAndLenCharPrice = 
+                price + p-&gt;repLenEnc.prices[posState][lenTest - 2] + 
+                GET_PRICE_0(p-&gt;isMatch[state2][posStateNext]) +
+                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
+                    data[lenTest], data2[lenTest], p-&gt;ProbPrices);
+            state2 = kLiteralNextStates[state2];
+            posStateNext = (position + lenTest + 1) &amp; p-&gt;pbMask;
+            nextRepMatchPrice = curAndLenCharPrice + 
+                GET_PRICE_1(p-&gt;isMatch[state2][posStateNext]) +
+                GET_PRICE_1(p-&gt;isRep[state2]);
+            
+            /* for (; lenTest2 &gt;= 2; lenTest2--) */
+            {
+              UInt32 curAndLenPrice;
+              COptimal *opt;
+              UInt32 offset = cur + lenTest + 1 + lenTest2;
+              while (lenEnd &lt; offset)
+                p-&gt;opt[++lenEnd].price = kInfinityPrice;
+              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+              opt = &amp;p-&gt;opt[offset];
+              if (curAndLenPrice &lt; opt-&gt;price) 
+              {
+                opt-&gt;price = curAndLenPrice;
+                opt-&gt;posPrev = cur + lenTest + 1;
+                opt-&gt;backPrev = 0;
+                opt-&gt;prev1IsChar = True;
+                opt-&gt;prev2 = True;
+                opt-&gt;posPrev2 = cur;
+                opt-&gt;backPrev2 = repIndex;
+              }
+            }
+          }
+        }
+    }
+    }
+    /* for (UInt32 lenTest = 2; lenTest &lt;= newLen; lenTest++) */
+    if (newLen &gt; numAvailableBytes)
+    {
+      newLen = numAvailableBytes;
+      for (numDistancePairs = 0; newLen &gt; matchDistances[numDistancePairs]; numDistancePairs += 2);
+      matchDistances[numDistancePairs] = newLen;
+      numDistancePairs += 2;
+    }
+    if (newLen &gt;= startLen)
+    {
+      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p-&gt;isRep[state]);
+      UInt32 offs, curBack, posSlot;
+      UInt32 lenTest;
+      while (lenEnd &lt; cur + newLen)
+        p-&gt;opt[++lenEnd].price = kInfinityPrice;
+
+      offs = 0;
+      while (startLen &gt; matchDistances[offs])
+        offs += 2;
+      curBack = matchDistances[offs + 1];
+      GetPosSlot2(curBack, posSlot);
+      for (lenTest = /*2*/ startLen; ; lenTest++)
+      {
+        UInt32 curAndLenPrice = normalMatchPrice + p-&gt;lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
+        UInt32 lenToPosState = GetLenToPosState(lenTest);
+        COptimal *opt;
+        if (curBack &lt; kNumFullDistances)
+          curAndLenPrice += p-&gt;distancesPrices[lenToPosState][curBack];
+        else
+          curAndLenPrice += p-&gt;posSlotPrices[lenToPosState][posSlot] + p-&gt;alignPrices[curBack &amp; kAlignMask];
+        
+        opt = &amp;p-&gt;opt[cur + lenTest];
+        if (curAndLenPrice &lt; opt-&gt;price) 
+        {
+          opt-&gt;price = curAndLenPrice;
+          opt-&gt;posPrev = cur;
+          opt-&gt;backPrev = curBack + LZMA_NUM_REPS;
+          opt-&gt;prev1IsChar = False;
+        }
+
+        if (/*_maxMode &amp;&amp; */lenTest == matchDistances[offs])
+        {
+          /* Try Match + Literal + Rep0 */
+          const Byte *data2 = data - (curBack + 1);
+          UInt32 lenTest2 = lenTest + 1;
+          UInt32 limit = lenTest2 + p-&gt;numFastBytes;
+          UInt32 nextRepMatchPrice;
+          if (limit &gt; numAvailableBytesFull)
+            limit = numAvailableBytesFull;
+          for (; lenTest2 &lt; limit &amp;&amp; data[lenTest2] == data2[lenTest2]; lenTest2++);
+          lenTest2 -= lenTest + 1;
+          if (lenTest2 &gt;= 2)
+          {
+            UInt32 state2 = kMatchNextStates[state];
+            UInt32 posStateNext = (position + lenTest) &amp; p-&gt;pbMask;
+            UInt32 curAndLenCharPrice = curAndLenPrice + 
+                GET_PRICE_0(p-&gt;isMatch[state2][posStateNext]) +
+                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
+                    data[lenTest], data2[lenTest], p-&gt;ProbPrices);
+            state2 = kLiteralNextStates[state2];
+            posStateNext = (posStateNext + 1) &amp; p-&gt;pbMask;
+            nextRepMatchPrice = curAndLenCharPrice + 
+                GET_PRICE_1(p-&gt;isMatch[state2][posStateNext]) +
+                GET_PRICE_1(p-&gt;isRep[state2]);
+            
+            /* for (; lenTest2 &gt;= 2; lenTest2--) */
+            {
+              UInt32 offset = cur + lenTest + 1 + lenTest2;
+              UInt32 curAndLenPrice;
+              COptimal *opt;
+              while (lenEnd &lt; offset)
+                p-&gt;opt[++lenEnd].price = kInfinityPrice;
+              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+              opt = &amp;p-&gt;opt[offset];
+              if (curAndLenPrice &lt; opt-&gt;price) 
+              {
+                opt-&gt;price = curAndLenPrice;
+                opt-&gt;posPrev = cur + lenTest + 1;
+                opt-&gt;backPrev = 0;
+                opt-&gt;prev1IsChar = True;
+                opt-&gt;prev2 = True;
+                opt-&gt;posPrev2 = cur;
+                opt-&gt;backPrev2 = curBack + LZMA_NUM_REPS;
+              }
+            }
+          }
+          offs += 2;
+          if (offs == numDistancePairs)
+            break;
+          curBack = matchDistances[offs + 1];
+          if (curBack &gt;= kNumFullDistances)
+            GetPosSlot2(curBack, posSlot);
+        }
+      }
+    }
+  }
+}
+
+#define ChangePair(smallDist, bigDist) (((bigDist) &gt;&gt; 7) &gt; (smallDist))
+
+static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
+{
+  UInt32 numAvailableBytes = p-&gt;matchFinder.GetNumAvailableBytes(p-&gt;matchFinderObj);
+  UInt32 lenMain, numDistancePairs;
+  const Byte *data;
+  UInt32 repLens[LZMA_NUM_REPS];
+  UInt32 repMaxIndex, i;
+  UInt32 *matchDistances;
+  UInt32 backMain;
+
+  if (!p-&gt;longestMatchWasFound)
+  {
+    lenMain = ReadMatchDistances(p, &amp;numDistancePairs);
+  }
+  else
+  {
+    lenMain = p-&gt;longestMatchLength;
+    numDistancePairs = p-&gt;numDistancePairs;
+    p-&gt;longestMatchWasFound = False;
+  }
+
+  data = p-&gt;matchFinder.GetPointerToCurrentPos(p-&gt;matchFinderObj) - 1;
+  if (numAvailableBytes &gt; LZMA_MATCH_LEN_MAX)
+    numAvailableBytes = LZMA_MATCH_LEN_MAX;
+  if (numAvailableBytes &lt; 2)
+  {
+    *backRes = (UInt32)(-1);
+    return 1;
+  }
+
+  repMaxIndex = 0;
+
+  for (i = 0; i &lt; LZMA_NUM_REPS; i++)
+  {
+    const Byte *data2 = data - (p-&gt;reps[i] + 1);
+    UInt32 len;
+    if (data[0] != data2[0] || data[1] != data2[1])
+    {
+      repLens[i] = 0;
+      continue;
+    }
+    for (len = 2; len &lt; numAvailableBytes &amp;&amp; data[len] == data2[len]; len++);
+    if (len &gt;= p-&gt;numFastBytes)
+    {
+      *backRes = i;
+      MovePos(p, len - 1);
+      return len;
+    }
+    repLens[i] = len;
+    if (len &gt; repLens[repMaxIndex])
+      repMaxIndex = i;
+  }
+  matchDistances = p-&gt;matchDistances;
+  if (lenMain &gt;= p-&gt;numFastBytes)
+  {
+    *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS; 
+    MovePos(p, lenMain - 1);
+    return lenMain;
+  }
+
+  backMain = 0; /* for GCC */
+  if (lenMain &gt;= 2)
+  {
+    backMain = matchDistances[numDistancePairs - 1];
+    while (numDistancePairs &gt; 2 &amp;&amp; lenMain == matchDistances[numDistancePairs - 4] + 1)
+    {
+      if (!ChangePair(matchDistances[numDistancePairs - 3], backMain))
+        break;
+      numDistancePairs -= 2;
+      lenMain = matchDistances[numDistancePairs - 2];
+      backMain = matchDistances[numDistancePairs - 1];
+    }
+    if (lenMain == 2 &amp;&amp; backMain &gt;= 0x80)
+      lenMain = 1;
+  }
+
+  if (repLens[repMaxIndex] &gt;= 2)
+  {
+    if (repLens[repMaxIndex] + 1 &gt;= lenMain || 
+        (repLens[repMaxIndex] + 2 &gt;= lenMain &amp;&amp; (backMain &gt; (1 &lt;&lt; 9))) ||
+        (repLens[repMaxIndex] + 3 &gt;= lenMain &amp;&amp; (backMain &gt; (1 &lt;&lt; 15))))
+    {
+      UInt32 lenRes;
+      *backRes = repMaxIndex;
+      lenRes = repLens[repMaxIndex];
+      MovePos(p, lenRes - 1);
+      return lenRes;
+    }
+  }
+  
+  if (lenMain &gt;= 2 &amp;&amp; numAvailableBytes &gt; 2)
+  {
+    UInt32 i;
+    numAvailableBytes = p-&gt;matchFinder.GetNumAvailableBytes(p-&gt;matchFinderObj);
+    p-&gt;longestMatchLength = ReadMatchDistances(p, &amp;p-&gt;numDistancePairs);
+    if (p-&gt;longestMatchLength &gt;= 2)
+    {
+      UInt32 newDistance = matchDistances[p-&gt;numDistancePairs - 1];
+      if ((p-&gt;longestMatchLength &gt;= lenMain &amp;&amp; newDistance &lt; backMain) || 
+          (p-&gt;longestMatchLength == lenMain + 1 &amp;&amp; !ChangePair(backMain, newDistance)) ||
+          (p-&gt;longestMatchLength &gt; lenMain + 1) ||
+          (p-&gt;longestMatchLength + 1 &gt;= lenMain &amp;&amp; lenMain &gt;= 3 &amp;&amp; ChangePair(newDistance, backMain)))
+      {
+        p-&gt;longestMatchWasFound = True;
+        *backRes = (UInt32)(-1);
+        return 1;
+      }
+    }
+    data = p-&gt;matchFinder.GetPointerToCurrentPos(p-&gt;matchFinderObj) - 1;
+    for (i = 0; i &lt; LZMA_NUM_REPS; i++)
+    {
+      UInt32 len;
+      const Byte *data2 = data - (p-&gt;reps[i] + 1);
+      if (data[1] != data2[1] || data[2] != data2[2])
+      {
+        repLens[i] = 0;
+        continue;
+      }
+      for (len = 2; len &lt; numAvailableBytes &amp;&amp; data[len] == data2[len]; len++);
+      if (len + 1 &gt;= lenMain)
+      {
+        p-&gt;longestMatchWasFound = True;
+        *backRes = (UInt32)(-1);
+        return 1;
+      }
+    }
+    *backRes = backMain + LZMA_NUM_REPS; 
+    MovePos(p, lenMain - 2);
+    return lenMain;
+  }
+  *backRes = (UInt32)(-1);
+  return 1;
+}
+
+static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
+{
+  UInt32 len;
+  RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isMatch[p-&gt;state][posState], 1);
+  RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isRep[p-&gt;state], 0);
+  p-&gt;state = kMatchNextStates[p-&gt;state];
+  len = LZMA_MATCH_LEN_MIN;
+  LenEnc_Encode2(&amp;p-&gt;lenEnc, &amp;p-&gt;rc, len - LZMA_MATCH_LEN_MIN, posState, !p-&gt;fastMode, p-&gt;ProbPrices);
+  RcTree_Encode(&amp;p-&gt;rc, p-&gt;posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 &lt;&lt; kNumPosSlotBits) - 1);
+  RangeEnc_EncodeDirectBits(&amp;p-&gt;rc, (((UInt32)1 &lt;&lt; 30) - 1) &gt;&gt; kNumAlignBits, 30 - kNumAlignBits);
+  RcTree_ReverseEncode(&amp;p-&gt;rc, p-&gt;posAlignEncoder, kNumAlignBits, kAlignMask);
+}
+
+static SRes CheckErrors(CLzmaEnc *p)
+{
+  if (p-&gt;result != SZ_OK)
+    return p-&gt;result;
+  if (p-&gt;rc.res != SZ_OK)
+    p-&gt;result = SZ_ERROR_WRITE;
+  if (p-&gt;matchFinderBase.result != SZ_OK)
+    p-&gt;result = SZ_ERROR_READ;
+  if (p-&gt;result != SZ_OK)
+    p-&gt;finished = True;
+  return p-&gt;result;
+}
+
+static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
+{
+  /* ReleaseMFStream(); */
+  p-&gt;finished = True;
+  if (p-&gt;writeEndMark)
+    WriteEndMarker(p, nowPos &amp; p-&gt;pbMask);
+  RangeEnc_FlushData(&amp;p-&gt;rc);
+  RangeEnc_FlushStream(&amp;p-&gt;rc);
+  return CheckErrors(p);
+}
+
+static void FillAlignPrices(CLzmaEnc *p)
+{
+  UInt32 i;
+  for (i = 0; i &lt; kAlignTableSize; i++)
+    p-&gt;alignPrices[i] = RcTree_ReverseGetPrice(p-&gt;posAlignEncoder, kNumAlignBits, i, p-&gt;ProbPrices);
+  p-&gt;alignPriceCount = 0;
+}
+
+static void FillDistancesPrices(CLzmaEnc *p)
+{
+  UInt32 tempPrices[kNumFullDistances];
+  UInt32 i, lenToPosState;
+  for (i = kStartPosModelIndex; i &lt; kNumFullDistances; i++)
+  { 
+    UInt32 posSlot = GetPosSlot1(i);
+    UInt32 footerBits = ((posSlot &gt;&gt; 1) - 1);
+    UInt32 base = ((2 | (posSlot &amp; 1)) &lt;&lt; footerBits);
+    tempPrices[i] = RcTree_ReverseGetPrice(p-&gt;posEncoders + base - posSlot - 1, footerBits, i - base, p-&gt;ProbPrices);
+  }
+
+  for (lenToPosState = 0; lenToPosState &lt; kNumLenToPosStates; lenToPosState++)
+  {
+    UInt32 posSlot;
+    const CLzmaProb *encoder = p-&gt;posSlotEncoder[lenToPosState];
+    UInt32 *posSlotPrices = p-&gt;posSlotPrices[lenToPosState];
+    for (posSlot = 0; posSlot &lt; p-&gt;distTableSize; posSlot++)
+      posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p-&gt;ProbPrices);
+    for (posSlot = kEndPosModelIndex; posSlot &lt; p-&gt;distTableSize; posSlot++)
+      posSlotPrices[posSlot] += ((((posSlot &gt;&gt; 1) - 1) - kNumAlignBits) &lt;&lt; kNumBitPriceShiftBits);
+
+    {
+      UInt32 *distancesPrices = p-&gt;distancesPrices[lenToPosState];
+      UInt32 i;
+      for (i = 0; i &lt; kStartPosModelIndex; i++)
+        distancesPrices[i] = posSlotPrices[i];
+      for (; i &lt; kNumFullDistances; i++)
+        distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
+    }
+  }
+  p-&gt;matchPriceCount = 0;
+}
+
+static void LzmaEnc_Construct(CLzmaEnc *p)
+{
+  RangeEnc_Construct(&amp;p-&gt;rc);
+  MatchFinder_Construct(&amp;p-&gt;matchFinderBase);
+  #ifdef COMPRESS_MF_MT
+  MatchFinderMt_Construct(&amp;p-&gt;matchFinderMt);
+  p-&gt;matchFinderMt.MatchFinder = &amp;p-&gt;matchFinderBase;
+  #endif
+
+  {
+    CLzmaEncProps props;
+    LzmaEncProps_Init(&amp;props);
+    LzmaEnc_SetProps(p, &amp;props);
+  }
+
+  #ifndef LZMA_LOG_BSR
+  LzmaEnc_FastPosInit(p-&gt;g_FastPos);
+  #endif
+
+  LzmaEnc_InitPriceTables(p-&gt;ProbPrices);
+  p-&gt;litProbs = 0;
+  p-&gt;saveState.litProbs = 0;
+}
+
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
+{
+  void *p;
+  p = alloc-&gt;Alloc(alloc, sizeof(CLzmaEnc));
+  if (p != 0)
+    LzmaEnc_Construct((CLzmaEnc *)p);
+  return p;
+}
+
+static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
+{
+  alloc-&gt;Free(alloc, p-&gt;litProbs);
+  alloc-&gt;Free(alloc, p-&gt;saveState.litProbs);
+  p-&gt;litProbs = 0;
+  p-&gt;saveState.litProbs = 0;
+}
+
+static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  #ifdef COMPRESS_MF_MT
+  MatchFinderMt_Destruct(&amp;p-&gt;matchFinderMt, allocBig);
+  #endif
+  MatchFinder_Free(&amp;p-&gt;matchFinderBase, allocBig);
+  LzmaEnc_FreeLits(p, alloc);
+  RangeEnc_Free(&amp;p-&gt;rc, alloc);
+}
+
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
+  alloc-&gt;Free(alloc, p);
+}
+
+static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
+{
+  UInt32 nowPos32, startPos32;
+  if (p-&gt;inStream != 0)
+  {
+    p-&gt;matchFinderBase.stream = p-&gt;inStream;
+    p-&gt;matchFinder.Init(p-&gt;matchFinderObj);
+    p-&gt;inStream = 0;
+  }
+
+  if (p-&gt;finished)
+    return p-&gt;result;
+  RINOK(CheckErrors(p));
+
+  nowPos32 = (UInt32)p-&gt;nowPos64;
+  startPos32 = nowPos32;
+
+  if (p-&gt;nowPos64 == 0)
+  {
+    UInt32 numDistancePairs;
+    Byte curByte;
+    if (p-&gt;matchFinder.GetNumAvailableBytes(p-&gt;matchFinderObj) == 0)
+      return Flush(p, nowPos32);
+    ReadMatchDistances(p, &amp;numDistancePairs);
+    RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isMatch[p-&gt;state][0], 0);
+    p-&gt;state = kLiteralNextStates[p-&gt;state];
+    curByte = p-&gt;matchFinder.GetIndexByte(p-&gt;matchFinderObj, 0 - p-&gt;additionalOffset);
+    LitEnc_Encode(&amp;p-&gt;rc, p-&gt;litProbs, curByte);
+    p-&gt;additionalOffset--;
+    nowPos32++;
+  }
+
+  if (p-&gt;matchFinder.GetNumAvailableBytes(p-&gt;matchFinderObj) != 0)
+  for (;;)
+  {
+    UInt32 pos, len, posState;
+
+    if (p-&gt;fastMode)
+      len = GetOptimumFast(p, &amp;pos);
+    else
+      len = GetOptimum(p, nowPos32, &amp;pos);
+
+    #ifdef SHOW_STAT2
+    printf("\n pos = %4X,   len = %d   pos = %d", nowPos32, len, pos);
+    #endif
+
+    posState = nowPos32 &amp; p-&gt;pbMask;
+    if (len == 1 &amp;&amp; pos == 0xFFFFFFFF)
+    {
+      Byte curByte;
+      CLzmaProb *probs;
+      const Byte *data;
+
+      RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isMatch[p-&gt;state][posState], 0);
+      data = p-&gt;matchFinder.GetPointerToCurrentPos(p-&gt;matchFinderObj) - p-&gt;additionalOffset;
+      curByte = *data;
+      probs = LIT_PROBS(nowPos32, *(data - 1));
+      if (IsCharState(p-&gt;state))
+        LitEnc_Encode(&amp;p-&gt;rc, probs, curByte);
+      else
+        LitEnc_EncodeMatched(&amp;p-&gt;rc, probs, curByte, *(data - p-&gt;reps[0] - 1));
+      p-&gt;state = kLiteralNextStates[p-&gt;state];
+    }
+    else
+    {
+      RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isMatch[p-&gt;state][posState], 1);
+      if (pos &lt; LZMA_NUM_REPS)
+      {
+        RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isRep[p-&gt;state], 1);
+        if (pos == 0)
+        {
+          RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isRepG0[p-&gt;state], 0);
+          RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isRep0Long[p-&gt;state][posState], ((len == 1) ? 0 : 1));
+        }
+        else
+        {
+          UInt32 distance = p-&gt;reps[pos];
+          RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isRepG0[p-&gt;state], 1);
+          if (pos == 1)
+            RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isRepG1[p-&gt;state], 0);
+          else
+          {
+            RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isRepG1[p-&gt;state], 1);
+            RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isRepG2[p-&gt;state], pos - 2);
+            if (pos == 3)
+              p-&gt;reps[3] = p-&gt;reps[2];
+            p-&gt;reps[2] = p-&gt;reps[1];
+          }
+          p-&gt;reps[1] = p-&gt;reps[0];
+          p-&gt;reps[0] = distance;
+        }
+        if (len == 1)
+          p-&gt;state = kShortRepNextStates[p-&gt;state];
+        else
+        {
+          LenEnc_Encode2(&amp;p-&gt;repLenEnc, &amp;p-&gt;rc, len - LZMA_MATCH_LEN_MIN, posState, !p-&gt;fastMode, p-&gt;ProbPrices);
+          p-&gt;state = kRepNextStates[p-&gt;state];
+        }
+      }
+      else
+      {
+        UInt32 posSlot;
+        RangeEnc_EncodeBit(&amp;p-&gt;rc, &amp;p-&gt;isRep[p-&gt;state], 0);
+        p-&gt;state = kMatchNextStates[p-&gt;state];
+        LenEnc_Encode2(&amp;p-&gt;lenEnc, &amp;p-&gt;rc, len - LZMA_MATCH_LEN_MIN, posState, !p-&gt;fastMode, p-&gt;ProbPrices);
+        pos -= LZMA_NUM_REPS;
+        GetPosSlot(pos, posSlot);
+        RcTree_Encode(&amp;p-&gt;rc, p-&gt;posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
+        
+        if (posSlot &gt;= kStartPosModelIndex)
+        {
+          UInt32 footerBits = ((posSlot &gt;&gt; 1) - 1);
+          UInt32 base = ((2 | (posSlot &amp; 1)) &lt;&lt; footerBits);
+          UInt32 posReduced = pos - base;
+
+          if (posSlot &lt; kEndPosModelIndex)
+            RcTree_ReverseEncode(&amp;p-&gt;rc, p-&gt;posEncoders + base - posSlot - 1, footerBits, posReduced);
+          else
+          {
+            RangeEnc_EncodeDirectBits(&amp;p-&gt;rc, posReduced &gt;&gt; kNumAlignBits, footerBits - kNumAlignBits);
+            RcTree_ReverseEncode(&amp;p-&gt;rc, p-&gt;posAlignEncoder, kNumAlignBits, posReduced &amp; kAlignMask);
+            p-&gt;alignPriceCount++;
+          }
+        }
+        p-&gt;reps[3] = p-&gt;reps[2];
+        p-&gt;reps[2] = p-&gt;reps[1];
+        p-&gt;reps[1] = p-&gt;reps[0];
+        p-&gt;reps[0] = pos;
+        p-&gt;matchPriceCount++;
+      }
+    }
+    p-&gt;additionalOffset -= len;
+    nowPos32 += len;
+    if (p-&gt;additionalOffset == 0)
+    {
+      UInt32 processed;
+      if (!p-&gt;fastMode)
+      {
+        if (p-&gt;matchPriceCount &gt;= (1 &lt;&lt; 7))
+          FillDistancesPrices(p);
+        if (p-&gt;alignPriceCount &gt;= kAlignTableSize)
+          FillAlignPrices(p);
+      }
+      if (p-&gt;matchFinder.GetNumAvailableBytes(p-&gt;matchFinderObj) == 0)
+        break;
+      processed = nowPos32 - startPos32;
+      if (useLimits)
+      {
+        if (processed + kNumOpts + 300 &gt;= maxUnpackSize ||
+            RangeEnc_GetProcessed(&amp;p-&gt;rc) + kNumOpts * 2 &gt;= maxPackSize)
+          break;
+      }
+      else if (processed &gt;= (1 &lt;&lt; 15))
+      {
+        p-&gt;nowPos64 += nowPos32 - startPos32;
+        return CheckErrors(p);
+      }
+    }
+  }
+  p-&gt;nowPos64 += nowPos32 - startPos32;
+  return Flush(p, nowPos32);
+}
+
+#define kBigHashDicLimit ((UInt32)1 &lt;&lt; 24)
+
+static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  UInt32 beforeSize = kNumOpts;
+  Bool btMode;
+  if (!RangeEnc_Alloc(&amp;p-&gt;rc, alloc))
+    return SZ_ERROR_MEM;
+  btMode = (p-&gt;matchFinderBase.btMode != 0);
+  #ifdef COMPRESS_MF_MT
+  p-&gt;mtMode = (p-&gt;multiThread &amp;&amp; !p-&gt;fastMode &amp;&amp; btMode);
+  #endif
+
+  {
+    unsigned lclp = p-&gt;lc + p-&gt;lp;
+    if (p-&gt;litProbs == 0 || p-&gt;saveState.litProbs == 0 || p-&gt;lclp != lclp)
+    {
+      LzmaEnc_FreeLits(p, alloc);
+      p-&gt;litProbs = (CLzmaProb *)alloc-&gt;Alloc(alloc, (0x300 &lt;&lt; lclp) * sizeof(CLzmaProb));
+      p-&gt;saveState.litProbs = (CLzmaProb *)alloc-&gt;Alloc(alloc, (0x300 &lt;&lt; lclp) * sizeof(CLzmaProb));
+      if (p-&gt;litProbs == 0 || p-&gt;saveState.litProbs == 0)
+      {
+        LzmaEnc_FreeLits(p, alloc);
+        return SZ_ERROR_MEM;
+      }
+      p-&gt;lclp = lclp;
+    }
+  }
+
+  p-&gt;matchFinderBase.bigHash = (p-&gt;dictSize &gt; kBigHashDicLimit);
+
+  if (beforeSize + p-&gt;dictSize &lt; keepWindowSize)
+    beforeSize = keepWindowSize - p-&gt;dictSize;
+
+  #ifdef COMPRESS_MF_MT
+  if (p-&gt;mtMode)
+  {
+    RINOK(MatchFinderMt_Create(&amp;p-&gt;matchFinderMt, p-&gt;dictSize, beforeSize, p-&gt;numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
+    p-&gt;matchFinderObj = &amp;p-&gt;matchFinderMt;
+    MatchFinderMt_CreateVTable(&amp;p-&gt;matchFinderMt, &amp;p-&gt;matchFinder);
+  }
+  else
+  #endif
+  {
+    if (!MatchFinder_Create(&amp;p-&gt;matchFinderBase, p-&gt;dictSize, beforeSize, p-&gt;numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
+      return SZ_ERROR_MEM;
+    p-&gt;matchFinderObj = &amp;p-&gt;matchFinderBase;
+    MatchFinder_CreateVTable(&amp;p-&gt;matchFinderBase, &amp;p-&gt;matchFinder);
+  }
+  return SZ_OK;
+}
+
+static void LzmaEnc_Init(CLzmaEnc *p)
+{
+  UInt32 i;
+  p-&gt;state = 0;
+  for(i = 0 ; i &lt; LZMA_NUM_REPS; i++)
+    p-&gt;reps[i] = 0;
+
+  RangeEnc_Init(&amp;p-&gt;rc);
+
+
+  for (i = 0; i &lt; kNumStates; i++)
+  {
+    UInt32 j;
+    for (j = 0; j &lt; LZMA_NUM_PB_STATES_MAX; j++)
+    {
+      p-&gt;isMatch[i][j] = kProbInitValue;
+      p-&gt;isRep0Long[i][j] = kProbInitValue;
+    }
+    p-&gt;isRep[i] = kProbInitValue;
+    p-&gt;isRepG0[i] = kProbInitValue;
+    p-&gt;isRepG1[i] = kProbInitValue;
+    p-&gt;isRepG2[i] = kProbInitValue;
+  }
+
+  {
+    UInt32 num = 0x300 &lt;&lt; (p-&gt;lp + p-&gt;lc);
+    for (i = 0; i &lt; num; i++)
+      p-&gt;litProbs[i] = kProbInitValue;
+  }
+
+  {
+    for (i = 0; i &lt; kNumLenToPosStates; i++)
+    {
+      CLzmaProb *probs = p-&gt;posSlotEncoder[i];
+      UInt32 j;
+      for (j = 0; j &lt; (1 &lt;&lt; kNumPosSlotBits); j++)
+        probs[j] = kProbInitValue;
+    }
+  }
+  {
+    for(i = 0; i &lt; kNumFullDistances - kEndPosModelIndex; i++)
+      p-&gt;posEncoders[i] = kProbInitValue;
+  }
+
+  LenEnc_Init(&amp;p-&gt;lenEnc.p);
+  LenEnc_Init(&amp;p-&gt;repLenEnc.p);
+
+  for (i = 0; i &lt; (1 &lt;&lt; kNumAlignBits); i++)
+    p-&gt;posAlignEncoder[i] = kProbInitValue;
+
+  p-&gt;longestMatchWasFound = False;
+  p-&gt;optimumEndIndex = 0;
+  p-&gt;optimumCurrentIndex = 0;
+  p-&gt;additionalOffset = 0;
+
+  p-&gt;pbMask = (1 &lt;&lt; p-&gt;pb) - 1;
+  p-&gt;lpMask = (1 &lt;&lt; p-&gt;lp) - 1;
+}
+
+static void LzmaEnc_InitPrices(CLzmaEnc *p)
+{
+  if (!p-&gt;fastMode)
+  {
+    FillDistancesPrices(p);
+    FillAlignPrices(p);
+  }
+
+  p-&gt;lenEnc.tableSize = 
+  p-&gt;repLenEnc.tableSize = 
+      p-&gt;numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
+  LenPriceEnc_UpdateTables(&amp;p-&gt;lenEnc, 1 &lt;&lt; p-&gt;pb, p-&gt;ProbPrices);
+  LenPriceEnc_UpdateTables(&amp;p-&gt;repLenEnc, 1 &lt;&lt; p-&gt;pb, p-&gt;ProbPrices);
+}
+
+static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  UInt32 i;
+  for (i = 0; i &lt; (UInt32)kDicLogSizeMaxCompress; i++)
+    if (p-&gt;dictSize &lt;= ((UInt32)1 &lt;&lt; i))
+      break;
+  p-&gt;distTableSize = i * 2;
+
+  p-&gt;finished = False;
+  p-&gt;result = SZ_OK;
+  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
+  LzmaEnc_Init(p);
+  LzmaEnc_InitPrices(p);
+  p-&gt;nowPos64 = 0;
+  return SZ_OK;
+}
+
+static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream,
+    ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  p-&gt;inStream = inStream;
+  p-&gt;rc.outStream = outStream;
+  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
+}
+
+static SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, 
+    ISeqInStream *inStream, UInt32 keepWindowSize,
+    ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  p-&gt;inStream = inStream;
+  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
+{
+  p-&gt;seqBufInStream.funcTable.Read = MyRead;
+  p-&gt;seqBufInStream.data = src;
+  p-&gt;seqBufInStream.rem = srcLen;
+}
+
+static SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
+    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  LzmaEnc_SetInputBuf(p, src, srcLen);
+  p-&gt;inStream = &amp;p-&gt;seqBufInStream.funcTable;
+  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+static void LzmaEnc_Finish(CLzmaEncHandle pp)
+{
+  #ifdef COMPRESS_MF_MT
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  if (p-&gt;mtMode)
+    MatchFinderMt_ReleaseStream(&amp;p-&gt;matchFinderMt);
+  #endif
+}
+
+typedef struct _CSeqOutStreamBuf
+{
+  ISeqOutStream funcTable;
+  Byte *data;
+  SizeT rem;
+  Bool overflow;
+} CSeqOutStreamBuf;
+
+static size_t MyWrite(void *pp, const void *data, size_t size)
+{
+  CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
+  if (p-&gt;rem &lt; size)
+  {
+    size = p-&gt;rem;
+    p-&gt;overflow = True;
+  }
+  memcpy(p-&gt;data, data, size);
+  p-&gt;rem -= size;
+  p-&gt;data += size;
+  return size;
+}
+
+
+static UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
+{
+  const CLzmaEnc *p = (CLzmaEnc *)pp;
+  return p-&gt;matchFinder.GetNumAvailableBytes(p-&gt;matchFinderObj);
+}
+
+static const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
+{
+  const CLzmaEnc *p = (CLzmaEnc *)pp;
+  return p-&gt;matchFinder.GetPointerToCurrentPos(p-&gt;matchFinderObj) - p-&gt;additionalOffset;
+}
+
+static SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, 
+    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  UInt64 nowPos64;
+  SRes res;
+  CSeqOutStreamBuf outStream;
+
+  outStream.funcTable.Write = MyWrite;
+  outStream.data = dest;
+  outStream.rem = *destLen;
+  outStream.overflow = False;
+
+  p-&gt;writeEndMark = False;
+  p-&gt;finished = False;
+  p-&gt;result = SZ_OK;
+
+  if (reInit)
+    LzmaEnc_Init(p);
+  LzmaEnc_InitPrices(p);
+  nowPos64 = p-&gt;nowPos64;
+  RangeEnc_Init(&amp;p-&gt;rc);
+  p-&gt;rc.outStream = &amp;outStream.funcTable;
+
+  res = LzmaEnc_CodeOneBlock(pp, True, desiredPackSize, *unpackSize);
+  
+  *unpackSize = (UInt32)(p-&gt;nowPos64 - nowPos64);
+  *destLen -= outStream.rem;
+  if (outStream.overflow)
+    return SZ_ERROR_OUTPUT_EOF;
+
+  return res;
+}
+
+SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
+    ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  SRes res = SZ_OK;
+
+  #ifdef COMPRESS_MF_MT
+  Byte allocaDummy[0x300];
+  int i = 0;
+  for (i = 0; i &lt; 16; i++)
+    allocaDummy[i] = (Byte)i;
+  #endif
+
+  RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig));
+
+  for (;;)
+  {
+    res = LzmaEnc_CodeOneBlock(pp, False, 0, 0);
+    if (res != SZ_OK || p-&gt;finished != 0)
+      break;
+    if (progress != 0)
+    {
+      res = progress-&gt;Progress(progress, p-&gt;nowPos64, RangeEnc_GetProcessed(&amp;p-&gt;rc));
+      if (res != SZ_OK)
+      {
+        res = SZ_ERROR_PROGRESS;
+        break;
+      }
+    }
+  }
+  LzmaEnc_Finish(pp);
+  return res;
+}
+
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  int i;
+  UInt32 dictSize = p-&gt;dictSize;
+  if (*size &lt; LZMA_PROPS_SIZE)
+    return SZ_ERROR_PARAM;
+  *size = LZMA_PROPS_SIZE;
+  props[0] = (Byte)((p-&gt;pb * 5 + p-&gt;lp) * 9 + p-&gt;lc);
+
+  for (i = 11; i &lt;= 30; i++)
+  {
+    if (dictSize &lt;= ((UInt32)2 &lt;&lt; i))
+    {
+      dictSize = (2 &lt;&lt; i);
+      break;
+    }
+    if (dictSize &lt;= ((UInt32)3 &lt;&lt; i))
+    {
+      dictSize = (3 &lt;&lt; i);
+      break;
+    }
+  }
+
+  for (i = 0; i &lt; 4; i++)
+    props[1 + i] = (Byte)(dictSize &gt;&gt; (8 * i));
+  return SZ_OK;
+}
+
+SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  SRes res;
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+
+  CSeqOutStreamBuf outStream;
+
+  LzmaEnc_SetInputBuf(p, src, srcLen);
+
+  outStream.funcTable.Write = MyWrite;
+  outStream.data = dest;
+  outStream.rem = *destLen;
+  outStream.overflow = False;
+
+  p-&gt;writeEndMark = writeEndMark;
+  res = LzmaEnc_Encode(pp, &amp;outStream.funcTable, &amp;p-&gt;seqBufInStream.funcTable, 
+      progress, alloc, allocBig);
+
+  *destLen -= outStream.rem;
+  if (outStream.overflow)
+    return SZ_ERROR_OUTPUT_EOF;
+  return res;
+}
+
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, 
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
+  SRes res;
+  if (p == 0)
+    return SZ_ERROR_MEM;
+
+  res = LzmaEnc_SetProps(p, props);
+  if (res == SZ_OK)
+  {
+    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
+    if (res == SZ_OK)
+      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
+          writeEndMark, progress, alloc, allocBig);
+  }
+
+  LzmaEnc_Destroy(p, alloc, allocBig);
+  return res;
+}
--- a/jffsX-utils/mkfs.jffs2.c
+++ b/jffsX-utils/mkfs.jffs2.c
@@ -1667,11 +1667,11 @@ int main(int argc, char **argv)
 						  }
 						  erase_block_size *= units;
 
-						  /* If it's less than 8KiB, they're not allowed */
-						  if (erase_block_size &lt; 0x2000) {
-							  fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n",
+						  /* If it's less than 4KiB, they're not allowed */
+						  if (erase_block_size &lt; 0x1000) {
+							  fprintf(stderr, "Erase size 0x%x too small. Increasing to 4KiB minimum\n",
 									  erase_block_size);
-							  erase_block_size = 0x2000;
+							  erase_block_size = 0x1000;
 						  }
 						  break;
 					  }
</pre></body></html>