This is the mail archive of the cygwin-apps mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch] Add .tar.lzma support to setup


This patch depends on the one posted here:
http://cygwin.com/ml/cygwin-apps/2008-06/msg00106.html

Using the lzma code from lzma-sdk 4.58, I've added support for .tar.lzma files to setup. The lzma-sdk code is available under the following terms:

   1. GNU Lesser General Public License (GNU LGPL)
   2. Common Public License (CPL)
   3. Simplified license for unmodified code (read SPECIAL EXCEPTION)
   4. Proprietary license

I had to modify the code to add c++ guards, so #3 is out (as is #4, natch). But, I think LGPL is ok for setup code, right? (And, of course, my new code is provided under the GPL like most of the rest of the setup code).

This has only been briefly tested, but it successfully unpacks several tarballs and I inspected its internal behavior to make sure that all the buffers had to get refilled and there were no obvious pointer or counting errors. I can't rule out non-obvious ones, tho. <g>

--
Chuck

2008-06-29  Charles Wilson

	* Makefile.am: Add new files.
	* compress.cc (compress::decompress): add support
	for compress_lzma.
	* compress_lzma.h: new file.
	* compress_lzma.cc: new file.
	* filemanip.cc (find_tar_ext): add support for
	.tar.lzma files.
	* install.cc (Installer::installOne): update comments.
	* lzma-sdk/LzmaDec.h: new file.
	* lzma-sdk/LzmaDec.c: new file.
	* lzma-sdk/Types.h: new file.

diff -urN setup-with-memleak-fix/Makefile.am setup/Makefile.am
--- setup-with-memleak-fix/Makefile.am	2008-06-29 14:54:36.000000000 -0400
+++ setup/Makefile.am	2008-06-29 17:41:41.173600000 -0400
@@ -138,6 +138,8 @@
 	compress_bz.h \
 	compress_gz.cc \
 	compress_gz.h \
+	compress_lzma.cc \
+	compress_lzma.h \
 	ConnectionSetting.cc \
 	ConnectionSetting.h \
 	ControlAdjuster.cc \
@@ -285,7 +287,10 @@
 	csu_util/version_compare.cc \
 	csu_util/version_compare.h \
 	libmd5-rfc/md5.c \
-	libmd5-rfc/md5.h
+	libmd5-rfc/md5.h \
+	lzma-sdk/LzmaDec.c \
+	lzma-sdk/LzmaDec.h \
+	lzma-sdk/Types.h
 
 VER := $(shell sed -ne 's/^\$$Revi[s]ion: *\([^ ]*\) *$$.*/\1/p' \
                $(srcdir)/ChangeLog)
diff -urN setup-with-memleak-fix/compress.cc setup/compress.cc
--- setup-with-memleak-fix/compress.cc	2008-06-29 14:56:16.000000000 -0400
+++ setup/compress.cc	2008-06-29 22:56:09.025000000 -0400
@@ -16,6 +16,7 @@
 #include "compress.h"
 #include "compress_gz.h"
 #include "compress_bz.h"
+#include "compress_lzma.h"
 
 /* In case you are wondering why the file magic is not in one place:
  * It could be. But there is little (any?) benefit.
@@ -26,7 +27,7 @@
  * the class could test itself. 
  */
 
-#define longest_magic 3
+#define longest_magic LZMA_PROPS_SIZE + 8
 
 io_stream *
 compress::decompress (io_stream * original)
@@ -57,6 +58,16 @@
 	  delete rv;
 	  return NULL;
 	}
+      else if (compress_lzma::is_lzma (magic, LZMA_PROPS_SIZE + 8))
+	{
+	  compress_lzma *rv = new compress_lzma (original);
+	  if (!rv->error ())
+	    return rv;
+	  /* else */
+	  rv->release_original();
+	  delete rv;
+	  return NULL;
+	}
     }
   return NULL;
 }
diff -urN setup-with-memleak-fix/compress_lzma.cc setup/compress_lzma.cc
--- setup-with-memleak-fix/compress_lzma.cc	1969-12-31 19:00:00.000000000 -0500
+++ setup/compress_lzma.cc	2008-06-30 01:24:25.818000000 -0400
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2008, Charles Wilson
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ * Written by Charles Wilson <cygwin@cygwin.com>
+ *
+ */
+
+#include "compress_lzma.h"
+
+#include <stdexcept>
+using namespace std;
+#include <errno.h>
+#include <memory.h>
+#include <malloc.h>
+
+/*
+ * allocator for LzmaDec
+ */
+static void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }
+static void SzFree(void *p, void *address) { p = p; free(address); }
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+/*
+ * Predicate: the stream is open for read.
+ */
+compress_lzma::compress_lzma (io_stream * parent)
+:
+  original(NULL),
+  owns_original(true),
+  peeklen(0),
+  lasterr(0),
+  initializedOk(true),
+  unpackSize(0),
+  thereIsSize(false),
+  inbuf(NULL),
+  outbuf(NULL),
+  outp(NULL),
+  inPos(0),
+  inSize(0),
+  outPos(0),
+  inProcessed(0),
+  outProcessed(0)
+{
+  /* read only */
+  if (!parent || parent->error())
+    {
+      lasterr = EBADF;
+      return;
+    }
+  original = parent;
+ 
+  inbuf = (unsigned char *) malloc (IN_BUF_SIZE);
+  if (!inbuf)
+    {
+      lasterr = ENOMEM;
+      return;
+    }
+
+  outbuf = (unsigned char *) malloc (OUT_BUF_SIZE);
+  if (!outbuf)
+    {
+      lasterr = ENOMEM;
+      destroy();
+      return;
+    }
+
+  errno = 0;
+  check_header ();                /* parse the header, and position fp */
+
+  outPos = 0;
+  inPos = 0;
+  inSize = 0;
+  outp = outbuf;  
+  inProcessed = 0;
+  outProcessed = 0;
+  return;
+}
+
+ssize_t
+compress_lzma::read (void *buffer, size_t len)
+{
+
+  if (!this->initializedOk)
+    return -1;
+
+  /* there is no recovery from a busted stream */
+  if (this->lasterr)
+    return -1;
+ 
+  if (len == 0)
+    return 0;
+
+  /* peekbuf is layered on top of existing buffering code */
+  if (this->peeklen)
+    {
+      ssize_t tmplen = std::min (this->peeklen, len);
+      this->peeklen -= tmplen;
+      memcpy (buffer, this->peekbuf, tmplen);
+      memmove (this->peekbuf, this->peekbuf + tmplen, sizeof(this->peekbuf) - tmplen);
+      ssize_t tmpread = read (&((char *) buffer)[tmplen], len - tmplen);
+      if (tmpread >= 0)
+        return tmpread + tmplen;
+      else
+        return tmpread;
+    }
+
+  if (this->outp < this->outbuf + this->outPos)
+  /* outp - outbuf < outPos, but avoid sign/unsigned warning */
+    {
+      ssize_t tmplen = std::min ((size_t)(this->outbuf + this->outPos - this->outp), len);
+      memcpy (buffer, this->outp, tmplen);
+      this->outp += tmplen;
+      ssize_t tmpread = read (&((char *) buffer)[tmplen], len - tmplen);
+      if (tmpread >= 0)
+        return tmpread + tmplen;
+      else
+        return tmpread;
+    }
+
+  size_t lenRemaining = len;
+  unsigned char * bufp = (unsigned char *)buffer;
+  /* if we made it here, any existing uncompressed data in outbuf
+   * has been consumed, so reset outp and outPos
+   */
+  this->outp = this->outbuf;
+  this->outPos = 0;
+  do
+    {
+      if (this->inPos == this->inSize)
+        {
+          this->inSize = (size_t) this->original->read(this->inbuf, IN_BUF_SIZE);
+          this->inPos = 0;
+        }
+
+      /* at this point, these two variables actually hold the number
+       * of bytes *available* to be processed or filled
+       */
+      this->inProcessed = this->inSize - this->inPos;
+      this->outProcessed = OUT_BUF_SIZE - this->outPos;
+
+
+      ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
+      if (this->thereIsSize && this->outProcessed > this->unpackSize)
+        {
+          this->outProcessed = unpackSize;
+          finishMode = LZMA_FINISH_END;
+        }
+
+      ELzmaStatus status;
+      int res = LzmaDec_DecodeToBuf(
+              &(this->state),
+              this->outbuf + this->outPos,
+              &(this->outProcessed),
+              this->inbuf + this->inPos,
+              &(this->inProcessed),
+              finishMode,
+              &status);
+      this->inPos += (UInt32)this->inProcessed;
+      this->outPos += this->outProcessed;
+      this->unpackSize -= this->outProcessed;
+
+      ssize_t tmplen = std::min (this->outProcessed, lenRemaining);
+      memcpy (bufp, outp, tmplen);
+      outp += tmplen;
+      bufp += tmplen;
+      lenRemaining -= tmplen;
+
+      if (res != SZ_OK)
+        {
+          lasterr = res;
+          return -1;
+        }
+
+     
+      if (this->thereIsSize && this->unpackSize == 0)
+        {
+          /* expected EOF */
+          break;
+        }
+      if (this->inProcessed == 0 && this->outProcessed == 0)
+        {
+          if (this->thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
+            {
+              lasterr = EIO;
+              return -1;
+            }
+          break;
+        }
+      if (lenRemaining == 0)
+        {
+          /* fulfilled request */
+          break;
+        }
+    }
+  while (true);
+     
+  return (len - lenRemaining); 
+}
+
+ssize_t
+compress_lzma::write (const void *buffer, size_t len)
+{
+  throw new logic_error("compress_lzma::write is not implemented");
+}
+
+ssize_t
+compress_lzma::peek (void *buffer, size_t len)
+{
+  /* can only peek 512 bytes */
+  if (len > 512)
+    return ENOMEM;
+
+  if (len > this->peeklen)
+    {
+      size_t want = len - this->peeklen;
+      ssize_t got = read (&(this->peekbuf[peeklen]), want);
+      if (got >= 0)
+        this->peeklen += got;
+      else
+        /* error */
+        return got;
+      /* we may have read less than requested. */
+      memcpy (buffer, this->peekbuf, this->peeklen);
+      return this->peeklen;
+    }
+  else
+    {
+      memcpy (buffer, this->peekbuf, len);
+      return len;
+    }
+  return 0;
+}
+
+long
+compress_lzma::tell ()
+{
+  throw new logic_error("compress_lzma::tell is not implemented");
+}
+
+int
+compress_lzma::seek (long where, io_stream_seek_t whence)
+{
+  throw new logic_error("compress_lzma::seek is not implemented");
+}
+
+int
+compress_lzma::error ()
+{
+  return lasterr;
+}
+
+int
+compress_lzma::set_mtime (int time)
+{
+  if (original)
+    return original->set_mtime (time);
+  return 1;
+}
+
+int
+compress_lzma::get_mtime ()
+{
+  if (original)
+      return original->get_mtime ();
+  return 0;
+}
+
+void
+compress_lzma::release_original ()
+{
+  owns_original = false;
+}
+
+void
+compress_lzma::destroy ()
+{
+  if (this->initializedOk)
+  {
+    LzmaDec_Free(&(this->state), &g_Alloc);
+  }
+  if (this->inbuf)
+    {
+      free (this->inbuf);
+      this->inbuf = NULL;
+    }
+  if (this->outbuf)
+    {
+      free (this->outbuf);
+      this->outbuf = NULL;
+    }
+
+  if (original && owns_original)
+    delete original;
+}
+
+compress_lzma::~compress_lzma ()
+{
+  destroy ();
+}
+
+/* ===========================================================================
+ *  Check the header of a lzma_stream opened for reading.
+ *  IN assertion:
+ *     the stream s has already been created sucessfully
+ *     this method is called only once per stream
+ */
+void
+compress_lzma::check_header ()
+{
+  this->initializedOk = false;
+  this->thereIsSize = false;
+  this->unpackSize = 0;
+
+  /* read properties */
+  if (this->original->read(this->header, sizeof(this->header)) != sizeof(this->header))
+    {
+      this->lasterr = (errno ? errno : EIO);
+      return;
+    }
+
+  /* read uncompressed size */
+  for (int i = 0; i < 8; i++)
+    {
+      unsigned char b = this->header[LZMA_PROPS_SIZE + i];
+      if (b != 0xFF)
+        {
+          this->thereIsSize = true;
+        }
+      this->unpackSize += (UInt64)b << (i * 8);
+    }
+  
+  /* Decode LZMA properties and allocate memory */
+  LzmaDec_Construct(&(this->state));
+  int res = LzmaDec_Allocate(&(this->state), this->header, LZMA_PROPS_SIZE, &g_Alloc);
+  if (res != SZ_OK)
+    {
+      lasterr = res;
+      return;
+    }
+
+  LzmaDec_Init(&(this->state));
+  initializedOk = true;
+}
+
+/* ===========================================================================
+ *  duplicates a lot of code in check_header, but we don't want
+ *  to read "too much" from the stream in the check_header case.
+ *  Here, we don't care because we know compress will call this
+ *  method with a peek'ed buffer. We also do not want to modify
+ *  the member variables 'header' and 'state'.
+ */
+bool
+compress_lzma::is_lzma (void * buffer, size_t len)
+{
+  unsigned char local_header[LZMA_PROPS_SIZE + 8];
+  CLzmaDec local_state;
+  UInt64   local_unpackSize    = 0;
+  bool     local_thereIsSize   = false;
+
+  /* read header */
+  if (len < LZMA_PROPS_SIZE + 8)
+    {
+      return false;
+    }
+  memcpy((void*)local_header, buffer, sizeof(local_header));
+
+  /* read uncompressed size */
+  for (int i = 0; i < 8; i++)
+    {
+      unsigned char b = local_header[LZMA_PROPS_SIZE + i];
+      if (b != 0xFF)
+        {
+          local_thereIsSize = true;
+        }
+      local_unpackSize += (UInt64)b << (i * 8);
+    }
+
+  /* decode header */
+  if (LzmaProps_Decode(&(local_state.prop), local_header, LZMA_PROPS_SIZE) != SZ_OK)
+    {
+      return false;
+    }
+
+  return true;
+}
+
diff -urN setup-with-memleak-fix/compress_lzma.h setup/compress_lzma.h
--- setup-with-memleak-fix/compress_lzma.h	1969-12-31 19:00:00.000000000 -0500
+++ setup/compress_lzma.h	2008-06-29 22:52:27.463000000 -0400
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2008, Charles Wilson
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ * Written by Charles Wilson <cygwin@cygwin.com>
+ *
+ */
+
+#ifndef SETUP_COMPRESS_LZMA_H
+#define SETUP_COMPRESS_LZMA_H
+
+/* this is the parent class for all compress IO operations. 
+ */
+
+#include "compress.h"
+#include "lzma-sdk/LzmaDec.h"
+
+class compress_lzma:public compress
+{
+public:
+  compress_lzma (io_stream *); /* decompress (read) only */
+  virtual ssize_t read (void *buffer, size_t len);
+  virtual ssize_t write (const void *buffer, size_t len); /* not implemented */
+  virtual ssize_t peek (void *buffer, size_t len);
+  virtual long tell (); /* not implemented */
+  virtual int seek (long where, io_stream_seek_t whence); /* not implemented */
+  virtual int error ();
+  virtual const char *next_file_name () { return NULL; };
+  virtual int set_mtime (int);
+  virtual int get_mtime ();
+  virtual size_t get_size () {return 0;};
+  virtual ~compress_lzma ();
+  static bool is_lzma(void *buffer, size_t len);
+  virtual void release_original(); /* give up ownership of original io_stream */
+
+private:
+  compress_lzma () {};
+
+  io_stream *original;
+  bool owns_original;
+  char peekbuf[512];
+  size_t peeklen;
+  int lasterr;
+  bool initializedOk;
+  void check_header ();
+  void destroy ();
+
+  /* from lzma */
+  static const size_t IN_BUF_SIZE  = (1 << 16);
+  static const size_t OUT_BUF_SIZE = (1 << 16);
+  unsigned char header[LZMA_PROPS_SIZE + 8];
+  UInt64 unpackSize;
+  bool thereIsSize;  /* true means header specifies uncompressed size */
+  CLzmaDec state;
+  unsigned char * inbuf;
+  unsigned char * outbuf;
+  unsigned char * outp;
+  size_t inPos;
+  size_t inSize;
+  size_t outPos;
+  SizeT inProcessed;
+  SizeT outProcessed;
+};
+
+#endif /* SETUP_COMPRESS_LZMA_H */
diff -urN setup-with-memleak-fix/filemanip.cc setup/filemanip.cc
--- setup-with-memleak-fix/filemanip.cc	2008-06-29 14:54:36.000000000 -0400
+++ setup/filemanip.cc	2008-06-29 17:44:15.693600000 -0400
@@ -73,6 +73,8 @@
     return ext - path;
   if ((ext = trail (path, ".tar")) && (end - ext) == 4)
     return ext - path;
+  if ((ext = trail (path, ".tar.lzma")) && (end - ext) == 9)
+    return ext - path;
   return 0;
 }
 
diff -urN setup-with-memleak-fix/install.cc setup/install.cc
--- setup-with-memleak-fix/install.cc	2008-06-29 14:54:36.000000000 -0400
+++ setup/install.cc	2008-06-29 17:44:55.348600000 -0400
@@ -239,8 +239,9 @@
 
 
   /* At this point pkgfile is an opened io_stream to either a .tar.bz2 file,
-     a .tar.gz file, or just a .tar file.  Try it first as a compressed file
-     and if that fails try opening it as a tar directly.  If both fail, abort.
+     a .tar.gz file, a .tar.lzma file, or just a .tar file.  Try it first as
+     a compressed file and if that fails try opening it as a tar directly.
+     If both fail, abort.
 
      Note on io_stream pointer management:
 
diff -urN setup-with-memleak-fix/lzma-sdk/LzmaDec.c setup/lzma-sdk/LzmaDec.c
--- setup-with-memleak-fix/lzma-sdk/LzmaDec.c	1969-12-31 19:00:00.000000000 -0500
+++ setup/lzma-sdk/LzmaDec.c	2008-06-29 23:06:04.722000000 -0400
@@ -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 <string.h>
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_INIT_SIZE 5
+
+#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> 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 < limit); i -= limit; }
+
+/* #define _LZMA_SIZE_OPT */
+
+#ifdef _LZMA_SIZE_OPT
+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 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 < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < 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 < limit); i -= limit; }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols) 
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << 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 << ((p)->lc + (p)->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 << 12)
+
+/* First LZMA-symbol is always decoded. 
+And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization 
+Out:
+  Result:
+    0 - OK
+    1 - Error
+  p->remainLen:
+    < 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->probs;
+
+  unsigned state = p->state;
+  UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
+  unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
+  unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
+  unsigned lc = p->prop.lc;
+
+  Byte *dic = p->dic;
+  SizeT dicBufSize = p->dicBufSize;
+  SizeT dicPos = p->dicPos;
+  
+  UInt32 processedPos = p->processedPos;
+  UInt32 checkDicSize = p->checkDicSize;
+  unsigned len = 0;
+
+  const Byte *buf = p->buf;
+  UInt32 range = p->range;
+  UInt32 code = p->code;
+
+  do
+  {
+    CLzmaProb *prob;
+    UInt32 bound;
+    unsigned ttt;
+    unsigned posState = processedPos & pbMask;
+
+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+    IF_BIT_0(prob)
+    {
+      unsigned symbol;
+      UPDATE_0(prob);
+      prob = probs + Literal;
+      if (checkDicSize != 0 || processedPos != 0)
+        prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + 
+        (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
+
+      if (state < kNumLitStates)
+      {
+        symbol = 1;
+        do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
+      }
+      else
+      {
+        unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+        unsigned offs = 0x100;
+        symbol = 1;
+        do
+        {
+          unsigned bit;
+          CLzmaProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & offs);
+          probLit = prob + offs + bit + symbol;
+          GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
+        }
+        while (symbol < 0x100);
+      }
+      dic[dicPos++] = (Byte)symbol;
+      processedPos++;
+
+      state = kLiteralNextStates[state];
+      /* if (state < 4) state = 0; else if (state < 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 && processedPos == 0)
+          return SZ_ERROR_DATA;
+        prob = probs + IsRepG0 + state;
+        IF_BIT_0(prob)
+        {
+          UPDATE_0(prob);
+          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IF_BIT_0(prob)
+          {
+            UPDATE_0(prob);
+            dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+            dicPos++;
+            processedPos++;
+            state = state < 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 < kNumLitStates ? 8 : 11;
+        prob = probs + RepLenCoder;
+      }
+      {
+        unsigned limit, offset;
+        CLzmaProb *probLen = prob + LenChoice;
+        IF_BIT_0(probLen)
+        {
+          UPDATE_0(probLen);
+          probLen = prob + LenLow + (posState << kLenNumLowBits);
+          offset = 0;
+          limit = (1 << kLenNumLowBits);
+        }
+        else
+        {
+          UPDATE_1(probLen);
+          probLen = prob + LenChoice2;
+          IF_BIT_0(probLen)
+          {
+            UPDATE_0(probLen);
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            limit = (1 << kLenNumMidBits);
+          }
+          else
+          {
+            UPDATE_1(probLen);
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            limit = (1 << kLenNumHighBits);
+          }
+        }
+        TREE_DECODE(probLen, limit, len);
+        len += offset;
+      }
+
+      if (state >= kNumStates)
+      {
+        UInt32 distance;
+        prob = probs + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
+        TREE_6_DECODE(prob, distance);
+        if (distance >= kStartPosModelIndex)
+        {
+          unsigned posSlot = (unsigned)distance; 
+          int numDirectBits = (int)(((distance >> 1) - 1));
+          distance = (2 | (distance & 1));
+          if (posSlot < kEndPosModelIndex)
+          {
+            distance <<= numDirectBits;
+            prob = probs + SpecPos + distance - posSlot - 1;
+            {
+              UInt32 mask = 1;
+              unsigned i = 1;
+              do
+              {
+                GET_BIT2(prob + i, i, ; , distance |= mask);
+                mask <<= 1;
+              }
+              while(--numDirectBits != 0);
+            }
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              NORMALIZE
+              range >>= 1;
+              
+              {
+                UInt32 t;
+                code -= range;
+                t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
+                distance = (distance << 1) + (t + 1);
+                code += range & t;
+              }
+              /*
+              distance <<= 1;
+              if (code >= range)
+              {
+                code -= range;
+                distance |= 1;
+              }
+              */
+            }
+            while (--numDirectBits != 0);
+            prob = probs + Align;
+            distance <<= 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 >= processedPos)
+            return SZ_ERROR_DATA;
+        }
+        else if (distance >= checkDicSize)
+          return SZ_ERROR_DATA;
+        state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
+        /* state = kLiteralNextStates[state]; */
+      }
+
+      len += kMatchMinLen;
+
+      {
+        SizeT rem = limit - dicPos;
+        unsigned curLen = ((rem < len) ? (unsigned)rem : len);
+        SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
+
+        processedPos += curLen;
+
+        len -= curLen;
+        if (pos + curLen <= 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 < limit && buf < bufLimit);
+  NORMALIZE;
+  p->buf = buf;
+  p->range = range;
+  p->code = code;
+  p->remainLen = len;
+  p->dicPos = dicPos;
+  p->processedPos = processedPos;
+  p->reps[0] = rep0;
+  p->reps[1] = rep1;
+  p->reps[2] = rep2;
+  p->reps[3] = rep3;
+  p->state = state;
+
+  return SZ_OK;
+}
+
+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
+{
+  if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
+  {
+    Byte *dic = p->dic;
+    SizeT dicPos = p->dicPos;
+    SizeT dicBufSize = p->dicBufSize;
+    unsigned len = p->remainLen;
+    UInt32 rep0 = p->reps[0];
+    if (limit - dicPos < len)
+      len = (unsigned)(limit - dicPos);
+
+    if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
+      p->checkDicSize = p->prop.dicSize;
+
+    p->processedPos += len;
+    p->remainLen -= len;
+    while (len-- != 0)
+    {
+      dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+      dicPos++;
+    }
+    p->dicPos = dicPos;
+  }
+}
+
+/* LzmaDec_DecodeReal2 decodes LZMA-symbols and sets p->needFlush and p->needInit, if required. */
+
+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+  do
+  {
+    SizeT limit2 = limit;
+    if (p->checkDicSize == 0)
+    {
+      UInt32 rem = p->prop.dicSize - p->processedPos;
+      if (limit - p->dicPos > rem)
+        limit2 = p->dicPos + rem;
+    }
+    RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
+    if (p->processedPos >= p->prop.dicSize)
+      p->checkDicSize = p->prop.dicSize;
+    LzmaDec_WriteRem(p, limit);
+  }
+  while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
+
+  if (p->remainLen > kMatchSpecLenStart)
+  {
+    p->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->range;
+  UInt32 code = p->code;
+  const Byte *bufLimit = buf + inSize;
+  CLzmaProb *probs = p->probs;
+  unsigned state = p->state;
+  ELzmaDummy res;
+
+  {
+    CLzmaProb *prob;
+    UInt32 bound;
+    unsigned ttt;
+    unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
+
+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+    IF_BIT_0_CHECK(prob)
+    {
+      UPDATE_0_CHECK
+
+      /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
+
+      prob = probs + Literal;
+      if (p->checkDicSize != 0 || p->processedPos != 0)
+        prob += (LZMA_LIT_SIZE * 
+          ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + 
+          (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
+
+      if (state < kNumLitStates)
+      {
+        unsigned symbol = 1;
+        do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
+      }
+      else
+      {
+        unsigned matchByte = p->dic[p->dicPos - p->reps[0] + 
+            ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
+        unsigned offs = 0x100;
+        unsigned symbol = 1;
+        do
+        {
+          unsigned bit;
+          CLzmaProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & offs);
+          probLit = prob + offs + bit + symbol;
+          GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
+        }
+        while (symbol < 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 << 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 << kLenNumLowBits);
+          offset = 0;
+          limit = 1 << kLenNumLowBits;
+        }
+        else
+        {
+          UPDATE_1_CHECK;
+          probLen = prob + LenChoice2;
+          IF_BIT_0_CHECK(probLen)
+          {
+            UPDATE_0_CHECK;
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            limit = 1 << kLenNumMidBits;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            limit = 1 << kLenNumHighBits;
+          }
+        }
+        TREE_DECODE_CHECK(probLen, limit, len);
+        len += offset;
+      }
+
+      if (state < 4)
+      {
+        unsigned posSlot;
+        prob = probs + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << 
+            kNumPosSlotBits);
+        TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
+        if (posSlot >= kStartPosModelIndex)
+        {
+          int numDirectBits = ((posSlot >> 1) - 1);
+
+          /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
+
+          if (posSlot < kEndPosModelIndex)
+          {
+            prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              NORMALIZE_CHECK
+              range >>= 1;
+              code -= range & (((code - range) >> 31) - 1);
+              /* if (code >= 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->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
+  p->range = 0xFFFFFFFF;
+  p->needFlush = 0;
+}
+
+static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) 
+{ 
+  p->needFlush = 1; 
+  p->remainLen = 0; 
+  p->tempBufSize = 0; 
+
+  if (initDic)
+  {
+    p->processedPos = 0;
+    p->checkDicSize = 0;
+    p->needInitState = 1;
+  }
+  if (initState)
+    p->needInitState = 1;
+}
+
+void LzmaDec_Init(CLzmaDec *p) 
+{ 
+  p->dicPos = 0; 
+  LzmaDec_InitDicAndState(p, True, True);
+}
+
+static void LzmaDec_InitStateReal(CLzmaDec *p)
+{
+  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
+  UInt32 i;
+  CLzmaProb *probs = p->probs;
+  for (i = 0; i < numProbs; i++)
+    probs[i] = kBitModelTotal >> 1; 
+  p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
+  p->state = 0;
+  p->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->remainLen != kMatchSpecLenStart)
+  {
+      int checkEndMarkNow;
+
+      if (p->needFlush != 0)
+      {
+        for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
+          p->tempBuf[p->tempBufSize++] = *src++;
+        if (p->tempBufSize < RC_INIT_SIZE)
+        {
+          *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+          return SZ_OK;
+        }
+        if (p->tempBuf[0] != 0)
+          return SZ_ERROR_DATA;
+
+        LzmaDec_InitRc(p, p->tempBuf);
+        p->tempBufSize = 0;
+      }
+
+      checkEndMarkNow = 0;
+      if (p->dicPos >= dicLimit)
+      {
+        if (p->remainLen == 0 && p->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->remainLen != 0)
+        {
+          *status = LZMA_STATUS_NOT_FINISHED;
+          return SZ_ERROR_DATA;
+        }
+        checkEndMarkNow = 1;
+      }
+
+      if (p->needInitState)
+        LzmaDec_InitStateReal(p);
+  
+      if (p->tempBufSize == 0)
+      {
+        SizeT processed;
+        const Byte *bufLimit;
+        if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+        {
+          int dummyRes = LzmaDec_TryDummy(p, src, inSize);
+          if (dummyRes == DUMMY_ERROR)
+          {
+            memcpy(p->tempBuf, src, inSize);
+            p->tempBufSize = (unsigned)inSize;
+            (*srcLen) += inSize;
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+            return SZ_OK;
+          }
+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+          {
+            *status = LZMA_STATUS_NOT_FINISHED;
+            return SZ_ERROR_DATA;
+          }
+          bufLimit = src;
+        }
+        else
+          bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
+        p->buf = src;
+        if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
+          return SZ_ERROR_DATA;
+        processed = p->buf - src;
+        (*srcLen) += processed;
+        src += processed;
+        inSize -= processed;
+      }
+      else
+      {
+        unsigned rem = p->tempBufSize, lookAhead = 0;
+        while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
+          p->tempBuf[rem++] = src[lookAhead++];
+        p->tempBufSize = rem;
+        if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+        {
+          int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
+          if (dummyRes == DUMMY_ERROR)
+          {
+            (*srcLen) += lookAhead;
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+            return SZ_OK;
+          }
+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+          {
+            *status = LZMA_STATUS_NOT_FINISHED;
+            return SZ_ERROR_DATA;
+          }
+        }
+        p->buf = p->tempBuf;
+        if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
+          return SZ_ERROR_DATA;
+        lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
+        (*srcLen) += lookAhead;
+        src += lookAhead;
+        inSize -= lookAhead;
+        p->tempBufSize = 0;
+      }
+  }
+  if (p->code == 0) 
+    *status = LZMA_STATUS_FINISHED_WITH_MARK;
+  return (p->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->dicPos == p->dicBufSize)
+      p->dicPos = 0;
+    dicPos = p->dicPos;
+    if (outSize > p->dicBufSize - dicPos)
+    {
+      outSizeCur = p->dicBufSize;
+      curFinishMode = LZMA_FINISH_ANY;
+    }
+    else
+    {
+      outSizeCur = dicPos + outSize;
+      curFinishMode = finishMode;
+    }
+
+    res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
+    src += inSizeCur;
+    inSize -= inSizeCur;
+    *srcLen += inSizeCur;
+    outSizeCur = p->dicPos - dicPos;
+    memcpy(dest, p->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->Free(alloc, p->probs);  
+  p->probs = 0; 
+}
+
+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) 
+{ 
+  alloc->Free(alloc, p->dic); 
+  p->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 < LZMA_PROPS_SIZE)
+    return SZ_ERROR_UNSUPPORTED;
+  else
+    dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
+ 
+  if (dicSize < LZMA_DIC_MIN)
+    dicSize = LZMA_DIC_MIN;
+  p->dicSize = dicSize;
+
+  d = data[0];
+  if (d >= (9 * 5 * 5))
+    return SZ_ERROR_UNSUPPORTED;
+
+  p->lc = d % 9;
+  d /= 9;
+  p->pb = d / 5;
+  p->lp = d % 5;
+
+  return SZ_OK;
+}
+
+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
+{
+  UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
+  if (p->probs == 0 || numProbs != p->numProbs)
+  {
+    LzmaDec_FreeProbs(p, alloc);
+    p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
+    p->numProbs = numProbs;
+    if (p->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(&propNew, props, propsSize));
+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+  p->prop = propNew;
+  return SZ_OK;
+}
+
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+  CLzmaProps propNew;
+  SizeT dicBufSize;
+  RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+  dicBufSize = propNew.dicSize;
+  if (p->dic == 0 || dicBufSize != p->dicBufSize)
+  {
+    LzmaDec_FreeDict(p, alloc);
+    p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
+    if (p->dic == 0)
+    {
+      LzmaDec_FreeProbs(p, alloc);
+      return SZ_ERROR_MEM;
+    }
+  }
+  p->dicBufSize = dicBufSize;
+  p->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 < RC_INIT_SIZE)
+    return SZ_ERROR_INPUT_EOF;
+
+  LzmaDec_Construct(&p);
+  res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
+  if (res != 0)
+    return res;
+  p.dic = dest;
+  p.dicBufSize = outSize;
+
+  LzmaDec_Init(&p);
+  
+  *srcLen = inSize;
+  res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
+
+  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
+    res = SZ_ERROR_INPUT_EOF;
+
+  (*destLen) = p.dicPos;
+  LzmaDec_FreeProbs(&p, alloc);
+  return res;
+}
diff -urN setup-with-memleak-fix/lzma-sdk/LzmaDec.h setup/lzma-sdk/LzmaDec.h
--- setup-with-memleak-fix/lzma-sdk/LzmaDec.h	1969-12-31 19:00:00.000000000 -0500
+++ setup/lzma-sdk/LzmaDec.h	2008-06-29 17:33:02.969600000 -0400
@@ -0,0 +1,241 @@
+/* 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"
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+
+/* #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 < 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)->dic = 0; (p)->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);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif
diff -urN setup-with-memleak-fix/lzma-sdk/Types.h setup/lzma-sdk/Types.h
--- setup-with-memleak-fix/lzma-sdk/Types.h	1969-12-31 19:00:00.000000000 -0500
+++ setup/lzma-sdk/Types.h	2008-06-29 17:32:10.731600000 -0400
@@ -0,0 +1,140 @@
+/* Types.h -- Basic types
+2008-04-11
+Igor Pavlov
+Public domain */
+
+#ifndef __7Z_TYPES_H
+#define __7Z_TYPES_H
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+
+
+#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 <stddef.h>
+typedef size_t SizeT;
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+
+#ifdef _MSC_VER
+
+#if _MSC_VER >= 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 && output(*size) == 0) means end_of_stream.
+       (output(*size) < 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 < 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)->Alloc((p), size)
+#define IAlloc_Free(p, a) (p)->Free((p), a)
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]