- upgrade to zlib-1.2.2.4 internal.
authorjbj <devnull@localhost>
Sat, 16 Jul 2005 16:37:06 +0000 (16:37 +0000)
committerjbj <devnull@localhost>
Sat, 16 Jul 2005 16:37:06 +0000 (16:37 +0000)
- macosx: avoid minigzip build failures.

CVS patchset: 7894
CVS date: 2005/07/16 16:37:06

69 files changed:
CHANGES
rpm.spec.in
zlib/ChangeLog
zlib/Makefile.am
zlib/README
zlib/as400/zlib.inc
zlib/contrib/README.contrib
zlib/contrib/asm586/match.S
zlib/contrib/asm686/match.S
zlib/contrib/infback9/infback9.h
zlib/contrib/infback9/inftree9.c
zlib/contrib/masm686/match.asm
zlib/contrib/masmx64/bld_ml64.bat [new file with mode: 0644]
zlib/contrib/masmx64/gvmat64.asm [new file with mode: 0644]
zlib/contrib/masmx64/inffas8664.c [new file with mode: 0644]
zlib/contrib/masmx64/inffasx64.asm [new file with mode: 0644]
zlib/contrib/masmx64/readme.txt [new file with mode: 0644]
zlib/contrib/masmx86/bld_ml32.bat [new file with mode: 0644]
zlib/contrib/masmx86/gvmat32.asm
zlib/contrib/masmx86/gvmat32c.c
zlib/contrib/masmx86/inffas32.asm
zlib/contrib/minizip/ChangeLogUnzip
zlib/contrib/minizip/crypt.h
zlib/contrib/minizip/ioapi.c
zlib/contrib/minizip/ioapi.h
zlib/contrib/minizip/iowin32.c
zlib/contrib/minizip/iowin32.h
zlib/contrib/minizip/miniunz.c
zlib/contrib/minizip/minizip.c
zlib/contrib/minizip/mztools.c [new file with mode: 0644]
zlib/contrib/minizip/mztools.h [new file with mode: 0644]
zlib/contrib/minizip/unzip.c
zlib/contrib/minizip/unzip.h
zlib/contrib/minizip/zip.c
zlib/contrib/minizip/zip.h
zlib/contrib/testzlib/rdtsc64.asm [new file with mode: 0644]
zlib/contrib/testzlib/testzlib.c
zlib/contrib/testzlib/testzlib.txt [new file with mode: 0644]
zlib/contrib/testzlib/testzlib8.sln [new file with mode: 0644]
zlib/contrib/testzlib/testzlib8.vcproj [new file with mode: 0644]
zlib/contrib/vstudio/vc7/gvmat32.obj
zlib/contrib/vstudio/vc7/inffas32.obj
zlib/contrib/vstudio/vc7/zlib.rc
zlib/crc32.c
zlib/deflate.c
zlib/deflate.h
zlib/examples/README.examples [new file with mode: 0644]
zlib/examples/fitblk.c [new file with mode: 0644]
zlib/examples/gun.c [new file with mode: 0644]
zlib/examples/gzjoin.c [new file with mode: 0644]
zlib/examples/zlib_how.html [new file with mode: 0644]
zlib/examples/zpipe.c [new file with mode: 0644]
zlib/examples/zran.c [new file with mode: 0644]
zlib/gzio.c
zlib/infback.c
zlib/inflate.c
zlib/inftrees.c
zlib/inftrees.h
zlib/make_vms.com [new file with mode: 0644]
zlib/minigzip.c
zlib/qnx/package.qpg
zlib/trees.c
zlib/win32/zlib1.rc
zlib/zconf.h
zlib/zconf.in.h
zlib/zlib.3
zlib/zlib.h
zlib/zutil.c
zlib/zutil.h

diff --git a/CHANGES b/CHANGES
index 9286511..f8b1d09 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -26,6 +26,8 @@
        - permit zlib in rpm to be built with make -j (#159404).
        - avoid '?' for zero length file mmap failure doing md5 (#159405).
        - permit scriptlet includes from builddir for spec files w/o %setup.
+       - upgrade to zlib-1.2.2.4 internal.
+       - macosx: avoid minigzip build failures.
 
 4.4 -> 4.4.1:
        - force *.py->*.pyo byte code compilation with brp-python-bytecompile.
index ed17033..0976f4b 100644 (file)
@@ -20,7 +20,7 @@ Name: rpm
 %define version @VERSION@
 Version: %{version}
 %{expand: %%define rpm_version %{version}}
-Release: 0.8
+Release: 0.9
 Group: System Environment/Base
 Source: ftp://jbj.org/pub/rpm-devel/rpm-%{rpm_version}.tar.gz
 License: GPL
@@ -499,6 +499,10 @@ exit 0
 %{__includedir}/popt.h
 
 %changelog
+* Sat Jul 16 2005 Jeff Johnson <jbj@jbj.org> 4.4.2-0.9
+- upgrade to zlib-1.2.2.4 internal.
+- macosx: avoid minigzip build failures.
+
 * Wed Jul 13 2005 Jeff Johnson <jbj@jbj.org> 4.4.2-0.8
 - updated de.po (#162756).
 - added CVSId: tag and SVNId: alias (#162807).
index d60b6d3..105a7cb 100644 (file)
@@ -1,6 +1,92 @@
 
                 ChangeLog file for zlib
 
+Changes in 1.2.2.4 (11 July 2005)
+- Add inflatePrime() function for starting inflation at bit boundary
+- Avoid some Visual C warnings in deflate.c
+- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit
+  compile
+- Fix some spelling errors in comments [Betts]
+- Correct inflateInit2() error return documentation in zlib.h
+- Added zran.c example of compressed data random access to examples
+  directory, shows use of inflatePrime()
+- Fix cast for assignments to strm->state in inflate.c and infback.c
+- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer]
+- Move declarations of gf2 functions to right place in crc32.c [Oberhumer]
+- Add cast in trees.c t avoid a warning [Oberhumer]
+- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer]
+- Update make_vms.com [Zinser]
+- Initialize state->write in inflateReset() since copied in inflate_fast()
+- Be more strict on incomplete code sets in inflate_table() and increase
+  ENOUGH and MAXD -- this repairs a possible security vulnerability for
+  invalid inflate input.  Thanks to Tavis Ormandy and Markus Oberhumer for
+  discovering the vulnerability and providing test cases.
+- Add ia64 support to configure for HP-UX [Smith]
+- Add error return to gzread() for format or i/o error [Levin]
+- Use malloc.h for OS/2 [Necasek]
+
+Changes in 1.2.2.3 (27 May 2005)
+- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile
+- Typecast fread() return values in gzio.c [Vollant]
+- Remove trailing space in minigzip.c outmode (VC++ can't deal with it)
+- Fix crc check bug in gzread() after gzungetc() [Heiner]
+- Add the deflateTune() function to adjust internal compression parameters
+- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack)
+- Remove an incorrect assertion in examples/zpipe.c
+- Add C++ wrapper in infback9.h [Donais]
+- Fix bug in inflateCopy() when decoding fixed codes
+- Note in zlib.h how much deflateSetDictionary() actually uses
+- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used)
+- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer]
+- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer]
+- Add gzdirect() function to indicate transparent reads
+- Update contrib/minizip [Vollant]
+- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer]
+- Add casts in crc32.c to avoid warnings [Oberhumer]
+- Add contrib/masmx64 [Vollant]
+- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant]
+
+Changes in 1.2.2.2 (30 December 2004)
+- Replace structure assignments in deflate.c and inflate.c with zmemcpy to
+  avoid implicit memcpy calls (portability for no-library compilation)
+- Increase sprintf() buffer size in gzdopen() to allow for large numbers
+- Add INFLATE_STRICT to check distances against zlib header
+- Improve WinCE errno handling and comments [Chang]
+- Remove comment about no gzip header processing in FAQ
+- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
+- Add updated make_vms.com [Coghlan], update README
+- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
+  fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html.
+- Add FAQ entry and comments in deflate.c on uninitialized memory access
+- Add Solaris 9 make options in configure [Gilbert]
+- Allow strerror() usage in gzio.c for STDC
+- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer]
+- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant]
+- Use z_off_t for adler32_combine() and crc32_combine() lengths
+- Make adler32() much faster for small len
+- Use OS_CODE in deflate() default gzip header
+
+Changes in 1.2.2.1 (31 October 2004)
+- Allow inflateSetDictionary() call for raw inflate
+- Fix inflate header crc check bug for file names and comments
+- Add deflateSetHeader() and gz_header structure for custom gzip headers
+- Add inflateGetheader() to retrieve gzip headers
+- Add crc32_combine() and adler32_combine() functions
+- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list
+- Use zstreamp consistently in zlib.h (inflate_back functions)
+- Remove GUNZIP condition from definition of inflate_mode in inflate.h
+  and in contrib/inflate86/inffast.S [Truta, Anderson]
+- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson]
+- Update projects/README.projects and projects/visualc6 [Truta]
+- Update win32/DLL_FAQ.txt [Truta]
+- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta]
+- Deprecate Z_ASCII; use Z_TEXT instead [Truta]
+- Use a new algorithm for setting strm->data_type in trees.c [Truta]
+- Do not define an exit() prototype in zutil.c unless DEBUG defined
+- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta]
+- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate()
+- Fix Darwin build version identification [Peterson]
+
 Changes in 1.2.2 (3 October 2004)
 - Update zlib.h comments on gzip in-memory processing
 - Set adler to 1 in inflateReset() to support Java test suite [Walles]
@@ -449,7 +535,7 @@ Changes in 1.0.7 (20 Jan 1998)
 Changes in 1.0.6 (19 Jan 1998)
 - add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
   gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
-- Fix a deflate bug occuring only with compression level 0 (thanks to
+- Fix a deflate bug occurring only with compression level 0 (thanks to
   Andy Buckler for finding this one).
 - In minigzip, pass transparently also the first byte for .Z files.
 - return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
index 01f7b1f..7f1abb2 100644 (file)
@@ -19,12 +19,10 @@ libz_la_SOURCES = \
 noinst_PROGRAMS = example minigzip
 
 example_SOURCES = example.c
-example_LDFLAGS = -L. -lz
-example_DEPENDENCIES = libz.la
+example_LDFLAGS = .libs/libz.a
 
 minigzip_SOURCES = minigzip.c
-minigzip_LDFLAGS = -L. -lz
-minigzip_DEPENDENCIES = libz.la
+minigzip_LDFLAGS = .libs/libz.a
 
 BUILT_SOURCES = # Doxyfile zlib.lcd
 
index df95ae1..3c8e1d4 100644 (file)
@@ -1,6 +1,6 @@
 ZLIB DATA COMPRESSION LIBRARY
 
-zlib 1.2.2 is a general purpose data compression library.  All the code is
+zlib 1.2.2.4 is a general purpose data compression library.  All the code is
 thread safe.  The data format used by the zlib library is described by RFCs
 (Request for Comments) 1950 to 1952 in the files
 http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
@@ -16,9 +16,8 @@ minigzip.c.
 
 To compile all files and run the test program, follow the instructions given at
 the top of Makefile. In short "make test; make install" should work for most
-machines. For Unix: "./configure; make test; make install" For MSDOS, use one
-of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or
-descrip.mms.
+machines. For Unix: "./configure; make test; make install". For MSDOS, use one
+of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
 
 Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
 <info@winimage.com> for the Windows DLL version. The zlib home page is
@@ -34,7 +33,7 @@ Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
 issue of  Dr. Dobb's Journal; a copy of the article is available in
 http://dogma.net/markn/articles/zlibtool/zlibtool.htm
 
-The changes made in version 1.2.2 are documented in the file ChangeLog.
+The changes made in version 1.2.2.4 are documented in the file ChangeLog.
 
 Unsupported third party contributions are provided in directory "contrib".
 
index e31e1a7..263677d 100644 (file)
@@ -1,7 +1,7 @@
       *  ZLIB.INC - Interface to the general purpose compression library
       *
       *  ILE RPG400 version by Patrick Monnerat, DATASPHERE.
-      *  Version 1.2.2
+      *  Version 1.2.2.4
       *
       *
       *  WARNING:
       *                               Constants
       **************************************************************************
       *
-     D ZLIB_VERSION    C                   '1.2.2'                            Header's version
-     D ZLIB_VERNUM     C                   X'1220'
+      *  Versioning information.
+      *
+     D ZLIB_VERSION    C                   '1.2.2.4'
+     D ZLIB_VERNUM     C                   X'1224'
+      *
+      *  Other equates.
       *
      D Z_NO_FLUSH      C                   0
      D Z_SYNC_FLUSH    C                   2
index 7778980..20afc62 100644 (file)
@@ -22,9 +22,6 @@ delphi/     by Cosmin Truta <cosmint@cs.ubbcluj.ro>
 dotzlib/    by Henrik Ravn <henrik@ravn.com>
         Support for Microsoft .Net and Visual C++ .Net
 
-gzappend/   by Mark Adler <madler@alumni.caltech.edu>
-        append to a gzip file -- illustrates the use of Z_BLOCK
-
 infback9/   by Mark Adler <madler@alumni.caltech.edu>
         Unsupported diffs to infback to decode the deflate64 format
 
@@ -45,6 +42,10 @@ masm686/    by Dan Higdon <hdan@kinesoft.com>
             and Chuck Walbourn <chuckw@kinesoft.com>
         asm code for Pentium Pro/PII, using the MASM syntax
 
+masmx64/    by Gilles Vollant <info@winimage.com>
+       x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to
+       replace longest_match() and inflate_fast()
+
 masmx86/    by Gilles Vollant <info@winimage.com>
         x86 asm code to replace longest_match() and inflate_fast(),
         for Visual C++ and MASM
index 8f16140..371c9a0 100644 (file)
-/* match.s -- Pentium-optimized version of longest_match()
- * Written for zlib 1.1.2
- * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License.
- */
-
-#ifndef NO_UNDERLINE
-#define        match_init      _match_init
-#define        longest_match   _longest_match
-#endif
-
-#define        MAX_MATCH       (258)
-#define        MIN_MATCH       (3)
-#define        MIN_LOOKAHEAD   (MAX_MATCH + MIN_MATCH + 1)
-#define        MAX_MATCH_8     ((MAX_MATCH + 7) & ~7)
-
-/* stack frame offsets */
-
-#define        wmask                   0       /* local copy of s->wmask       */
-#define        window                  4       /* local copy of s->window      */
-#define        windowbestlen           8       /* s->window + bestlen          */
-#define        chainlenscanend         12      /* high word: current chain len */
-                                       /* low word: last bytes sought  */
-#define        scanstart               16      /* first two bytes of string    */
-#define        scanalign               20      /* dword-misalignment of string */
-#define        nicematch               24      /* a good enough match size     */
-#define        bestlen                 28      /* size of best match so far    */
-#define        scan                    32      /* ptr to string wanting match  */
-
-#define        LocalVarsSize           (36)
-/*     saved ebx               36 */
-/*     saved edi               40 */
-/*     saved esi               44 */
-/*     saved ebp               48 */
-/*     return address          52 */
-#define        deflatestate            56      /* the function arguments       */
-#define        curmatch                60
-
-/* Offsets for fields in the deflate_state structure. These numbers
- * are calculated from the definition of deflate_state, with the
- * assumption that the compiler will dword-align the fields. (Thus,
- * changing the definition of deflate_state could easily cause this
- * program to crash horribly, without so much as a warning at
- * compile time. Sigh.)
- */
-#define        dsWSize                 36
-#define        dsWMask                 44
-#define        dsWindow                48
-#define        dsPrev                  56
-#define        dsMatchLen              88
-#define        dsPrevMatch             92
-#define        dsStrStart              100
-#define        dsMatchStart            104
-#define        dsLookahead             108
-#define        dsPrevLen               112
-#define        dsMaxChainLen           116
-#define        dsGoodMatch             132
-#define        dsNiceMatch             136
-
-
-.file "match.S"
-
-.globl match_init, longest_match
-
-.text
-
-/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
-
-longest_match:
-
-/* Save registers that the compiler may be using, and adjust %esp to   */
-/* make room for our stack frame.                                      */
-
-               pushl   %ebp
-               pushl   %edi
-               pushl   %esi
-               pushl   %ebx
-               subl    $LocalVarsSize, %esp
-
-/* Retrieve the function arguments. %ecx will hold cur_match           */
-/* throughout the entire function. %edx will hold the pointer to the   */
-/* deflate_state structure during the function's setup (before         */
-/* entering the main loop).                                            */
-
-               movl    deflatestate(%esp), %edx
-               movl    curmatch(%esp), %ecx
-
-/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;     */
-
-               movl    dsNiceMatch(%edx), %eax
-               movl    dsLookahead(%edx), %ebx
-               cmpl    %eax, %ebx
-               jl      LookaheadLess
-               movl    %eax, %ebx
-LookaheadLess: movl    %ebx, nicematch(%esp)
-
-/* register Bytef *scan = s->window + s->strstart;                     */
-
-               movl    dsWindow(%edx), %esi
-               movl    %esi, window(%esp)
-               movl    dsStrStart(%edx), %ebp
-               lea     (%esi,%ebp), %edi
-               movl    %edi, scan(%esp)
-
-/* Determine how many bytes the scan ptr is off from being             */
-/* dword-aligned.                                                      */
-
-               movl    %edi, %eax
-               negl    %eax
-               andl    $3, %eax
-               movl    %eax, scanalign(%esp)
-
-/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */
-/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */
-
-               movl    dsWSize(%edx), %eax
-               subl    $MIN_LOOKAHEAD, %eax
-               subl    %eax, %ebp
-               jg      LimitPositive
-               xorl    %ebp, %ebp
-LimitPositive:
-
-/* unsigned chain_length = s->max_chain_length;                                */
-/* if (s->prev_length >= s->good_match) {                              */
-/*     chain_length >>= 2;                                             */
-/* }                                                                   */
-
-               movl    dsPrevLen(%edx), %eax
-               movl    dsGoodMatch(%edx), %ebx
-               cmpl    %ebx, %eax
-               movl    dsMaxChainLen(%edx), %ebx
-               jl      LastMatchGood
-               shrl    $2, %ebx
-LastMatchGood:
-
-/* chainlen is decremented once beforehand so that the function can    */
-/* use the sign flag instead of the zero flag for the exit test.       */
-/* It is then shifted into the high word, to make room for the scanend */
-/* scanend value, which it will always accompany.                      */
-
-               decl    %ebx
-               shll    $16, %ebx
-
-/* int best_len = s->prev_length;                                      */
-
-               movl    dsPrevLen(%edx), %eax
-               movl    %eax, bestlen(%esp)
-
-/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
-
-               addl    %eax, %esi
-               movl    %esi, windowbestlen(%esp)
-
-/* register ush scan_start = *(ushf*)scan;                             */
-/* register ush scan_end   = *(ushf*)(scan+best_len-1);                        */
-
-               movw    (%edi), %bx
-               movw    %bx, scanstart(%esp)
-               movw    -1(%edi,%eax), %bx
-               movl    %ebx, chainlenscanend(%esp)
-
-/* Posf *prev = s->prev;                                               */
-/* uInt wmask = s->w_mask;                                             */
-
-               movl    dsPrev(%edx), %edi
-               movl    dsWMask(%edx), %edx
-               mov     %edx, wmask(%esp)
-
-/* Jump into the main loop.                                            */
-
-               jmp     LoopEntry
-
-.balign 16
-
-/* do {
- *     match = s->window + cur_match;
- *     if (*(ushf*)(match+best_len-1) != scan_end ||
- *         *(ushf*)match != scan_start) continue;
- *     [...]
- * } while ((cur_match = prev[cur_match & wmask]) > limit
- *          && --chain_length != 0);
- *
- * Here is the inner loop of the function. The function will spend the
- * majority of its time in this loop, and majority of that time will
- * be spent in the first ten instructions.
- *
- * Within this loop:
- * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)
- * %ecx = curmatch
- * %edx = curmatch & wmask
- * %esi = windowbestlen - i.e., (window + bestlen)
- * %edi = prev
- * %ebp = limit
- *
- * Two optimization notes on the choice of instructions:
- *
- * The first instruction uses a 16-bit address, which costs an extra,
- * unpairable cycle. This is cheaper than doing a 32-bit access and
- * zeroing the high word, due to the 3-cycle misalignment penalty which
- * would occur half the time. This also turns out to be cheaper than
- * doing two separate 8-bit accesses, as the memory is so rarely in the
- * L1 cache.
- *
- * The window buffer, however, apparently spends a lot of time in the
- * cache, and so it is faster to retrieve the word at the end of the
- * match string with two 8-bit loads. The instructions that test the
- * word at the beginning of the match string, however, are executed
- * much less frequently, and there it was cheaper to use 16-bit
- * instructions, which avoided the necessity of saving off and
- * subsequently reloading one of the other registers.
- */
-LookupLoop:
-                                                       /* 1 U & V  */
-               movw    (%edi,%edx,2), %cx              /* 2 U pipe */
-               movl    wmask(%esp), %edx               /* 2 V pipe */
-               cmpl    %ebp, %ecx                      /* 3 U pipe */
-               jbe     LeaveNow                        /* 3 V pipe */
-               subl    $0x00010000, %ebx               /* 4 U pipe */
-               js      LeaveNow                        /* 4 V pipe */
-LoopEntry:     movb    -1(%esi,%ecx), %al              /* 5 U pipe */
-               andl    %ecx, %edx                      /* 5 V pipe */
-               cmpb    %bl, %al                        /* 6 U pipe */
-               jnz     LookupLoop                      /* 6 V pipe */
-               movb    (%esi,%ecx), %ah
-               cmpb    %bh, %ah
-               jnz     LookupLoop
-               movl    window(%esp), %eax
-               movw    (%eax,%ecx), %ax
-               cmpw    scanstart(%esp), %ax
-               jnz     LookupLoop
-
-/* Store the current value of chainlen.                                        */
-
-               movl    %ebx, chainlenscanend(%esp)
-
-/* Point %edi to the string under scrutiny, and %esi to the string we  */
-/* are hoping to match it up with. In actuality, %esi and %edi are     */
-/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is     */
-/* initialized to -(MAX_MATCH_8 - scanalign).                          */
-
-               movl    window(%esp), %esi
-               movl    scan(%esp), %edi
-               addl    %ecx, %esi
-               movl    scanalign(%esp), %eax
-               movl    $(-MAX_MATCH_8), %edx
-               lea     MAX_MATCH_8(%edi,%eax), %edi
-               lea     MAX_MATCH_8(%esi,%eax), %esi
-
-/* Test the strings for equality, 8 bytes at a time. At the end,
- * adjust %edx so that it is offset to the exact byte that mismatched.
- *
- * We already know at this point that the first three bytes of the
- * strings match each other, and they can be safely passed over before
- * starting the compare loop. So what this code does is skip over 0-3
- * bytes, as much as necessary in order to dword-align the %edi
- * pointer. (%esi will still be misaligned three times out of four.)
- *
- * It should be confessed that this loop usually does not represent
- * much of the total running time. Replacing it with a more
- * straightforward "rep cmpsb" would not drastically degrade
- * performance.
- */
-LoopCmps:
-               movl    (%esi,%edx), %eax
-               movl    (%edi,%edx), %ebx
-               xorl    %ebx, %eax
-               jnz     LeaveLoopCmps
-               movl    4(%esi,%edx), %eax
-               movl    4(%edi,%edx), %ebx
-               xorl    %ebx, %eax
-               jnz     LeaveLoopCmps4
-               addl    $8, %edx
-               jnz     LoopCmps
-               jmp     LenMaximum
-LeaveLoopCmps4:        addl    $4, %edx
-LeaveLoopCmps: testl   $0x0000FFFF, %eax
-               jnz     LenLower
-               addl    $2, %edx
-               shrl    $16, %eax
-LenLower:      subb    $1, %al
-               adcl    $0, %edx
-
-/* Calculate the length of the match. If it is longer than MAX_MATCH,  */
-/* then automatically accept it as the best possible match and leave.  */
-
-               lea     (%edi,%edx), %eax
-               movl    scan(%esp), %edi
-               subl    %edi, %eax
-               cmpl    $MAX_MATCH, %eax
-               jge     LenMaximum
-
-/* If the length of the match is not longer than the best match we     */
-/* have so far, then forget it and return to the lookup loop.          */
-
-               movl    deflatestate(%esp), %edx
-               movl    bestlen(%esp), %ebx
-               cmpl    %ebx, %eax
-               jg      LongerMatch
-               movl    chainlenscanend(%esp), %ebx
-               movl    windowbestlen(%esp), %esi
-               movl    dsPrev(%edx), %edi
-               movl    wmask(%esp), %edx
-               andl    %ecx, %edx
-               jmp     LookupLoop
-
-/*         s->match_start = cur_match;                                 */
-/*         best_len = len;                                             */
-/*         if (len >= nice_match) break;                               */
-/*         scan_end = *(ushf*)(scan+best_len-1);                       */
-
-LongerMatch:   movl    nicematch(%esp), %ebx
-               movl    %eax, bestlen(%esp)
-               movl    %ecx, dsMatchStart(%edx)
-               cmpl    %ebx, %eax
-               jge     LeaveNow
-               movl    window(%esp), %esi
-               addl    %eax, %esi
-               movl    %esi, windowbestlen(%esp)
-               movl    chainlenscanend(%esp), %ebx
-               movw    -1(%edi,%eax), %bx
-               movl    dsPrev(%edx), %edi
-               movl    %ebx, chainlenscanend(%esp)
-               movl    wmask(%esp), %edx
-               andl    %ecx, %edx
-               jmp     LookupLoop
-
-/* Accept the current string, with the maximum possible length.                */
-
-LenMaximum:    movl    deflatestate(%esp), %edx
-               movl    $MAX_MATCH, bestlen(%esp)
-               movl    %ecx, dsMatchStart(%edx)
-
-/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;          */
-/* return s->lookahead;                                                        */
-
-LeaveNow:
-               movl    deflatestate(%esp), %edx
-               movl    bestlen(%esp), %ebx
-               movl    dsLookahead(%edx), %eax
-               cmpl    %eax, %ebx
-               jg      LookaheadRet
-               movl    %ebx, %eax
-LookaheadRet:
-
-/* Restore the stack and return from whence we came.                   */
-
-               addl    $LocalVarsSize, %esp
-               popl    %ebx
-               popl    %esi
-               popl    %edi
-               popl    %ebp
-match_init:    ret
+/* match.s -- Pentium-optimized version of longest_match()\r
+ * Written for zlib 1.1.2\r
+ * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>\r
+ *\r
+ * This is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License.\r
+ */\r
+\r
+#ifndef NO_UNDERLINE\r
+#define        match_init      _match_init\r
+#define        longest_match   _longest_match\r
+#endif\r
+\r
+#define        MAX_MATCH       (258)\r
+#define        MIN_MATCH       (3)\r
+#define        MIN_LOOKAHEAD   (MAX_MATCH + MIN_MATCH + 1)\r
+#define        MAX_MATCH_8     ((MAX_MATCH + 7) & ~7)\r
+\r
+/* stack frame offsets */\r
+\r
+#define        wmask                   0       /* local copy of s->wmask       */\r
+#define        window                  4       /* local copy of s->window      */\r
+#define        windowbestlen           8       /* s->window + bestlen          */\r
+#define        chainlenscanend         12      /* high word: current chain len */\r
+                                       /* low word: last bytes sought  */\r
+#define        scanstart               16      /* first two bytes of string    */\r
+#define        scanalign               20      /* dword-misalignment of string */\r
+#define        nicematch               24      /* a good enough match size     */\r
+#define        bestlen                 28      /* size of best match so far    */\r
+#define        scan                    32      /* ptr to string wanting match  */\r
+\r
+#define        LocalVarsSize           (36)\r
+/*     saved ebx               36 */\r
+/*     saved edi               40 */\r
+/*     saved esi               44 */\r
+/*     saved ebp               48 */\r
+/*     return address          52 */\r
+#define        deflatestate            56      /* the function arguments       */\r
+#define        curmatch                60\r
+\r
+/* Offsets for fields in the deflate_state structure. These numbers\r
+ * are calculated from the definition of deflate_state, with the\r
+ * assumption that the compiler will dword-align the fields. (Thus,\r
+ * changing the definition of deflate_state could easily cause this\r
+ * program to crash horribly, without so much as a warning at\r
+ * compile time. Sigh.)\r
+ */\r
+\r
+/* All the +zlib1222add offsets are due to the addition of fields\r
+ *  in zlib in the deflate_state structure since the asm code was first written\r
+ * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").\r
+ * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").\r
+ * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").\r
+ */\r
+\r
+#define zlib1222add            (8)\r
+\r
+#define        dsWSize                 (36+zlib1222add)\r
+#define        dsWMask                 (44+zlib1222add)\r
+#define        dsWindow                (48+zlib1222add)\r
+#define        dsPrev                  (56+zlib1222add)\r
+#define        dsMatchLen              (88+zlib1222add)\r
+#define        dsPrevMatch             (92+zlib1222add)\r
+#define        dsStrStart              (100+zlib1222add)\r
+#define        dsMatchStart            (104+zlib1222add)\r
+#define        dsLookahead             (108+zlib1222add)\r
+#define        dsPrevLen               (112+zlib1222add)\r
+#define        dsMaxChainLen           (116+zlib1222add)\r
+#define        dsGoodMatch             (132+zlib1222add)\r
+#define        dsNiceMatch             (136+zlib1222add)\r
+\r
+\r
+.file "match.S"\r
+\r
+.globl match_init, longest_match\r
+\r
+.text\r
+\r
+/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */\r
+\r
+longest_match:\r
+\r
+/* Save registers that the compiler may be using, and adjust %esp to   */\r
+/* make room for our stack frame.                                      */\r
+\r
+               pushl   %ebp\r
+               pushl   %edi\r
+               pushl   %esi\r
+               pushl   %ebx\r
+               subl    $LocalVarsSize, %esp\r
+\r
+/* Retrieve the function arguments. %ecx will hold cur_match           */\r
+/* throughout the entire function. %edx will hold the pointer to the   */\r
+/* deflate_state structure during the function's setup (before         */\r
+/* entering the main loop).                                            */\r
+\r
+               movl    deflatestate(%esp), %edx\r
+               movl    curmatch(%esp), %ecx\r
+\r
+/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;     */\r
+\r
+               movl    dsNiceMatch(%edx), %eax\r
+               movl    dsLookahead(%edx), %ebx\r
+               cmpl    %eax, %ebx\r
+               jl      LookaheadLess\r
+               movl    %eax, %ebx\r
+LookaheadLess: movl    %ebx, nicematch(%esp)\r
+\r
+/* register Bytef *scan = s->window + s->strstart;                     */\r
+\r
+               movl    dsWindow(%edx), %esi\r
+               movl    %esi, window(%esp)\r
+               movl    dsStrStart(%edx), %ebp\r
+               lea     (%esi,%ebp), %edi\r
+               movl    %edi, scan(%esp)\r
+\r
+/* Determine how many bytes the scan ptr is off from being             */\r
+/* dword-aligned.                                                      */\r
+\r
+               movl    %edi, %eax\r
+               negl    %eax\r
+               andl    $3, %eax\r
+               movl    %eax, scanalign(%esp)\r
+\r
+/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */\r
+/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */\r
+\r
+               movl    dsWSize(%edx), %eax\r
+               subl    $MIN_LOOKAHEAD, %eax\r
+               subl    %eax, %ebp\r
+               jg      LimitPositive\r
+               xorl    %ebp, %ebp\r
+LimitPositive:\r
+\r
+/* unsigned chain_length = s->max_chain_length;                                */\r
+/* if (s->prev_length >= s->good_match) {                              */\r
+/*     chain_length >>= 2;                                             */\r
+/* }                                                                   */\r
+\r
+               movl    dsPrevLen(%edx), %eax\r
+               movl    dsGoodMatch(%edx), %ebx\r
+               cmpl    %ebx, %eax\r
+               movl    dsMaxChainLen(%edx), %ebx\r
+               jl      LastMatchGood\r
+               shrl    $2, %ebx\r
+LastMatchGood:\r
+\r
+/* chainlen is decremented once beforehand so that the function can    */\r
+/* use the sign flag instead of the zero flag for the exit test.       */\r
+/* It is then shifted into the high word, to make room for the scanend */\r
+/* scanend value, which it will always accompany.                      */\r
+\r
+               decl    %ebx\r
+               shll    $16, %ebx\r
+\r
+/* int best_len = s->prev_length;                                      */\r
+\r
+               movl    dsPrevLen(%edx), %eax\r
+               movl    %eax, bestlen(%esp)\r
+\r
+/* Store the sum of s->window + best_len in %esi locally, and in %esi. */\r
+\r
+               addl    %eax, %esi\r
+               movl    %esi, windowbestlen(%esp)\r
+\r
+/* register ush scan_start = *(ushf*)scan;                             */\r
+/* register ush scan_end   = *(ushf*)(scan+best_len-1);                        */\r
+\r
+               movw    (%edi), %bx\r
+               movw    %bx, scanstart(%esp)\r
+               movw    -1(%edi,%eax), %bx\r
+               movl    %ebx, chainlenscanend(%esp)\r
+\r
+/* Posf *prev = s->prev;                                               */\r
+/* uInt wmask = s->w_mask;                                             */\r
+\r
+               movl    dsPrev(%edx), %edi\r
+               movl    dsWMask(%edx), %edx\r
+               mov     %edx, wmask(%esp)\r
+\r
+/* Jump into the main loop.                                            */\r
+\r
+               jmp     LoopEntry\r
+\r
+.balign 16\r
+\r
+/* do {\r
+ *     match = s->window + cur_match;\r
+ *     if (*(ushf*)(match+best_len-1) != scan_end ||\r
+ *         *(ushf*)match != scan_start) continue;\r
+ *     [...]\r
+ * } while ((cur_match = prev[cur_match & wmask]) > limit\r
+ *          && --chain_length != 0);\r
+ *\r
+ * Here is the inner loop of the function. The function will spend the\r
+ * majority of its time in this loop, and majority of that time will\r
+ * be spent in the first ten instructions.\r
+ *\r
+ * Within this loop:\r
+ * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)\r
+ * %ecx = curmatch\r
+ * %edx = curmatch & wmask\r
+ * %esi = windowbestlen - i.e., (window + bestlen)\r
+ * %edi = prev\r
+ * %ebp = limit\r
+ *\r
+ * Two optimization notes on the choice of instructions:\r
+ *\r
+ * The first instruction uses a 16-bit address, which costs an extra,\r
+ * unpairable cycle. This is cheaper than doing a 32-bit access and\r
+ * zeroing the high word, due to the 3-cycle misalignment penalty which\r
+ * would occur half the time. This also turns out to be cheaper than\r
+ * doing two separate 8-bit accesses, as the memory is so rarely in the\r
+ * L1 cache.\r
+ *\r
+ * The window buffer, however, apparently spends a lot of time in the\r
+ * cache, and so it is faster to retrieve the word at the end of the\r
+ * match string with two 8-bit loads. The instructions that test the\r
+ * word at the beginning of the match string, however, are executed\r
+ * much less frequently, and there it was cheaper to use 16-bit\r
+ * instructions, which avoided the necessity of saving off and\r
+ * subsequently reloading one of the other registers.\r
+ */\r
+LookupLoop:\r
+                                                       /* 1 U & V  */\r
+               movw    (%edi,%edx,2), %cx              /* 2 U pipe */\r
+               movl    wmask(%esp), %edx               /* 2 V pipe */\r
+               cmpl    %ebp, %ecx                      /* 3 U pipe */\r
+               jbe     LeaveNow                        /* 3 V pipe */\r
+               subl    $0x00010000, %ebx               /* 4 U pipe */\r
+               js      LeaveNow                        /* 4 V pipe */\r
+LoopEntry:     movb    -1(%esi,%ecx), %al              /* 5 U pipe */\r
+               andl    %ecx, %edx                      /* 5 V pipe */\r
+               cmpb    %bl, %al                        /* 6 U pipe */\r
+               jnz     LookupLoop                      /* 6 V pipe */\r
+               movb    (%esi,%ecx), %ah\r
+               cmpb    %bh, %ah\r
+               jnz     LookupLoop\r
+               movl    window(%esp), %eax\r
+               movw    (%eax,%ecx), %ax\r
+               cmpw    scanstart(%esp), %ax\r
+               jnz     LookupLoop\r
+\r
+/* Store the current value of chainlen.                                        */\r
+\r
+               movl    %ebx, chainlenscanend(%esp)\r
+\r
+/* Point %edi to the string under scrutiny, and %esi to the string we  */\r
+/* are hoping to match it up with. In actuality, %esi and %edi are     */\r
+/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is     */\r
+/* initialized to -(MAX_MATCH_8 - scanalign).                          */\r
+\r
+               movl    window(%esp), %esi\r
+               movl    scan(%esp), %edi\r
+               addl    %ecx, %esi\r
+               movl    scanalign(%esp), %eax\r
+               movl    $(-MAX_MATCH_8), %edx\r
+               lea     MAX_MATCH_8(%edi,%eax), %edi\r
+               lea     MAX_MATCH_8(%esi,%eax), %esi\r
+\r
+/* Test the strings for equality, 8 bytes at a time. At the end,\r
+ * adjust %edx so that it is offset to the exact byte that mismatched.\r
+ *\r
+ * We already know at this point that the first three bytes of the\r
+ * strings match each other, and they can be safely passed over before\r
+ * starting the compare loop. So what this code does is skip over 0-3\r
+ * bytes, as much as necessary in order to dword-align the %edi\r
+ * pointer. (%esi will still be misaligned three times out of four.)\r
+ *\r
+ * It should be confessed that this loop usually does not represent\r
+ * much of the total running time. Replacing it with a more\r
+ * straightforward "rep cmpsb" would not drastically degrade\r
+ * performance.\r
+ */\r
+LoopCmps:\r
+               movl    (%esi,%edx), %eax\r
+               movl    (%edi,%edx), %ebx\r
+               xorl    %ebx, %eax\r
+               jnz     LeaveLoopCmps\r
+               movl    4(%esi,%edx), %eax\r
+               movl    4(%edi,%edx), %ebx\r
+               xorl    %ebx, %eax\r
+               jnz     LeaveLoopCmps4\r
+               addl    $8, %edx\r
+               jnz     LoopCmps\r
+               jmp     LenMaximum\r
+LeaveLoopCmps4:        addl    $4, %edx\r
+LeaveLoopCmps: testl   $0x0000FFFF, %eax\r
+               jnz     LenLower\r
+               addl    $2, %edx\r
+               shrl    $16, %eax\r
+LenLower:      subb    $1, %al\r
+               adcl    $0, %edx\r
+\r
+/* Calculate the length of the match. If it is longer than MAX_MATCH,  */\r
+/* then automatically accept it as the best possible match and leave.  */\r
+\r
+               lea     (%edi,%edx), %eax\r
+               movl    scan(%esp), %edi\r
+               subl    %edi, %eax\r
+               cmpl    $MAX_MATCH, %eax\r
+               jge     LenMaximum\r
+\r
+/* If the length of the match is not longer than the best match we     */\r
+/* have so far, then forget it and return to the lookup loop.          */\r
+\r
+               movl    deflatestate(%esp), %edx\r
+               movl    bestlen(%esp), %ebx\r
+               cmpl    %ebx, %eax\r
+               jg      LongerMatch\r
+               movl    chainlenscanend(%esp), %ebx\r
+               movl    windowbestlen(%esp), %esi\r
+               movl    dsPrev(%edx), %edi\r
+               movl    wmask(%esp), %edx\r
+               andl    %ecx, %edx\r
+               jmp     LookupLoop\r
+\r
+/*         s->match_start = cur_match;                                 */\r
+/*         best_len = len;                                             */\r
+/*         if (len >= nice_match) break;                               */\r
+/*         scan_end = *(ushf*)(scan+best_len-1);                       */\r
+\r
+LongerMatch:   movl    nicematch(%esp), %ebx\r
+               movl    %eax, bestlen(%esp)\r
+               movl    %ecx, dsMatchStart(%edx)\r
+               cmpl    %ebx, %eax\r
+               jge     LeaveNow\r
+               movl    window(%esp), %esi\r
+               addl    %eax, %esi\r
+               movl    %esi, windowbestlen(%esp)\r
+               movl    chainlenscanend(%esp), %ebx\r
+               movw    -1(%edi,%eax), %bx\r
+               movl    dsPrev(%edx), %edi\r
+               movl    %ebx, chainlenscanend(%esp)\r
+               movl    wmask(%esp), %edx\r
+               andl    %ecx, %edx\r
+               jmp     LookupLoop\r
+\r
+/* Accept the current string, with the maximum possible length.                */\r
+\r
+LenMaximum:    movl    deflatestate(%esp), %edx\r
+               movl    $MAX_MATCH, bestlen(%esp)\r
+               movl    %ecx, dsMatchStart(%edx)\r
+\r
+/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;          */\r
+/* return s->lookahead;                                                        */\r
+\r
+LeaveNow:\r
+               movl    deflatestate(%esp), %edx\r
+               movl    bestlen(%esp), %ebx\r
+               movl    dsLookahead(%edx), %eax\r
+               cmpl    %eax, %ebx\r
+               jg      LookaheadRet\r
+               movl    %ebx, %eax\r
+LookaheadRet:\r
+\r
+/* Restore the stack and return from whence we came.                   */\r
+\r
+               addl    $LocalVarsSize, %esp\r
+               popl    %ebx\r
+               popl    %esi\r
+               popl    %edi\r
+               popl    %ebp\r
+match_init:    ret\r
index 8e86c33..c24be4d 100644 (file)
-/* match.s -- Pentium-Pro-optimized version of longest_match()
- * Written for zlib 1.1.2
- * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License.
- */
-
-#ifndef NO_UNDERLINE
-#define        match_init      _match_init
-#define        longest_match   _longest_match
-#endif
-
-#define        MAX_MATCH       (258)
-#define        MIN_MATCH       (3)
-#define        MIN_LOOKAHEAD   (MAX_MATCH + MIN_MATCH + 1)
-#define        MAX_MATCH_8     ((MAX_MATCH + 7) & ~7)
-
-/* stack frame offsets */
-
-#define        chainlenwmask           0       /* high word: current chain len */
-                                       /* low word: s->wmask           */
-#define        window                  4       /* local copy of s->window      */
-#define        windowbestlen           8       /* s->window + bestlen          */
-#define        scanstart               16      /* first two bytes of string    */
-#define        scanend                 12      /* last two bytes of string     */
-#define        scanalign               20      /* dword-misalignment of string */
-#define        nicematch               24      /* a good enough match size     */
-#define        bestlen                 28      /* size of best match so far    */
-#define        scan                    32      /* ptr to string wanting match  */
-
-#define        LocalVarsSize           (36)
-/*     saved ebx               36 */
-/*     saved edi               40 */
-/*     saved esi               44 */
-/*     saved ebp               48 */
-/*     return address          52 */
-#define        deflatestate            56      /* the function arguments       */
-#define        curmatch                60
-
-/* Offsets for fields in the deflate_state structure. These numbers
- * are calculated from the definition of deflate_state, with the
- * assumption that the compiler will dword-align the fields. (Thus,
- * changing the definition of deflate_state could easily cause this
- * program to crash horribly, without so much as a warning at
- * compile time. Sigh.)
- */
-#define        dsWSize                 36
-#define        dsWMask                 44
-#define        dsWindow                48
-#define        dsPrev                  56
-#define        dsMatchLen              88
-#define        dsPrevMatch             92
-#define        dsStrStart              100
-#define        dsMatchStart            104
-#define        dsLookahead             108
-#define        dsPrevLen               112
-#define        dsMaxChainLen           116
-#define        dsGoodMatch             132
-#define        dsNiceMatch             136
-
-
-.file "match.S"
-
-.globl match_init, longest_match
-
-.text
-
-/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
-
-longest_match:
-
-/* Save registers that the compiler may be using, and adjust %esp to   */
-/* make room for our stack frame.                                      */
-
-               pushl   %ebp
-               pushl   %edi
-               pushl   %esi
-               pushl   %ebx
-               subl    $LocalVarsSize, %esp
-
-/* Retrieve the function arguments. %ecx will hold cur_match           */
-/* throughout the entire function. %edx will hold the pointer to the   */
-/* deflate_state structure during the function's setup (before         */
-/* entering the main loop).                                            */
-
-               movl    deflatestate(%esp), %edx
-               movl    curmatch(%esp), %ecx
-
-/* uInt wmask = s->w_mask;                                             */
-/* unsigned chain_length = s->max_chain_length;                                */
-/* if (s->prev_length >= s->good_match) {                              */
-/*     chain_length >>= 2;                                             */
-/* }                                                                   */
-
-               movl    dsPrevLen(%edx), %eax
-               movl    dsGoodMatch(%edx), %ebx
-               cmpl    %ebx, %eax
-               movl    dsWMask(%edx), %eax
-               movl    dsMaxChainLen(%edx), %ebx
-               jl      LastMatchGood
-               shrl    $2, %ebx
-LastMatchGood:
-
-/* chainlen is decremented once beforehand so that the function can    */
-/* use the sign flag instead of the zero flag for the exit test.       */
-/* It is then shifted into the high word, to make room for the wmask   */
-/* value, which it will always accompany.                              */
-
-               decl    %ebx
-               shll    $16, %ebx
-               orl     %eax, %ebx
-               movl    %ebx, chainlenwmask(%esp)
-
-/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;     */
-
-               movl    dsNiceMatch(%edx), %eax
-               movl    dsLookahead(%edx), %ebx
-               cmpl    %eax, %ebx
-               jl      LookaheadLess
-               movl    %eax, %ebx
-LookaheadLess: movl    %ebx, nicematch(%esp)
-
-/* register Bytef *scan = s->window + s->strstart;                     */
-
-               movl    dsWindow(%edx), %esi
-               movl    %esi, window(%esp)
-               movl    dsStrStart(%edx), %ebp
-               lea     (%esi,%ebp), %edi
-               movl    %edi, scan(%esp)
-
-/* Determine how many bytes the scan ptr is off from being             */
-/* dword-aligned.                                                      */
-
-               movl    %edi, %eax
-               negl    %eax
-               andl    $3, %eax
-               movl    %eax, scanalign(%esp)
-
-/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */
-/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */
-
-               movl    dsWSize(%edx), %eax
-               subl    $MIN_LOOKAHEAD, %eax
-               subl    %eax, %ebp
-               jg      LimitPositive
-               xorl    %ebp, %ebp
-LimitPositive:
-
-/* int best_len = s->prev_length;                                      */
-
-               movl    dsPrevLen(%edx), %eax
-               movl    %eax, bestlen(%esp)
-
-/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
-
-               addl    %eax, %esi
-               movl    %esi, windowbestlen(%esp)
-
-/* register ush scan_start = *(ushf*)scan;                             */
-/* register ush scan_end   = *(ushf*)(scan+best_len-1);                        */
-/* Posf *prev = s->prev;                                               */
-
-               movzwl  (%edi), %ebx
-               movl    %ebx, scanstart(%esp)
-               movzwl  -1(%edi,%eax), %ebx
-               movl    %ebx, scanend(%esp)
-               movl    dsPrev(%edx), %edi
-
-/* Jump into the main loop.                                            */
-
-               movl    chainlenwmask(%esp), %edx
-               jmp     LoopEntry
-
-.balign 16
-
-/* do {
- *     match = s->window + cur_match;
- *     if (*(ushf*)(match+best_len-1) != scan_end ||
- *         *(ushf*)match != scan_start) continue;
- *     [...]
- * } while ((cur_match = prev[cur_match & wmask]) > limit
- *          && --chain_length != 0);
- *
- * Here is the inner loop of the function. The function will spend the
- * majority of its time in this loop, and majority of that time will
- * be spent in the first ten instructions.
- *
- * Within this loop:
- * %ebx = scanend
- * %ecx = curmatch
- * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
- * %esi = windowbestlen - i.e., (window + bestlen)
- * %edi = prev
- * %ebp = limit
- */
-LookupLoop:
-               andl    %edx, %ecx
-               movzwl  (%edi,%ecx,2), %ecx
-               cmpl    %ebp, %ecx
-               jbe     LeaveNow
-               subl    $0x00010000, %edx
-               js      LeaveNow
-LoopEntry:     movzwl  -1(%esi,%ecx), %eax
-               cmpl    %ebx, %eax
-               jnz     LookupLoop
-               movl    window(%esp), %eax
-               movzwl  (%eax,%ecx), %eax
-               cmpl    scanstart(%esp), %eax
-               jnz     LookupLoop
-
-/* Store the current value of chainlen.                                        */
-
-               movl    %edx, chainlenwmask(%esp)
-
-/* Point %edi to the string under scrutiny, and %esi to the string we  */
-/* are hoping to match it up with. In actuality, %esi and %edi are     */
-/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is     */
-/* initialized to -(MAX_MATCH_8 - scanalign).                          */
-
-               movl    window(%esp), %esi
-               movl    scan(%esp), %edi
-               addl    %ecx, %esi
-               movl    scanalign(%esp), %eax
-               movl    $(-MAX_MATCH_8), %edx
-               lea     MAX_MATCH_8(%edi,%eax), %edi
-               lea     MAX_MATCH_8(%esi,%eax), %esi
-
-/* Test the strings for equality, 8 bytes at a time. At the end,
- * adjust %edx so that it is offset to the exact byte that mismatched.
- *
- * We already know at this point that the first three bytes of the
- * strings match each other, and they can be safely passed over before
- * starting the compare loop. So what this code does is skip over 0-3
- * bytes, as much as necessary in order to dword-align the %edi
- * pointer. (%esi will still be misaligned three times out of four.)
- *
- * It should be confessed that this loop usually does not represent
- * much of the total running time. Replacing it with a more
- * straightforward "rep cmpsb" would not drastically degrade
- * performance.
- */
-LoopCmps:
-               movl    (%esi,%edx), %eax
-               xorl    (%edi,%edx), %eax
-               jnz     LeaveLoopCmps
-               movl    4(%esi,%edx), %eax
-               xorl    4(%edi,%edx), %eax
-               jnz     LeaveLoopCmps4
-               addl    $8, %edx
-               jnz     LoopCmps
-               jmp     LenMaximum
-LeaveLoopCmps4:        addl    $4, %edx
-LeaveLoopCmps: testl   $0x0000FFFF, %eax
-               jnz     LenLower
-               addl    $2, %edx
-               shrl    $16, %eax
-LenLower:      subb    $1, %al
-               adcl    $0, %edx
-
-/* Calculate the length of the match. If it is longer than MAX_MATCH,  */
-/* then automatically accept it as the best possible match and leave.  */
-
-               lea     (%edi,%edx), %eax
-               movl    scan(%esp), %edi
-               subl    %edi, %eax
-               cmpl    $MAX_MATCH, %eax
-               jge     LenMaximum
-
-/* If the length of the match is not longer than the best match we     */
-/* have so far, then forget it and return to the lookup loop.          */
-
-               movl    deflatestate(%esp), %edx
-               movl    bestlen(%esp), %ebx
-               cmpl    %ebx, %eax
-               jg      LongerMatch
-               movl    windowbestlen(%esp), %esi
-               movl    dsPrev(%edx), %edi
-               movl    scanend(%esp), %ebx
-               movl    chainlenwmask(%esp), %edx
-               jmp     LookupLoop
-
-/*         s->match_start = cur_match;                                 */
-/*         best_len = len;                                             */
-/*         if (len >= nice_match) break;                               */
-/*         scan_end = *(ushf*)(scan+best_len-1);                       */
-
-LongerMatch:   movl    nicematch(%esp), %ebx
-               movl    %eax, bestlen(%esp)
-               movl    %ecx, dsMatchStart(%edx)
-               cmpl    %ebx, %eax
-               jge     LeaveNow
-               movl    window(%esp), %esi
-               addl    %eax, %esi
-               movl    %esi, windowbestlen(%esp)
-               movzwl  -1(%edi,%eax), %ebx
-               movl    dsPrev(%edx), %edi
-               movl    %ebx, scanend(%esp)
-               movl    chainlenwmask(%esp), %edx
-               jmp     LookupLoop
-
-/* Accept the current string, with the maximum possible length.                */
-
-LenMaximum:    movl    deflatestate(%esp), %edx
-               movl    $MAX_MATCH, bestlen(%esp)
-               movl    %ecx, dsMatchStart(%edx)
-
-/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;          */
-/* return s->lookahead;                                                        */
-
-LeaveNow:
-               movl    deflatestate(%esp), %edx
-               movl    bestlen(%esp), %ebx
-               movl    dsLookahead(%edx), %eax
-               cmpl    %eax, %ebx
-               jg      LookaheadRet
-               movl    %ebx, %eax
-LookaheadRet:
-
-/* Restore the stack and return from whence we came.                   */
-
-               addl    $LocalVarsSize, %esp
-               popl    %ebx
-               popl    %esi
-               popl    %edi
-               popl    %ebp
-match_init:    ret
+/* match.s -- Pentium-Pro-optimized version of longest_match()\r
+ * Written for zlib 1.1.2\r
+ * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>\r
+ *\r
+ * This is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License.\r
+ */\r
+\r
+#ifndef NO_UNDERLINE\r
+#define        match_init      _match_init\r
+#define        longest_match   _longest_match\r
+#endif\r
+\r
+#define        MAX_MATCH       (258)\r
+#define        MIN_MATCH       (3)\r
+#define        MIN_LOOKAHEAD   (MAX_MATCH + MIN_MATCH + 1)\r
+#define        MAX_MATCH_8     ((MAX_MATCH + 7) & ~7)\r
+\r
+/* stack frame offsets */\r
+\r
+#define        chainlenwmask           0       /* high word: current chain len */\r
+                                       /* low word: s->wmask           */\r
+#define        window                  4       /* local copy of s->window      */\r
+#define        windowbestlen           8       /* s->window + bestlen          */\r
+#define        scanstart               16      /* first two bytes of string    */\r
+#define        scanend                 12      /* last two bytes of string     */\r
+#define        scanalign               20      /* dword-misalignment of string */\r
+#define        nicematch               24      /* a good enough match size     */\r
+#define        bestlen                 28      /* size of best match so far    */\r
+#define        scan                    32      /* ptr to string wanting match  */\r
+\r
+#define        LocalVarsSize           (36)\r
+/*     saved ebx               36 */\r
+/*     saved edi               40 */\r
+/*     saved esi               44 */\r
+/*     saved ebp               48 */\r
+/*     return address          52 */\r
+#define        deflatestate            56      /* the function arguments       */\r
+#define        curmatch                60\r
+\r
+/* All the +zlib1222add offsets are due to the addition of fields\r
+ *  in zlib in the deflate_state structure since the asm code was first written\r
+ * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").\r
+ * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").\r
+ * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").\r
+ */\r
+\r
+#define zlib1222add            (8)\r
+\r
+#define        dsWSize                 (36+zlib1222add)\r
+#define        dsWMask                 (44+zlib1222add)\r
+#define        dsWindow                (48+zlib1222add)\r
+#define        dsPrev                  (56+zlib1222add)\r
+#define        dsMatchLen              (88+zlib1222add)\r
+#define        dsPrevMatch             (92+zlib1222add)\r
+#define        dsStrStart              (100+zlib1222add)\r
+#define        dsMatchStart            (104+zlib1222add)\r
+#define        dsLookahead             (108+zlib1222add)\r
+#define        dsPrevLen               (112+zlib1222add)\r
+#define        dsMaxChainLen           (116+zlib1222add)\r
+#define        dsGoodMatch             (132+zlib1222add)\r
+#define        dsNiceMatch             (136+zlib1222add)\r
+\r
+\r
+.file "match.S"\r
+\r
+.globl match_init, longest_match\r
+\r
+.text\r
+\r
+/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */\r
+\r
+longest_match:\r
+\r
+/* Save registers that the compiler may be using, and adjust %esp to   */\r
+/* make room for our stack frame.                                      */\r
+\r
+               pushl   %ebp\r
+               pushl   %edi\r
+               pushl   %esi\r
+               pushl   %ebx\r
+               subl    $LocalVarsSize, %esp\r
+\r
+/* Retrieve the function arguments. %ecx will hold cur_match           */\r
+/* throughout the entire function. %edx will hold the pointer to the   */\r
+/* deflate_state structure during the function's setup (before         */\r
+/* entering the main loop).                                            */\r
+\r
+               movl    deflatestate(%esp), %edx\r
+               movl    curmatch(%esp), %ecx\r
+\r
+/* uInt wmask = s->w_mask;                                             */\r
+/* unsigned chain_length = s->max_chain_length;                                */\r
+/* if (s->prev_length >= s->good_match) {                              */\r
+/*     chain_length >>= 2;                                             */\r
+/* }                                                                   */\r
+\r
+               movl    dsPrevLen(%edx), %eax\r
+               movl    dsGoodMatch(%edx), %ebx\r
+               cmpl    %ebx, %eax\r
+               movl    dsWMask(%edx), %eax\r
+               movl    dsMaxChainLen(%edx), %ebx\r
+               jl      LastMatchGood\r
+               shrl    $2, %ebx\r
+LastMatchGood:\r
+\r
+/* chainlen is decremented once beforehand so that the function can    */\r
+/* use the sign flag instead of the zero flag for the exit test.       */\r
+/* It is then shifted into the high word, to make room for the wmask   */\r
+/* value, which it will always accompany.                              */\r
+\r
+               decl    %ebx\r
+               shll    $16, %ebx\r
+               orl     %eax, %ebx\r
+               movl    %ebx, chainlenwmask(%esp)\r
+\r
+/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;     */\r
+\r
+               movl    dsNiceMatch(%edx), %eax\r
+               movl    dsLookahead(%edx), %ebx\r
+               cmpl    %eax, %ebx\r
+               jl      LookaheadLess\r
+               movl    %eax, %ebx\r
+LookaheadLess: movl    %ebx, nicematch(%esp)\r
+\r
+/* register Bytef *scan = s->window + s->strstart;                     */\r
+\r
+               movl    dsWindow(%edx), %esi\r
+               movl    %esi, window(%esp)\r
+               movl    dsStrStart(%edx), %ebp\r
+               lea     (%esi,%ebp), %edi\r
+               movl    %edi, scan(%esp)\r
+\r
+/* Determine how many bytes the scan ptr is off from being             */\r
+/* dword-aligned.                                                      */\r
+\r
+               movl    %edi, %eax\r
+               negl    %eax\r
+               andl    $3, %eax\r
+               movl    %eax, scanalign(%esp)\r
+\r
+/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */\r
+/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */\r
+\r
+               movl    dsWSize(%edx), %eax\r
+               subl    $MIN_LOOKAHEAD, %eax\r
+               subl    %eax, %ebp\r
+               jg      LimitPositive\r
+               xorl    %ebp, %ebp\r
+LimitPositive:\r
+\r
+/* int best_len = s->prev_length;                                      */\r
+\r
+               movl    dsPrevLen(%edx), %eax\r
+               movl    %eax, bestlen(%esp)\r
+\r
+/* Store the sum of s->window + best_len in %esi locally, and in %esi. */\r
+\r
+               addl    %eax, %esi\r
+               movl    %esi, windowbestlen(%esp)\r
+\r
+/* register ush scan_start = *(ushf*)scan;                             */\r
+/* register ush scan_end   = *(ushf*)(scan+best_len-1);                        */\r
+/* Posf *prev = s->prev;                                               */\r
+\r
+               movzwl  (%edi), %ebx\r
+               movl    %ebx, scanstart(%esp)\r
+               movzwl  -1(%edi,%eax), %ebx\r
+               movl    %ebx, scanend(%esp)\r
+               movl    dsPrev(%edx), %edi\r
+\r
+/* Jump into the main loop.                                            */\r
+\r
+               movl    chainlenwmask(%esp), %edx\r
+               jmp     LoopEntry\r
+\r
+.balign 16\r
+\r
+/* do {\r
+ *     match = s->window + cur_match;\r
+ *     if (*(ushf*)(match+best_len-1) != scan_end ||\r
+ *         *(ushf*)match != scan_start) continue;\r
+ *     [...]\r
+ * } while ((cur_match = prev[cur_match & wmask]) > limit\r
+ *          && --chain_length != 0);\r
+ *\r
+ * Here is the inner loop of the function. The function will spend the\r
+ * majority of its time in this loop, and majority of that time will\r
+ * be spent in the first ten instructions.\r
+ *\r
+ * Within this loop:\r
+ * %ebx = scanend\r
+ * %ecx = curmatch\r
+ * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)\r
+ * %esi = windowbestlen - i.e., (window + bestlen)\r
+ * %edi = prev\r
+ * %ebp = limit\r
+ */\r
+LookupLoop:\r
+               andl    %edx, %ecx\r
+               movzwl  (%edi,%ecx,2), %ecx\r
+               cmpl    %ebp, %ecx\r
+               jbe     LeaveNow\r
+               subl    $0x00010000, %edx\r
+               js      LeaveNow\r
+LoopEntry:     movzwl  -1(%esi,%ecx), %eax\r
+               cmpl    %ebx, %eax\r
+               jnz     LookupLoop\r
+               movl    window(%esp), %eax\r
+               movzwl  (%eax,%ecx), %eax\r
+               cmpl    scanstart(%esp), %eax\r
+               jnz     LookupLoop\r
+\r
+/* Store the current value of chainlen.                                        */\r
+\r
+               movl    %edx, chainlenwmask(%esp)\r
+\r
+/* Point %edi to the string under scrutiny, and %esi to the string we  */\r
+/* are hoping to match it up with. In actuality, %esi and %edi are     */\r
+/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is     */\r
+/* initialized to -(MAX_MATCH_8 - scanalign).                          */\r
+\r
+               movl    window(%esp), %esi\r
+               movl    scan(%esp), %edi\r
+               addl    %ecx, %esi\r
+               movl    scanalign(%esp), %eax\r
+               movl    $(-MAX_MATCH_8), %edx\r
+               lea     MAX_MATCH_8(%edi,%eax), %edi\r
+               lea     MAX_MATCH_8(%esi,%eax), %esi\r
+\r
+/* Test the strings for equality, 8 bytes at a time. At the end,\r
+ * adjust %edx so that it is offset to the exact byte that mismatched.\r
+ *\r
+ * We already know at this point that the first three bytes of the\r
+ * strings match each other, and they can be safely passed over before\r
+ * starting the compare loop. So what this code does is skip over 0-3\r
+ * bytes, as much as necessary in order to dword-align the %edi\r
+ * pointer. (%esi will still be misaligned three times out of four.)\r
+ *\r
+ * It should be confessed that this loop usually does not represent\r
+ * much of the total running time. Replacing it with a more\r
+ * straightforward "rep cmpsb" would not drastically degrade\r
+ * performance.\r
+ */\r
+LoopCmps:\r
+               movl    (%esi,%edx), %eax\r
+               xorl    (%edi,%edx), %eax\r
+               jnz     LeaveLoopCmps\r
+               movl    4(%esi,%edx), %eax\r
+               xorl    4(%edi,%edx), %eax\r
+               jnz     LeaveLoopCmps4\r
+               addl    $8, %edx\r
+               jnz     LoopCmps\r
+               jmp     LenMaximum\r
+LeaveLoopCmps4:        addl    $4, %edx\r
+LeaveLoopCmps: testl   $0x0000FFFF, %eax\r
+               jnz     LenLower\r
+               addl    $2, %edx\r
+               shrl    $16, %eax\r
+LenLower:      subb    $1, %al\r
+               adcl    $0, %edx\r
+\r
+/* Calculate the length of the match. If it is longer than MAX_MATCH,  */\r
+/* then automatically accept it as the best possible match and leave.  */\r
+\r
+               lea     (%edi,%edx), %eax\r
+               movl    scan(%esp), %edi\r
+               subl    %edi, %eax\r
+               cmpl    $MAX_MATCH, %eax\r
+               jge     LenMaximum\r
+\r
+/* If the length of the match is not longer than the best match we     */\r
+/* have so far, then forget it and return to the lookup loop.          */\r
+\r
+               movl    deflatestate(%esp), %edx\r
+               movl    bestlen(%esp), %ebx\r
+               cmpl    %ebx, %eax\r
+               jg      LongerMatch\r
+               movl    windowbestlen(%esp), %esi\r
+               movl    dsPrev(%edx), %edi\r
+               movl    scanend(%esp), %ebx\r
+               movl    chainlenwmask(%esp), %edx\r
+               jmp     LookupLoop\r
+\r
+/*         s->match_start = cur_match;                                 */\r
+/*         best_len = len;                                             */\r
+/*         if (len >= nice_match) break;                               */\r
+/*         scan_end = *(ushf*)(scan+best_len-1);                       */\r
+\r
+LongerMatch:   movl    nicematch(%esp), %ebx\r
+               movl    %eax, bestlen(%esp)\r
+               movl    %ecx, dsMatchStart(%edx)\r
+               cmpl    %ebx, %eax\r
+               jge     LeaveNow\r
+               movl    window(%esp), %esi\r
+               addl    %eax, %esi\r
+               movl    %esi, windowbestlen(%esp)\r
+               movzwl  -1(%edi,%eax), %ebx\r
+               movl    dsPrev(%edx), %edi\r
+               movl    %ebx, scanend(%esp)\r
+               movl    chainlenwmask(%esp), %edx\r
+               jmp     LookupLoop\r
+\r
+/* Accept the current string, with the maximum possible length.                */\r
+\r
+LenMaximum:    movl    deflatestate(%esp), %edx\r
+               movl    $MAX_MATCH, bestlen(%esp)\r
+               movl    %ecx, dsMatchStart(%edx)\r
+\r
+/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;          */\r
+/* return s->lookahead;                                                        */\r
+\r
+LeaveNow:\r
+               movl    deflatestate(%esp), %edx\r
+               movl    bestlen(%esp), %ebx\r
+               movl    dsLookahead(%edx), %eax\r
+               cmpl    %eax, %ebx\r
+               jg      LookaheadRet\r
+               movl    %ebx, %eax\r
+LookaheadRet:\r
+\r
+/* Restore the stack and return from whence we came.                   */\r
+\r
+               addl    $LocalVarsSize, %esp\r
+               popl    %ebx\r
+               popl    %esi\r
+               popl    %edi\r
+               popl    %ebp\r
+match_init:    ret\r
index 10bf58c..1073c0a 100644 (file)
  * zlib.h must be included before this header file.
  */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm,
                                     in_func in, void FAR *in_desc,
                                     out_func out, void FAR *out_desc));
@@ -27,3 +31,7 @@ ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm,
 #define inflateBack9Init(strm, window) \
         inflateBack9Init_((strm), (window), \
         ZLIB_VERSION, sizeof(z_stream))
+
+#ifdef __cplusplus
+}
+#endif
index 9b48bc5..9e37840 100644 (file)
@@ -1,5 +1,5 @@
 /* inftree9.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2005 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -9,7 +9,7 @@
 #define MAXBITS 15
 
 const char inflate9_copyright[] =
-   " inflate9 1.2.2 Copyright 1995-2004 Mark Adler ";
+   " inflate9 1.2.2.4 Copyright 1995-2005 Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -64,7 +64,7 @@ unsigned short FAR *work;
     static const unsigned short lext[31] = { /* Length codes 257..285 extra */
         128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
         130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
-        133, 133, 133, 133, 144, 199, 198};
+        133, 133, 133, 133, 144, 206, 69};
     static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
         65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
index 2287804..4b03a71 100644 (file)
-
-; match.asm -- Pentium-Pro optimized version of longest_match()
-;
-; Updated for zlib 1.1.3 and converted to MASM 6.1x
-; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com>
-;                    and Chuck Walbourn <chuckw@kinesoft.com>
-; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro>
-;
-; This is free software; you can redistribute it and/or modify it
-; under the terms of the GNU General Public License.
-
-; Based on match.S
-; Written for zlib 1.1.2
-; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
-
-       .686P
-       .MODEL  FLAT
-
-;===========================================================================
-; EQUATES
-;===========================================================================
-
-MAX_MATCH      EQU 258
-MIN_MATCH      EQU 3
-MIN_LOOKAHEAD  EQU (MAX_MATCH + MIN_MATCH + 1)
-MAX_MATCH_8    EQU ((MAX_MATCH + 7) AND (NOT 7))
-
-;===========================================================================
-; STRUCTURES
-;===========================================================================
-
-; This STRUCT assumes a 4-byte alignment
-
-DEFLATE_STATE  STRUCT
-ds_strm                        dd ?
-ds_status              dd ?
-ds_pending_buf         dd ?
-ds_pending_buf_size    dd ?
-ds_pending_out         dd ?
-ds_pending             dd ?
-ds_wrap                        dd ?
-ds_data_type           db ?
-ds_method              db ?
-                       db ?    ; padding
-                       db ?    ; padding
-ds_last_flush          dd ?
-ds_w_size              dd ?    ; used
-ds_w_bits              dd ?
-ds_w_mask              dd ?    ; used
-ds_window              dd ?    ; used
-ds_window_size         dd ?
-ds_prev                        dd ?    ; used
-ds_head                        dd ?
-ds_ins_h               dd ?
-ds_hash_size           dd ?
-ds_hash_bits           dd ?
-ds_hash_mask           dd ?
-ds_hash_shift          dd ?
-ds_block_start         dd ?
-ds_match_length                dd ?    ; used
-ds_prev_match          dd ?    ; used
-ds_match_available     dd ?
-ds_strstart            dd ?    ; used
-ds_match_start         dd ?    ; used
-ds_lookahead           dd ?    ; used
-ds_prev_length         dd ?    ; used
-ds_max_chain_length    dd ?    ; used
-ds_max_laxy_match      dd ?
-ds_level               dd ?
-ds_strategy            dd ?
-ds_good_match          dd ?    ; used
-ds_nice_match          dd ?    ; used
-
-; Don't need anymore of the struct for match
-DEFLATE_STATE  ENDS
-
-;===========================================================================
-; CODE
-;===========================================================================
-_TEXT  SEGMENT
-
-;---------------------------------------------------------------------------
-; match_init
-;---------------------------------------------------------------------------
-       ALIGN   4
-PUBLIC _match_init
-_match_init    PROC
-       ; no initialization needed
-       ret
-_match_init    ENDP
-
-;---------------------------------------------------------------------------
-; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
-;---------------------------------------------------------------------------
-       ALIGN   4
-
-PUBLIC _longest_match
-_longest_match PROC
-
-; Since this code uses EBP for a scratch register, the stack frame must
-; be manually constructed and referenced relative to the ESP register.
-
-; Stack image
-; Variables
-chainlenwmask  =  0    ; high word: current chain len
-                       ; low word: s->wmask
-window         =  4    ; local copy of s->window
-windowbestlen  =  8    ; s->window + bestlen
-scanend                = 12    ; last two bytes of string
-scanstart      = 16    ; first two bytes of string
-scanalign      = 20    ; dword-misalignment of string
-nicematch      = 24    ; a good enough match size
-bestlen                = 28    ; size of best match so far
-scan           = 32    ; ptr to string wanting match
-varsize                = 36    ; number of bytes (also offset to last saved register)
-
-; Saved Registers (actually pushed into place)
-ebx_save       = 36
-edi_save       = 40
-esi_save       = 44
-ebp_save       = 48
-
-; Parameters
-retaddr                = 52
-deflatestate   = 56
-curmatch       = 60
-
-; Save registers that the compiler may be using
-       push    ebp
-       push    edi
-       push    esi
-       push    ebx
-
-; Allocate local variable space
-       sub     esp,varsize
-
-; Retrieve the function arguments. ecx will hold cur_match
-; throughout the entire function. edx will hold the pointer to the
-; deflate_state structure during the function's setup (before
-; entering the main loop).
-
-       mov     edx, [esp+deflatestate]
-ASSUME edx:PTR DEFLATE_STATE
-
-       mov     ecx, [esp+curmatch]
-
-; uInt wmask = s->w_mask;
-; unsigned chain_length = s->max_chain_length;
-; if (s->prev_length >= s->good_match) {
-;     chain_length >>= 2;
-; }
-
-       mov     eax, [edx].ds_prev_length
-       mov     ebx, [edx].ds_good_match
-       cmp     eax, ebx
-       mov     eax, [edx].ds_w_mask
-       mov     ebx, [edx].ds_max_chain_length
-       jl      SHORT LastMatchGood
-       shr     ebx, 2
-LastMatchGood:
-
-; chainlen is decremented once beforehand so that the function can
-; use the sign flag instead of the zero flag for the exit test.
-; It is then shifted into the high word, to make room for the wmask
-; value, which it will always accompany.
-
-       dec     ebx
-       shl     ebx, 16
-       or      ebx, eax
-       mov     [esp+chainlenwmask], ebx
-
-; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-
-       mov     eax, [edx].ds_nice_match
-       mov     ebx, [edx].ds_lookahead
-       cmp     ebx, eax
-       jl      SHORT LookaheadLess
-       mov     ebx, eax
-LookaheadLess:
-       mov     [esp+nicematch], ebx
-
-;/* register Bytef *scan = s->window + s->strstart;                     */
-
-       mov     esi, [edx].ds_window
-       mov     [esp+window], esi
-       mov     ebp, [edx].ds_strstart
-       lea     edi, [esi+ebp]
-       mov     [esp+scan],edi
-
-;/* Determine how many bytes the scan ptr is off from being             */
-;/* dword-aligned.                                                      */
-
-       mov     eax, edi
-       neg     eax
-       and     eax, 3
-       mov     [esp+scanalign], eax
-
-;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */
-;/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */
-
-       mov     eax, [edx].ds_w_size
-       sub     eax, MIN_LOOKAHEAD
-       sub     ebp, eax
-       jg      SHORT LimitPositive
-       xor     ebp, ebp
-LimitPositive:
-
-;/* int best_len = s->prev_length;                                      */
-
-       mov     eax, [edx].ds_prev_length
-       mov     [esp+bestlen], eax
-
-;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
-
-       add     esi, eax
-       mov     [esp+windowbestlen], esi
-
-;/* register ush scan_start = *(ushf*)scan;                             */
-;/* register ush scan_end   = *(ushf*)(scan+best_len-1);                */
-;/* Posf *prev = s->prev;                                               */
-
-       movzx   ebx, WORD PTR[edi]
-       mov     [esp+scanstart], ebx
-       movzx   ebx, WORD PTR[eax+edi-1]
-       mov     [esp+scanend], ebx
-       mov     edi, [edx].ds_prev
-
-;/* Jump into the main loop.                                            */
-
-       mov     edx, [esp+chainlenwmask]
-       jmp     SHORT LoopEntry
-
-;/* do {
-; *     match = s->window + cur_match;
-; *     if (*(ushf*)(match+best_len-1) != scan_end ||
-; *         *(ushf*)match != scan_start) continue;
-; *     [...]
-; * } while ((cur_match = prev[cur_match & wmask]) > limit
-; *          && --chain_length != 0);
-; *
-; * Here is the inner loop of the function. The function will spend the
-; * majority of its time in this loop, and majority of that time will
-; * be spent in the first ten instructions.
-; *
-; * Within this loop:
-; * %ebx = scanend
-; * %ecx = curmatch
-; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
-; * %esi = windowbestlen - i.e., (window + bestlen)
-; * %edi = prev
-; * %ebp = limit
-; */
-
-       ALIGN   4
-LookupLoop:
-       and     ecx, edx
-       movzx   ecx, WORD PTR[edi+ecx*2]
-       cmp     ecx, ebp
-       jbe     LeaveNow
-       sub     edx, 000010000H
-       js      LeaveNow
-
-LoopEntry:
-       movzx   eax, WORD PTR[esi+ecx-1]
-       cmp     eax, ebx
-       jnz     SHORT LookupLoop
-
-       mov     eax, [esp+window]
-       movzx   eax, WORD PTR[eax+ecx]
-       cmp     eax, [esp+scanstart]
-       jnz     SHORT LookupLoop
-
-;/* Store the current value of chainlen.                                */
-
-       mov     [esp+chainlenwmask], edx
-
-;/* Point %edi to the string under scrutiny, and %esi to the string we  */
-;/* are hoping to match it up with. In actuality, %esi and %edi are     */
-;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is     */
-;/* initialized to -(MAX_MATCH_8 - scanalign).                          */
-
-       mov     esi, [esp+window]
-       mov     edi, [esp+scan]
-       add     esi, ecx
-       mov     eax, [esp+scanalign]
-       mov     edx, -MAX_MATCH_8
-       lea     edi, [edi+eax+MAX_MATCH_8]
-       lea     esi, [esi+eax+MAX_MATCH_8]
-
-;/* Test the strings for equality, 8 bytes at a time. At the end,
-; * adjust %edx so that it is offset to the exact byte that mismatched.
-; *
-; * We already know at this point that the first three bytes of the
-; * strings match each other, and they can be safely passed over before
-; * starting the compare loop. So what this code does is skip over 0-3
-; * bytes, as much as necessary in order to dword-align the %edi
-; * pointer. (%esi will still be misaligned three times out of four.)
-; *
-; * It should be confessed that this loop usually does not represent
-; * much of the total running time. Replacing it with a more
-; * straightforward "rep cmpsb" would not drastically degrade
-; * performance.
-; */
-
-LoopCmps:
-       mov     eax, DWORD PTR[esi+edx]
-       xor     eax, DWORD PTR[edi+edx]
-       jnz     SHORT LeaveLoopCmps
-
-       mov     eax, DWORD PTR[esi+edx+4]
-       xor     eax, DWORD PTR[edi+edx+4]
-       jnz     SHORT LeaveLoopCmps4
-
-       add     edx, 8
-       jnz     SHORT LoopCmps
-       jmp     LenMaximum
-       ALIGN   4
-
-LeaveLoopCmps4:
-       add     edx, 4
-
-LeaveLoopCmps:
-       test    eax, 00000FFFFH
-       jnz     SHORT LenLower
-
-       add     edx, 2
-       shr     eax, 16
-
-LenLower:
-       sub     al, 1
-       adc     edx, 0
-
-;/* Calculate the length of the match. If it is longer than MAX_MATCH,  */
-;/* then automatically accept it as the best possible match and leave.  */
-
-       lea     eax, [edi+edx]
-       mov     edi, [esp+scan]
-       sub     eax, edi
-       cmp     eax, MAX_MATCH
-       jge     SHORT LenMaximum
-
-;/* If the length of the match is not longer than the best match we     */
-;/* have so far, then forget it and return to the lookup loop.          */
-
-       mov     edx, [esp+deflatestate]
-       mov     ebx, [esp+bestlen]
-       cmp     eax, ebx
-       jg      SHORT LongerMatch
-       mov     esi, [esp+windowbestlen]
-       mov     edi, [edx].ds_prev
-       mov     ebx, [esp+scanend]
-       mov     edx, [esp+chainlenwmask]
-       jmp     LookupLoop
-       ALIGN   4
-
-;/*         s->match_start = cur_match;                                 */
-;/*         best_len = len;                                             */
-;/*         if (len >= nice_match) break;                               */
-;/*         scan_end = *(ushf*)(scan+best_len-1);                       */
-
-LongerMatch:
-       mov     ebx, [esp+nicematch]
-       mov     [esp+bestlen], eax
-       mov     [edx].ds_match_start, ecx
-       cmp     eax, ebx
-       jge     SHORT LeaveNow
-       mov     esi, [esp+window]
-       add     esi, eax
-       mov     [esp+windowbestlen], esi
-       movzx   ebx, WORD PTR[edi+eax-1]
-       mov     edi, [edx].ds_prev
-       mov     [esp+scanend], ebx
-       mov     edx, [esp+chainlenwmask]
-       jmp     LookupLoop
-       ALIGN   4
-
-;/* Accept the current string, with the maximum possible length.        */
-
-LenMaximum:
-       mov     edx, [esp+deflatestate]
-       mov     DWORD PTR[esp+bestlen], MAX_MATCH
-       mov     [edx].ds_match_start, ecx
-
-;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;          */
-;/* return s->lookahead;                                                */
-
-LeaveNow:
-       mov     edx, [esp+deflatestate]
-       mov     ebx, [esp+bestlen]
-       mov     eax, [edx].ds_lookahead
-       cmp     ebx, eax
-       jg      SHORT LookaheadRet
-       mov     eax, ebx
-LookaheadRet:
-
-; Restore the stack and return from whence we came.
-
-       add     esp, varsize
-       pop     ebx
-       pop     esi
-       pop     edi
-       pop     ebp
-       ret
-
-_longest_match ENDP
-
-_TEXT  ENDS
-END
+\r
+; match.asm -- Pentium-Pro optimized version of longest_match()\r
+;\r
+; Updated for zlib 1.1.3 and converted to MASM 6.1x\r
+; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com>\r
+;                    and Chuck Walbourn <chuckw@kinesoft.com>\r
+; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro>\r
+;\r
+; This is free software; you can redistribute it and/or modify it\r
+; under the terms of the GNU General Public License.\r
+\r
+; Based on match.S\r
+; Written for zlib 1.1.2\r
+; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>\r
+;\r
+; Modified by Gilles Vollant (2005) for add gzhead and gzindex\r
+\r
+       .686P\r
+       .MODEL  FLAT\r
+\r
+;===========================================================================\r
+; EQUATES\r
+;===========================================================================\r
+\r
+MAX_MATCH      EQU 258\r
+MIN_MATCH      EQU 3\r
+MIN_LOOKAHEAD  EQU (MAX_MATCH + MIN_MATCH + 1)\r
+MAX_MATCH_8    EQU ((MAX_MATCH + 7) AND (NOT 7))\r
+\r
+;===========================================================================\r
+; STRUCTURES\r
+;===========================================================================\r
+\r
+; This STRUCT assumes a 4-byte alignment\r
+\r
+DEFLATE_STATE  STRUCT\r
+ds_strm                        dd ?\r
+ds_status              dd ?\r
+ds_pending_buf         dd ?\r
+ds_pending_buf_size    dd ?\r
+ds_pending_out         dd ?\r
+ds_pending             dd ?\r
+ds_wrap                        dd ?\r
+; gzhead and gzindex are added in zlib 1.2.2.2 (see deflate.h)\r
+ds_gzhead               dd ?\r
+ds_gzindex              dd ?\r
+ds_data_type           db ?\r
+ds_method              db ?\r
+                       db ?    ; padding\r
+                       db ?    ; padding\r
+ds_last_flush          dd ?\r
+ds_w_size              dd ?    ; used\r
+ds_w_bits              dd ?\r
+ds_w_mask              dd ?    ; used\r
+ds_window              dd ?    ; used\r
+ds_window_size         dd ?\r
+ds_prev                        dd ?    ; used\r
+ds_head                        dd ?\r
+ds_ins_h               dd ?\r
+ds_hash_size           dd ?\r
+ds_hash_bits           dd ?\r
+ds_hash_mask           dd ?\r
+ds_hash_shift          dd ?\r
+ds_block_start         dd ?\r
+ds_match_length                dd ?    ; used\r
+ds_prev_match          dd ?    ; used\r
+ds_match_available     dd ?\r
+ds_strstart            dd ?    ; used\r
+ds_match_start         dd ?    ; used\r
+ds_lookahead           dd ?    ; used\r
+ds_prev_length         dd ?    ; used\r
+ds_max_chain_length    dd ?    ; used\r
+ds_max_laxy_match      dd ?\r
+ds_level               dd ?\r
+ds_strategy            dd ?\r
+ds_good_match          dd ?    ; used\r
+ds_nice_match          dd ?    ; used\r
+\r
+; Don't need anymore of the struct for match\r
+DEFLATE_STATE  ENDS\r
+\r
+;===========================================================================\r
+; CODE\r
+;===========================================================================\r
+_TEXT  SEGMENT\r
+\r
+;---------------------------------------------------------------------------\r
+; match_init\r
+;---------------------------------------------------------------------------\r
+       ALIGN   4\r
+PUBLIC _match_init\r
+_match_init    PROC\r
+       ; no initialization needed\r
+       ret\r
+_match_init    ENDP\r
+\r
+;---------------------------------------------------------------------------\r
+; uInt longest_match(deflate_state *deflatestate, IPos curmatch)\r
+;---------------------------------------------------------------------------\r
+       ALIGN   4\r
+\r
+PUBLIC _longest_match\r
+_longest_match PROC\r
+\r
+; Since this code uses EBP for a scratch register, the stack frame must\r
+; be manually constructed and referenced relative to the ESP register.\r
+\r
+; Stack image\r
+; Variables\r
+chainlenwmask  =  0    ; high word: current chain len\r
+                       ; low word: s->wmask\r
+window         =  4    ; local copy of s->window\r
+windowbestlen  =  8    ; s->window + bestlen\r
+scanend                = 12    ; last two bytes of string\r
+scanstart      = 16    ; first two bytes of string\r
+scanalign      = 20    ; dword-misalignment of string\r
+nicematch      = 24    ; a good enough match size\r
+bestlen                = 28    ; size of best match so far\r
+scan           = 32    ; ptr to string wanting match\r
+varsize                = 36    ; number of bytes (also offset to last saved register)\r
+\r
+; Saved Registers (actually pushed into place)\r
+ebx_save       = 36\r
+edi_save       = 40\r
+esi_save       = 44\r
+ebp_save       = 48\r
+\r
+; Parameters\r
+retaddr                = 52\r
+deflatestate   = 56\r
+curmatch       = 60\r
+\r
+; Save registers that the compiler may be using\r
+       push    ebp\r
+       push    edi\r
+       push    esi\r
+       push    ebx\r
+\r
+; Allocate local variable space\r
+       sub     esp,varsize\r
+\r
+; Retrieve the function arguments. ecx will hold cur_match\r
+; throughout the entire function. edx will hold the pointer to the\r
+; deflate_state structure during the function's setup (before\r
+; entering the main loop).\r
+\r
+       mov     edx, [esp+deflatestate]\r
+ASSUME edx:PTR DEFLATE_STATE\r
+\r
+       mov     ecx, [esp+curmatch]\r
+\r
+; uInt wmask = s->w_mask;\r
+; unsigned chain_length = s->max_chain_length;\r
+; if (s->prev_length >= s->good_match) {\r
+;     chain_length >>= 2;\r
+; }\r
+\r
+       mov     eax, [edx].ds_prev_length\r
+       mov     ebx, [edx].ds_good_match\r
+       cmp     eax, ebx\r
+       mov     eax, [edx].ds_w_mask\r
+       mov     ebx, [edx].ds_max_chain_length\r
+       jl      SHORT LastMatchGood\r
+       shr     ebx, 2\r
+LastMatchGood:\r
+\r
+; chainlen is decremented once beforehand so that the function can\r
+; use the sign flag instead of the zero flag for the exit test.\r
+; It is then shifted into the high word, to make room for the wmask\r
+; value, which it will always accompany.\r
+\r
+       dec     ebx\r
+       shl     ebx, 16\r
+       or      ebx, eax\r
+       mov     [esp+chainlenwmask], ebx\r
+\r
+; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;\r
+\r
+       mov     eax, [edx].ds_nice_match\r
+       mov     ebx, [edx].ds_lookahead\r
+       cmp     ebx, eax\r
+       jl      SHORT LookaheadLess\r
+       mov     ebx, eax\r
+LookaheadLess:\r
+       mov     [esp+nicematch], ebx\r
+\r
+;/* register Bytef *scan = s->window + s->strstart;                     */\r
+\r
+       mov     esi, [edx].ds_window\r
+       mov     [esp+window], esi\r
+       mov     ebp, [edx].ds_strstart\r
+       lea     edi, [esi+ebp]\r
+       mov     [esp+scan],edi\r
+\r
+;/* Determine how many bytes the scan ptr is off from being             */\r
+;/* dword-aligned.                                                      */\r
+\r
+       mov     eax, edi\r
+       neg     eax\r
+       and     eax, 3\r
+       mov     [esp+scanalign], eax\r
+\r
+;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */\r
+;/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */\r
+\r
+       mov     eax, [edx].ds_w_size\r
+       sub     eax, MIN_LOOKAHEAD\r
+       sub     ebp, eax\r
+       jg      SHORT LimitPositive\r
+       xor     ebp, ebp\r
+LimitPositive:\r
+\r
+;/* int best_len = s->prev_length;                                      */\r
+\r
+       mov     eax, [edx].ds_prev_length\r
+       mov     [esp+bestlen], eax\r
+\r
+;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */\r
+\r
+       add     esi, eax\r
+       mov     [esp+windowbestlen], esi\r
+\r
+;/* register ush scan_start = *(ushf*)scan;                             */\r
+;/* register ush scan_end   = *(ushf*)(scan+best_len-1);                */\r
+;/* Posf *prev = s->prev;                                               */\r
+\r
+       movzx   ebx, WORD PTR[edi]\r
+       mov     [esp+scanstart], ebx\r
+       movzx   ebx, WORD PTR[eax+edi-1]\r
+       mov     [esp+scanend], ebx\r
+       mov     edi, [edx].ds_prev\r
+\r
+;/* Jump into the main loop.                                            */\r
+\r
+       mov     edx, [esp+chainlenwmask]\r
+       jmp     SHORT LoopEntry\r
+\r
+;/* do {\r
+; *     match = s->window + cur_match;\r
+; *     if (*(ushf*)(match+best_len-1) != scan_end ||\r
+; *         *(ushf*)match != scan_start) continue;\r
+; *     [...]\r
+; * } while ((cur_match = prev[cur_match & wmask]) > limit\r
+; *          && --chain_length != 0);\r
+; *\r
+; * Here is the inner loop of the function. The function will spend the\r
+; * majority of its time in this loop, and majority of that time will\r
+; * be spent in the first ten instructions.\r
+; *\r
+; * Within this loop:\r
+; * %ebx = scanend\r
+; * %ecx = curmatch\r
+; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)\r
+; * %esi = windowbestlen - i.e., (window + bestlen)\r
+; * %edi = prev\r
+; * %ebp = limit\r
+; */\r
+\r
+       ALIGN   4\r
+LookupLoop:\r
+       and     ecx, edx\r
+       movzx   ecx, WORD PTR[edi+ecx*2]\r
+       cmp     ecx, ebp\r
+       jbe     LeaveNow\r
+       sub     edx, 000010000H\r
+       js      LeaveNow\r
+\r
+LoopEntry:\r
+       movzx   eax, WORD PTR[esi+ecx-1]\r
+       cmp     eax, ebx\r
+       jnz     SHORT LookupLoop\r
+\r
+       mov     eax, [esp+window]\r
+       movzx   eax, WORD PTR[eax+ecx]\r
+       cmp     eax, [esp+scanstart]\r
+       jnz     SHORT LookupLoop\r
+\r
+;/* Store the current value of chainlen.                                */\r
+\r
+       mov     [esp+chainlenwmask], edx\r
+\r
+;/* Point %edi to the string under scrutiny, and %esi to the string we  */\r
+;/* are hoping to match it up with. In actuality, %esi and %edi are     */\r
+;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is     */\r
+;/* initialized to -(MAX_MATCH_8 - scanalign).                          */\r
+\r
+       mov     esi, [esp+window]\r
+       mov     edi, [esp+scan]\r
+       add     esi, ecx\r
+       mov     eax, [esp+scanalign]\r
+       mov     edx, -MAX_MATCH_8\r
+       lea     edi, [edi+eax+MAX_MATCH_8]\r
+       lea     esi, [esi+eax+MAX_MATCH_8]\r
+\r
+;/* Test the strings for equality, 8 bytes at a time. At the end,\r
+; * adjust %edx so that it is offset to the exact byte that mismatched.\r
+; *\r
+; * We already know at this point that the first three bytes of the\r
+; * strings match each other, and they can be safely passed over before\r
+; * starting the compare loop. So what this code does is skip over 0-3\r
+; * bytes, as much as necessary in order to dword-align the %edi\r
+; * pointer. (%esi will still be misaligned three times out of four.)\r
+; *\r
+; * It should be confessed that this loop usually does not represent\r
+; * much of the total running time. Replacing it with a more\r
+; * straightforward "rep cmpsb" would not drastically degrade\r
+; * performance.\r
+; */\r
+\r
+LoopCmps:\r
+       mov     eax, DWORD PTR[esi+edx]\r
+       xor     eax, DWORD PTR[edi+edx]\r
+       jnz     SHORT LeaveLoopCmps\r
+\r
+       mov     eax, DWORD PTR[esi+edx+4]\r
+       xor     eax, DWORD PTR[edi+edx+4]\r
+       jnz     SHORT LeaveLoopCmps4\r
+\r
+       add     edx, 8\r
+       jnz     SHORT LoopCmps\r
+       jmp     LenMaximum\r
+       ALIGN   4\r
+\r
+LeaveLoopCmps4:\r
+       add     edx, 4\r
+\r
+LeaveLoopCmps:\r
+       test    eax, 00000FFFFH\r
+       jnz     SHORT LenLower\r
+\r
+       add     edx, 2\r
+       shr     eax, 16\r
+\r
+LenLower:\r
+       sub     al, 1\r
+       adc     edx, 0\r
+\r
+;/* Calculate the length of the match. If it is longer than MAX_MATCH,  */\r
+;/* then automatically accept it as the best possible match and leave.  */\r
+\r
+       lea     eax, [edi+edx]\r
+       mov     edi, [esp+scan]\r
+       sub     eax, edi\r
+       cmp     eax, MAX_MATCH\r
+       jge     SHORT LenMaximum\r
+\r
+;/* If the length of the match is not longer than the best match we     */\r
+;/* have so far, then forget it and return to the lookup loop.          */\r
+\r
+       mov     edx, [esp+deflatestate]\r
+       mov     ebx, [esp+bestlen]\r
+       cmp     eax, ebx\r
+       jg      SHORT LongerMatch\r
+       mov     esi, [esp+windowbestlen]\r
+       mov     edi, [edx].ds_prev\r
+       mov     ebx, [esp+scanend]\r
+       mov     edx, [esp+chainlenwmask]\r
+       jmp     LookupLoop\r
+       ALIGN   4\r
+\r
+;/*         s->match_start = cur_match;                                 */\r
+;/*         best_len = len;                                             */\r
+;/*         if (len >= nice_match) break;                               */\r
+;/*         scan_end = *(ushf*)(scan+best_len-1);                       */\r
+\r
+LongerMatch:\r
+       mov     ebx, [esp+nicematch]\r
+       mov     [esp+bestlen], eax\r
+       mov     [edx].ds_match_start, ecx\r
+       cmp     eax, ebx\r
+       jge     SHORT LeaveNow\r
+       mov     esi, [esp+window]\r
+       add     esi, eax\r
+       mov     [esp+windowbestlen], esi\r
+       movzx   ebx, WORD PTR[edi+eax-1]\r
+       mov     edi, [edx].ds_prev\r
+       mov     [esp+scanend], ebx\r
+       mov     edx, [esp+chainlenwmask]\r
+       jmp     LookupLoop\r
+       ALIGN   4\r
+\r
+;/* Accept the current string, with the maximum possible length.        */\r
+\r
+LenMaximum:\r
+       mov     edx, [esp+deflatestate]\r
+       mov     DWORD PTR[esp+bestlen], MAX_MATCH\r
+       mov     [edx].ds_match_start, ecx\r
+\r
+;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;          */\r
+;/* return s->lookahead;                                                */\r
+\r
+LeaveNow:\r
+       mov     edx, [esp+deflatestate]\r
+       mov     ebx, [esp+bestlen]\r
+       mov     eax, [edx].ds_lookahead\r
+       cmp     ebx, eax\r
+       jg      SHORT LookaheadRet\r
+       mov     eax, ebx\r
+LookaheadRet:\r
+\r
+; Restore the stack and return from whence we came.\r
+\r
+       add     esp, varsize\r
+       pop     ebx\r
+       pop     esi\r
+       pop     edi\r
+       pop     ebp\r
+       ret\r
+\r
+_longest_match ENDP\r
+\r
+_TEXT  ENDS\r
+END\r
diff --git a/zlib/contrib/masmx64/bld_ml64.bat b/zlib/contrib/masmx64/bld_ml64.bat
new file mode 100644 (file)
index 0000000..8f9343d
--- /dev/null
@@ -0,0 +1,2 @@
+ml64.exe /Flinffasx64 /c /Zi inffasx64.asm\r
+ml64.exe /Flgvmat64   /c /Zi gvmat64.asm\r
diff --git a/zlib/contrib/masmx64/gvmat64.asm b/zlib/contrib/masmx64/gvmat64.asm
new file mode 100644 (file)
index 0000000..cee2145
--- /dev/null
@@ -0,0 +1,464 @@
+;uInt longest_match_x64(\r
+;    deflate_state *s,\r
+;    IPos cur_match);                             /* current match */\r
+\r
+; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86\r
+; Copyright (C) 1995-2005 Jean-loup Gailly, Brian Raiter and Gilles Vollant.\r
+; File written by Gilles Vollant, by modifiying the longest_match\r
+;  from Jean-loup Gailly in deflate.c\r
+;  and modifying asm686 with masm, optimised assembly code from Brian Raiter,\r
+;      written 1998\r
+;         http://www.zlib.net\r
+;         http://www.winimage.com/zLibDll\r
+;         http://www.muppetlabs.com/~breadbox/software/assembly.html\r
+;\r
+; to compile this file, I use option\r
+;   ml64.exe /Flgvmat64 /c /Zi gvmat64.asm\r
+;   with Microsoft Macro Assembler (x64) for AMD64\r
+;\r
+;   ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK\r
+;\r
+;   (you can get Windows 2003 server DDK with ml64 and cl for AMD64 from\r
+;      http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)\r
+;\r
+; Be carrefull to adapt zlib1222add below to your version of zLib\r
+\r
+\r
+;uInt longest_match(s, cur_match)\r
+;    deflate_state *s;\r
+;    IPos cur_match;                             /* current match */\r
+.code\r
+longest_match PROC\r
+\r
+\r
+;LocalVarsSize   equ 88\r
+ LocalVarsSize   equ 72\r
+\r
+; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12\r
+; free register :  r14,r15\r
+; register can be saved : rsp\r
+\r
+ chainlenwmask   equ  rsp + 8 - LocalVarsSize    ; high word: current chain len\r
+                                                 ; low word: s->wmask\r
+;window          equ  rsp + xx - LocalVarsSize   ; local copy of s->window ; stored in r10\r
+;windowbestlen   equ  rsp + xx - LocalVarsSize   ; s->window + bestlen , use r10+r11\r
+;scanstart       equ  rsp + xx - LocalVarsSize   ; first two bytes of string ; stored in r12w\r
+;scanend         equ  rsp + xx - LocalVarsSize   ; last two bytes of string use ebx\r
+;scanalign       equ  rsp + xx - LocalVarsSize   ; dword-misalignment of string r13\r
+;bestlen         equ  rsp + xx - LocalVarsSize   ; size of best match so far -> r11d\r
+;scan            equ  rsp + xx - LocalVarsSize   ; ptr to string wanting match -> r9\r
+ nicematch       equ  rsp + 16 - LocalVarsSize   ; a good enough match size -> r14\r
+\r
+save_rdi        equ  rsp + 24 - LocalVarsSize\r
+save_rsi        equ  rsp + 32 - LocalVarsSize\r
+save_rbx        equ  rsp + 40 - LocalVarsSize\r
+save_rbp        equ  rsp + 48 - LocalVarsSize\r
+save_r12        equ  rsp + 56 - LocalVarsSize\r
+save_r13        equ  rsp + 64 - LocalVarsSize\r
+;save_r14        equ  rsp + 72 - LocalVarsSize\r
+;save_r15        equ  rsp + 80 - LocalVarsSize\r
+\r
+\r
+\r
+;  all the +4 offsets are due to the addition of pending_buf_size (in zlib\r
+;  in the deflate_state structure since the asm code was first written\r
+;  (if you compile with zlib 1.0.4 or older, remove the +4).\r
+;  Note : these value are good with a 8 bytes boundary pack structure\r
+\r
+\r
+    MAX_MATCH           equ     258\r
+    MIN_MATCH           equ     3\r
+    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)\r
+\r
+\r
+;;; Offsets for fields in the deflate_state structure. These numbers\r
+;;; are calculated from the definition of deflate_state, with the\r
+;;; assumption that the compiler will dword-align the fields. (Thus,\r
+;;; changing the definition of deflate_state could easily cause this\r
+;;; program to crash horribly, without so much as a warning at\r
+;;; compile time. Sigh.)\r
+\r
+;  all the +zlib1222add offsets are due to the addition of fields\r
+;  in zlib in the deflate_state structure since the asm code was first written\r
+;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").\r
+;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").\r
+;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").\r
+\r
+zlib1222add     equ 8\r
+\r
+dsWSize         equ 56+zlib1222add+(zlib1222add/2)\r
+dsWMask         equ 64+zlib1222add+(zlib1222add/2)\r
+dsWindow        equ 72+zlib1222add\r
+dsPrev          equ 88+zlib1222add\r
+dsMatchLen      equ 128+zlib1222add\r
+dsPrevMatch     equ 132+zlib1222add\r
+dsStrStart      equ 140+zlib1222add\r
+dsMatchStart    equ 144+zlib1222add\r
+dsLookahead     equ 148+zlib1222add\r
+dsPrevLen       equ 152+zlib1222add\r
+dsMaxChainLen   equ 156+zlib1222add\r
+dsGoodMatch     equ 172+zlib1222add\r
+dsNiceMatch     equ 176+zlib1222add\r
+\r
+\r
+; parameter 1 in r8(deflate state s), param 2 in rdx (cur match)\r
+\r
+; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and\r
+; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp\r
+;\r
+; All registers must be preserved across the call, except for\r
+;   rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch.\r
+\r
+\r
+\r
+;;; Save registers that the compiler may be using, and adjust esp to\r
+;;; make room for our stack frame.\r
+\r
+\r
+;;; Retrieve the function arguments. r8d will hold cur_match\r
+;;; throughout the entire function. edx will hold the pointer to the\r
+;;; deflate_state structure during the function's setup (before\r
+;;; entering the main loop.\r
+\r
+; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match)\r
+\r
+; this clear high 32 bits of r8, which can be garbage in both r8 and rdx\r
+\r
+\r
+        mov [save_rdi],rdi\r
+        mov [save_rsi],rsi\r
+        mov [save_rbx],rbx\r
+        mov [save_rbp],rbp\r
+        mov r8d,edx\r
+        mov [save_r12],r12\r
+        mov [save_r13],r13\r
+;        mov [save_r14],r14\r
+;        mov [save_r15],r15\r
+\r
+\r
+;;; uInt wmask = s->w_mask;\r
+;;; unsigned chain_length = s->max_chain_length;\r
+;;; if (s->prev_length >= s->good_match) {\r
+;;;     chain_length >>= 2;\r
+;;; }\r
+\r
+        mov edi, [rcx + dsPrevLen]\r
+        mov esi, [rcx + dsGoodMatch]\r
+        mov eax, [rcx + dsWMask]\r
+        mov ebx, [rcx + dsMaxChainLen]\r
+        cmp edi, esi\r
+        jl  LastMatchGood\r
+        shr ebx, 2\r
+LastMatchGood:\r
+\r
+;;; chainlen is decremented once beforehand so that the function can\r
+;;; use the sign flag instead of the zero flag for the exit test.\r
+;;; It is then shifted into the high word, to make room for the wmask\r
+;;; value, which it will always accompany.\r
+\r
+        dec ebx\r
+        shl ebx, 16\r
+        or  ebx, eax\r
+        mov [chainlenwmask], ebx\r
+\r
+;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;\r
+\r
+        mov eax, [rcx + dsNiceMatch]\r
+        mov r10d, [rcx + dsLookahead]\r
+        cmp r10d, eax\r
+        cmovnl r10d, eax\r
+        mov [nicematch],r10d\r
+LookaheadLess:\r
+\r
+;;; register Bytef *scan = s->window + s->strstart;\r
+\r
+        mov r10, [rcx + dsWindow]\r
+        mov ebp, [rcx + dsStrStart]\r
+        lea r13, [r10 + rbp]\r
+\r
+;;; Determine how many bytes the scan ptr is off from being\r
+;;; dword-aligned.\r
+\r
+         mov r9,r13\r
+         neg r13\r
+         and r13,3\r
+\r
+;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?\r
+;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;\r
+\r
+        mov eax, [rcx + dsWSize]\r
+        sub eax, MIN_LOOKAHEAD\r
+        xor edi,edi\r
+        sub ebp, eax\r
+\r
+        mov r11d, [rcx + dsPrevLen]\r
+\r
+        cmovng ebp,edi\r
+\r
+;;; int best_len = s->prev_length;\r
+\r
+\r
+;;; Store the sum of s->window + best_len in esi locally, and in esi.\r
+\r
+       lea  rsi,[r10+r11]\r
+\r
+;;; register ush scan_start = *(ushf*)scan;\r
+;;; register ush scan_end   = *(ushf*)(scan+best_len-1);\r
+;;; Posf *prev = s->prev;\r
+\r
+        movzx r12d,word ptr [r9]\r
+        movzx   ebx, word ptr [r9 + r11 - 1]\r
+        mov rdi, [rcx + dsPrev]\r
+\r
+;;; Jump into the main loop.\r
+\r
+        mov edx, [chainlenwmask]\r
+\r
+        cmp bx,word ptr [rsi + r8 - 1]\r
+        jz  LookupLoopIsZero\r
+\r
+LookupLoop1:\r
+        and r8d, edx\r
+\r
+        movzx   r8d, word ptr [rdi + r8*2]\r
+        cmp r8d, ebp\r
+        jbe LeaveNow\r
+        sub edx, 00010000h\r
+        js  LeaveNow\r
+\r
+LoopEntry1:\r
+        cmp bx,word ptr [rsi + r8 - 1]\r
+        jz  LookupLoopIsZero\r
+\r
+LookupLoop2:\r
+        and r8d, edx\r
+\r
+        movzx   r8d, word ptr [rdi + r8*2]\r
+        cmp r8d, ebp\r
+        jbe LeaveNow\r
+        sub edx, 00010000h\r
+        js  LeaveNow\r
+\r
+LoopEntry2:\r
+        cmp bx,word ptr [rsi + r8 - 1]\r
+        jz  LookupLoopIsZero\r
+\r
+LookupLoop4:\r
+        and r8d, edx\r
+\r
+        movzx   r8d, word ptr [rdi + r8*2]\r
+        cmp r8d, ebp\r
+        jbe LeaveNow\r
+        sub edx, 00010000h\r
+        js  LeaveNow\r
+\r
+LoopEntry4:\r
+\r
+        cmp bx,word ptr [rsi + r8 - 1]\r
+        jnz LookupLoop1\r
+        jmp LookupLoopIsZero\r
+\r
+\r
+;;; do {\r
+;;;     match = s->window + cur_match;\r
+;;;     if (*(ushf*)(match+best_len-1) != scan_end ||\r
+;;;         *(ushf*)match != scan_start) continue;\r
+;;;     [...]\r
+;;; } while ((cur_match = prev[cur_match & wmask]) > limit\r
+;;;          && --chain_length != 0);\r
+;;;\r
+;;; Here is the inner loop of the function. The function will spend the\r
+;;; majority of its time in this loop, and majority of that time will\r
+;;; be spent in the first ten instructions.\r
+;;;\r
+;;; Within this loop:\r
+;;; ebx = scanend\r
+;;; r8d = curmatch\r
+;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)\r
+;;; esi = windowbestlen - i.e., (window + bestlen)\r
+;;; edi = prev\r
+;;; ebp = limit\r
+\r
+LookupLoop:\r
+        and r8d, edx\r
+\r
+        movzx   r8d, word ptr [rdi + r8*2]\r
+        cmp r8d, ebp\r
+        jbe LeaveNow\r
+        sub edx, 00010000h\r
+        js  LeaveNow\r
+\r
+LoopEntry:\r
+\r
+        cmp bx,word ptr [rsi + r8 - 1]\r
+        jnz LookupLoop1\r
+LookupLoopIsZero:\r
+        cmp     r12w, word ptr [r10 + r8]\r
+        jnz LookupLoop1\r
+\r
+\r
+;;; Store the current value of chainlen.\r
+        mov [chainlenwmask], edx\r
+\r
+;;; Point edi to the string under scrutiny, and esi to the string we\r
+;;; are hoping to match it up with. In actuality, esi and edi are\r
+;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is\r
+;;; initialized to -(MAX_MATCH_8 - scanalign).\r
+\r
+        lea rsi,[r8+r10]\r
+        mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8)\r
+        lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8]\r
+        lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8]\r
+\r
+        prefetcht1 [rsi+rdx]\r
+        prefetcht1 [rdi+rdx]\r
+;;; Test the strings for equality, 8 bytes at a time. At the end,\r
+;;; adjust edx so that it is offset to the exact byte that mismatched.\r
+;;;\r
+;;; We already know at this point that the first three bytes of the\r
+;;; strings match each other, and they can be safely passed over before\r
+;;; starting the compare loop. So what this code does is skip over 0-3\r
+;;; bytes, as much as necessary in order to dword-align the edi\r
+;;; pointer. (esi will still be misaligned three times out of four.)\r
+;;;\r
+;;; It should be confessed that this loop usually does not represent\r
+;;; much of the total running time. Replacing it with a more\r
+;;; straightforward "rep cmpsb" would not drastically degrade\r
+;;; performance.\r
+\r
+;LoopCmps:\r
+;        mov eax, [rsi + rdx]\r
+;        xor eax, [rdi + rdx]\r
+;        jnz LeaveLoopCmps\r
+;        mov eax, [rsi + rdx + 4]\r
+;        xor eax, [rdi + rdx + 4]\r
+;        jnz LeaveLoopCmps4\r
+;        add rdx, 8\r
+;        jnz LoopCmps\r
+;        jmp LenMaximum\r
+;LeaveLoopCmps4: add rdx, 4\r
+;LeaveLoopCmps:  test    eax, 0000FFFFh\r
+;        jnz LenLower\r
+;        add rdx,  2\r
+;        shr eax, 16\r
+;LenLower:   sub al, 1\r
+;        adc rdx, 0\r
+\r
+\r
+LoopCmps:\r
+        mov rax, [rsi + rdx]\r
+        xor rax, [rdi + rdx]\r
+        jnz LeaveLoopCmps\r
+\r
+        mov rax, [rsi + rdx + 8]\r
+        xor rax, [rdi + rdx + 8]\r
+        jnz LeaveLoopCmps8\r
+\r
+\r
+        mov rax, [rsi + rdx + 8+8]\r
+        xor rax, [rdi + rdx + 8+8]\r
+        jnz LeaveLoopCmps16\r
+\r
+        add rdx,8+8+8\r
+\r
+        jmp short LoopCmps\r
+LeaveLoopCmps16: add rdx,8\r
+LeaveLoopCmps8: add rdx,8\r
+LeaveLoopCmps:\r
+\r
+        test    eax, 0000FFFFh\r
+        jnz LenLower\r
+\r
+        test eax,0ffffffffh\r
+\r
+        jnz LenLower32\r
+\r
+        add rdx,4\r
+        shr rax,32\r
+        or ax,ax\r
+        jnz LenLower\r
+\r
+LenLower32:\r
+        shr eax,16\r
+        add rdx,2\r
+LenLower:   sub al, 1\r
+        adc rdx, 0\r
+;;; Calculate the length of the match. If it is longer than MAX_MATCH,\r
+;;; then automatically accept it as the best possible match and leave.\r
+\r
+        lea rax, [rdi + rdx]\r
+        sub rax, r9\r
+        cmp eax, MAX_MATCH\r
+        jge LenMaximum\r
+\r
+;;; If the length of the match is not longer than the best match we\r
+;;; have so far, then forget it and return to the lookup loop.\r
+;///////////////////////////////////\r
+\r
+        cmp eax, r11d\r
+        jg  LongerMatch\r
+\r
+        lea rsi,[r10+r11]\r
+\r
+        mov rdi, [rcx + dsPrev]\r
+        mov edx, [chainlenwmask]\r
+        jmp LookupLoop\r
+\r
+;;;         s->match_start = cur_match;\r
+;;;         best_len = len;\r
+;;;         if (len >= nice_match) break;\r
+;;;         scan_end = *(ushf*)(scan+best_len-1);\r
+\r
+LongerMatch:\r
+        mov r11d, eax\r
+        mov [rcx + dsMatchStart], r8d\r
+        cmp eax, [nicematch]\r
+        jge LeaveNow\r
+\r
+        lea rsi,[r10+rax]\r
+\r
+        movzx   ebx, word ptr [r9 + rax - 1]\r
+        mov rdi, [rcx + dsPrev]\r
+        mov edx, [chainlenwmask]\r
+        jmp LookupLoop\r
+\r
+;;; Accept the current string, with the maximum possible length.\r
+\r
+LenMaximum:\r
+        mov r11d,MAX_MATCH\r
+        mov [rcx + dsMatchStart], r8d\r
+\r
+;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;\r
+;;; return s->lookahead;\r
+\r
+LeaveNow:\r
+        mov eax, [rcx + dsLookahead]\r
+        cmp r11d, eax\r
+        cmovng eax, r11d\r
+\r
+\r
+;;; Restore the stack and return from whence we came.\r
+\r
+\r
+        mov rsi,[save_rsi]\r
+        mov rdi,[save_rdi]\r
+        mov rbx,[save_rbx]\r
+        mov rbp,[save_rbp]\r
+        mov r12,[save_r12]\r
+        mov r13,[save_r13]\r
+;        mov r14,[save_r14]\r
+;        mov r15,[save_r15]\r
+\r
+\r
+        ret 0\r
+; please don't remove this string !\r
+; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!\r
+    db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0\r
+longest_match   ENDP\r
+\r
+match_init PROC\r
+  ret 0\r
+match_init ENDP\r
+\r
+\r
+END\r
diff --git a/zlib/contrib/masmx64/inffas8664.c b/zlib/contrib/masmx64/inffas8664.c
new file mode 100644 (file)
index 0000000..3af764d
--- /dev/null
@@ -0,0 +1,186 @@
+/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding\r
+ * version for AMD64 on Windows using Microsoft C compiler\r
+ *\r
+ * Copyright (C) 1995-2003 Mark Adler\r
+ * For conditions of distribution and use, see copyright notice in zlib.h\r
+ *\r
+ * Copyright (C) 2003 Chris Anderson <christop@charm.net>\r
+ * Please use the copyright conditions above.\r
+ *\r
+ * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant\r
+ *\r
+ * inffas8664.c call function inffas8664fnc in inffasx64.asm\r
+ *  inffasx64.asm is automatically convert from AMD64 portion of inffas86.c\r
+ *\r
+ * Dec-29-2003 -- I added AMD64 inflate asm support.  This version is also\r
+ * slightly quicker on x86 systems because, instead of using rep movsb to copy\r
+ * data, it uses rep movsw, which moves data in 2-byte chunks instead of single\r
+ * bytes.  I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates\r
+ * from http://fedora.linux.duke.edu/fc1_x86_64\r
+ * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with\r
+ * 1GB ram.  The 64-bit version is about 4% faster than the 32-bit version,\r
+ * when decompressing mozilla-source-1.3.tar.gz.\r
+ *\r
+ * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from\r
+ * the gcc -S output of zlib-1.2.0/inffast.c.  Zlib-1.2.0 is in beta release at\r
+ * the moment.  I have successfully compiled and tested this code with gcc2.96,\r
+ * gcc3.2, icc5.0, msvc6.0.  It is very close to the speed of inffast.S\r
+ * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX\r
+ * enabled.  I will attempt to merge the MMX code into this version.  Newer\r
+ * versions of this and inffast.S can be found at\r
+ * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/\r
+ *\r
+ */\r
+\r
+#include <stdio.h>\r
+#include "zutil.h"\r
+#include "inftrees.h"\r
+#include "inflate.h"\r
+#include "inffast.h"\r
+\r
+/* Mark Adler's comments from inffast.c: */\r
+\r
+/*\r
+   Decode literal, length, and distance codes and write out the resulting\r
+   literal and match bytes until either not enough input or output is\r
+   available, an end-of-block is encountered, or a data error is encountered.\r
+   When large enough input and output buffers are supplied to inflate(), for\r
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the\r
+   inflate execution time is spent in this routine.\r
+\r
+   Entry assumptions:\r
+\r
+        state->mode == LEN\r
+        strm->avail_in >= 6\r
+        strm->avail_out >= 258\r
+        start >= strm->avail_out\r
+        state->bits < 8\r
+\r
+   On return, state->mode is one of:\r
+\r
+        LEN -- ran out of enough output space or enough available input\r
+        TYPE -- reached end of block code, inflate() to interpret next block\r
+        BAD -- error in block data\r
+\r
+   Notes:\r
+\r
+    - The maximum input bits used by a length/distance pair is 15 bits for the\r
+      length code, 5 bits for the length extra, 15 bits for the distance code,\r
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.\r
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid\r
+      checking for available input while decoding.\r
+\r
+    - The maximum bytes that a single length/distance pair can output is 258\r
+      bytes, which is the maximum length that can be coded.  inflate_fast()\r
+      requires strm->avail_out >= 258 for each loop to avoid checking for\r
+      output space.\r
+ */\r
+\r
+\r
+\r
+    typedef struct inffast_ar {\r
+/* 64   32                               x86  x86_64 */\r
+/* ar offset                              register */\r
+/*  0    0 */ void *esp;                /* esp save */\r
+/*  8    4 */ void *ebp;                /* ebp save */\r
+/* 16    8 */ unsigned char FAR *in;    /* esi rsi  local strm->next_in */\r
+/* 24   12 */ unsigned char FAR *last;  /*     r9   while in < last */\r
+/* 32   16 */ unsigned char FAR *out;   /* edi rdi  local strm->next_out */\r
+/* 40   20 */ unsigned char FAR *beg;   /*          inflate()'s init next_out */\r
+/* 48   24 */ unsigned char FAR *end;   /*     r10  while out < end */\r
+/* 56   28 */ unsigned char FAR *window;/*          size of window, wsize!=0 */\r
+/* 64   32 */ code const FAR *lcode;    /* ebp rbp  local strm->lencode */\r
+/* 72   36 */ code const FAR *dcode;    /*     r11  local strm->distcode */\r
+/* 80   40 */ size_t /*unsigned long */hold;       /* edx rdx  local strm->hold */\r
+/* 88   44 */ unsigned bits;            /* ebx rbx  local strm->bits */\r
+/* 92   48 */ unsigned wsize;           /*          window size */\r
+/* 96   52 */ unsigned write;           /*          window write index */\r
+/*100   56 */ unsigned lmask;           /*     r12  mask for lcode */\r
+/*104   60 */ unsigned dmask;           /*     r13  mask for dcode */\r
+/*108   64 */ unsigned len;             /*     r14  match length */\r
+/*112   68 */ unsigned dist;            /*     r15  match distance */\r
+/*116   72 */ unsigned status;          /*          set when state chng*/\r
+    } type_ar;\r
+#ifdef ASMINF\r
+\r
+void inflate_fast(strm, start)\r
+z_streamp strm;\r
+unsigned start;         /* inflate()'s starting value for strm->avail_out */\r
+{\r
+    struct inflate_state FAR *state;\r
+    type_ar ar;\r
+    void inffas8664fnc(struct inffast_ar * par);\r
+\r
+    \r
+\r
+#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64))\r
+#define PAD_AVAIL_IN 6\r
+#define PAD_AVAIL_OUT 258    \r
+#else\r
+#define PAD_AVAIL_IN 5\r
+#define PAD_AVAIL_OUT 257\r
+#endif\r
+\r
+    /* copy state to local variables */\r
+    state = (struct inflate_state FAR *)strm->state;\r
+\r
+    ar.in = strm->next_in;\r
+    ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN);\r
+    ar.out = strm->next_out;\r
+    ar.beg = ar.out - (start - strm->avail_out);\r
+    ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);\r
+    ar.wsize = state->wsize;\r
+    ar.write = state->write;\r
+    ar.window = state->window;\r
+    ar.hold = state->hold;\r
+    ar.bits = state->bits;\r
+    ar.lcode = state->lencode;\r
+    ar.dcode = state->distcode;\r
+    ar.lmask = (1U << state->lenbits) - 1;\r
+    ar.dmask = (1U << state->distbits) - 1;\r
+\r
+    /* decode literals and length/distances until end-of-block or not enough\r
+       input data or output space */\r
+\r
+    /* align in on 1/2 hold size boundary */\r
+    while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) {\r
+        ar.hold += (unsigned long)*ar.in++ << ar.bits;\r
+        ar.bits += 8;\r
+    }\r
+\r
+    inffas8664fnc(&ar);\r
+\r
+    if (ar.status > 1) {\r
+        if (ar.status == 2)\r
+            strm->msg = "invalid literal/length code";\r
+        else if (ar.status == 3)\r
+            strm->msg = "invalid distance code";\r
+        else\r
+            strm->msg = "invalid distance too far back";\r
+        state->mode = BAD;\r
+    }\r
+    else if ( ar.status == 1 ) {\r
+        state->mode = TYPE;\r
+    }\r
+\r
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */\r
+    ar.len = ar.bits >> 3;\r
+    ar.in -= ar.len;\r
+    ar.bits -= ar.len << 3;\r
+    ar.hold &= (1U << ar.bits) - 1;\r
+\r
+    /* update state and return */\r
+    strm->next_in = ar.in;\r
+    strm->next_out = ar.out;\r
+    strm->avail_in = (unsigned)(ar.in < ar.last ?\r
+                                PAD_AVAIL_IN + (ar.last - ar.in) :\r
+                                PAD_AVAIL_IN - (ar.in - ar.last));\r
+    strm->avail_out = (unsigned)(ar.out < ar.end ?\r
+                                 PAD_AVAIL_OUT + (ar.end - ar.out) :\r
+                                 PAD_AVAIL_OUT - (ar.out - ar.end));\r
+    state->hold = (unsigned long)ar.hold;\r
+    state->bits = ar.bits;\r
+    return;\r
+}\r
+\r
+#endif\r
diff --git a/zlib/contrib/masmx64/inffasx64.asm b/zlib/contrib/masmx64/inffasx64.asm
new file mode 100644 (file)
index 0000000..b5d93a2
--- /dev/null
@@ -0,0 +1,392 @@
+; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding\r
+; version for AMD64 on Windows using Microsoft C compiler\r
+;\r
+; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c\r
+; inffasx64.asm is called by inffas8664.c, which contain more info.\r
+\r
+\r
+; to compile this file, I use option\r
+;   ml64.exe /Flinffasx64 /c /Zi inffasx64.asm\r
+;   with Microsoft Macro Assembler (x64) for AMD64\r
+;\r
+;   ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK\r
+;\r
+;   (you can get Windows 2003 server DDK with ml64 and cl.exe for AMD64 from \r
+;      http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)\r
+;\r
+\r
+.code\r
+inffas8664fnc PROC\r
+\r
+; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and\r
+; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp\r
+;\r
+; All registers must be preserved across the call, except for\r
+;   rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch.\r
+\r
+\r
+       mov [rsp-8],rsi\r
+       mov [rsp-16],rdi\r
+       mov [rsp-24],r12\r
+       mov [rsp-32],r13\r
+       mov [rsp-40],r14\r
+       mov [rsp-48],r15\r
+       mov [rsp-56],rbx\r
+\r
+       mov rax,rcx\r
+\r
+       mov     [rax+8], rbp       ; /* save regs rbp and rsp */\r
+       mov     [rax], rsp\r
+\r
+       mov     rsp, rax          ; /* make rsp point to &ar */\r
+\r
+       mov     rsi, [rsp+16]      ; /* rsi  = in */\r
+       mov     rdi, [rsp+32]      ; /* rdi  = out */\r
+       mov     r9, [rsp+24]       ; /* r9   = last */\r
+       mov     r10, [rsp+48]      ; /* r10  = end */\r
+       mov     rbp, [rsp+64]      ; /* rbp  = lcode */\r
+       mov     r11, [rsp+72]      ; /* r11  = dcode */\r
+       mov     rdx, [rsp+80]      ; /* rdx  = hold */\r
+       mov     ebx, [rsp+88]      ; /* ebx  = bits */\r
+       mov     r12d, [rsp+100]    ; /* r12d = lmask */\r
+       mov     r13d, [rsp+104]    ; /* r13d = dmask */\r
+                                          ; /* r14d = len */\r
+                                          ; /* r15d = dist */\r
+\r
+\r
+       cld\r
+       cmp     r10, rdi\r
+       je      L_one_time           ; /* if only one decode left */\r
+       cmp     r9, rsi\r
+\r
+    jne L_do_loop\r
+\r
+\r
+L_one_time:\r
+       mov     r8, r12           ; /* r8 = lmask */\r
+       cmp     bl, 32\r
+       ja      L_get_length_code_one_time\r
+\r
+       lodsd                         ; /* eax = *(uint *)in++ */\r
+       mov     cl, bl            ; /* cl = bits, needs it for shifting */\r
+       add     bl, 32             ; /* bits += 32 */\r
+       shl     rax, cl\r
+       or      rdx, rax          ; /* hold |= *((uint *)in)++ << bits */\r
+       jmp     L_get_length_code_one_time\r
+\r
+ALIGN 4\r
+L_while_test:\r
+       cmp     r10, rdi\r
+       jbe     L_break_loop\r
+       cmp     r9, rsi\r
+       jbe     L_break_loop\r
+\r
+L_do_loop:\r
+       mov     r8, r12           ; /* r8 = lmask */\r
+       cmp     bl, 32\r
+       ja      L_get_length_code    ; /* if (32 < bits) */\r
+\r
+       lodsd                         ; /* eax = *(uint *)in++ */\r
+       mov     cl, bl            ; /* cl = bits, needs it for shifting */\r
+       add     bl, 32             ; /* bits += 32 */\r
+       shl     rax, cl\r
+       or      rdx, rax          ; /* hold |= *((uint *)in)++ << bits */\r
+\r
+L_get_length_code:\r
+       and     r8, rdx            ; /* r8 &= hold */\r
+       mov     eax, [rbp+r8*4]  ; /* eax = lcode[hold & lmask] */\r
+\r
+       mov     cl, ah            ; /* cl = this.bits */\r
+       sub     bl, ah            ; /* bits -= this.bits */\r
+       shr     rdx, cl           ; /* hold >>= this.bits */\r
+\r
+       test    al, al\r
+       jnz     L_test_for_length_base ; /* if (op != 0) 45.7% */\r
+\r
+       mov     r8, r12            ; /* r8 = lmask */\r
+       shr     eax, 16            ; /* output this.val char */\r
+       stosb\r
+\r
+L_get_length_code_one_time:\r
+       and     r8, rdx            ; /* r8 &= hold */\r
+       mov     eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */\r
+\r
+L_dolen:\r
+       mov     cl, ah            ; /* cl = this.bits */\r
+       sub     bl, ah            ; /* bits -= this.bits */\r
+       shr     rdx, cl           ; /* hold >>= this.bits */\r
+\r
+       test    al, al\r
+       jnz     L_test_for_length_base ; /* if (op != 0) 45.7% */\r
+\r
+       shr     eax, 16            ; /* output this.val char */\r
+       stosb\r
+       jmp     L_while_test\r
+\r
+ALIGN 4\r
+L_test_for_length_base:\r
+       mov     r14d, eax         ; /* len = this */\r
+       shr     r14d, 16           ; /* len = this.val */\r
+       mov     cl, al\r
+\r
+       test    al, 16\r
+       jz      L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */\r
+       and     cl, 15             ; /* op &= 15 */\r
+       jz      L_decode_distance    ; /* if (!op) */\r
+\r
+L_add_bits_to_len:\r
+       sub     bl, cl\r
+       xor     eax, eax\r
+       inc     eax\r
+       shl     eax, cl\r
+       dec     eax\r
+       and     eax, edx          ; /* eax &= hold */\r
+       shr     rdx, cl\r
+       add     r14d, eax         ; /* len += hold & mask[op] */\r
+\r
+L_decode_distance:\r
+       mov     r8, r13           ; /* r8 = dmask */\r
+       cmp     bl, 32\r
+       ja      L_get_distance_code  ; /* if (32 < bits) */\r
+\r
+       lodsd                         ; /* eax = *(uint *)in++ */\r
+       mov     cl, bl            ; /* cl = bits, needs it for shifting */\r
+       add     bl, 32             ; /* bits += 32 */\r
+       shl     rax, cl\r
+       or      rdx, rax          ; /* hold |= *((uint *)in)++ << bits */\r
+\r
+L_get_distance_code:\r
+       and     r8, rdx           ; /* r8 &= hold */\r
+       mov     eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */\r
+\r
+L_dodist:\r
+       mov     r15d, eax         ; /* dist = this */\r
+       shr     r15d, 16           ; /* dist = this.val */\r
+       mov     cl, ah\r
+       sub     bl, ah            ; /* bits -= this.bits */\r
+       shr     rdx, cl           ; /* hold >>= this.bits */\r
+       mov     cl, al            ; /* cl = this.op */\r
+\r
+       test    al, 16             ; /* if ((op & 16) == 0) */\r
+       jz      L_test_for_second_level_dist\r
+       and     cl, 15             ; /* op &= 15 */\r
+       jz      L_check_dist_one\r
+\r
+L_add_bits_to_dist:\r
+       sub     bl, cl\r
+       xor     eax, eax\r
+       inc     eax\r
+       shl     eax, cl\r
+       dec     eax                 ; /* (1 << op) - 1 */\r
+       and     eax, edx          ; /* eax &= hold */\r
+       shr     rdx, cl\r
+       add     r15d, eax         ; /* dist += hold & ((1 << op) - 1) */\r
+\r
+L_check_window:\r
+       mov     r8, rsi           ; /* save in so from can use it's reg */\r
+       mov     rax, rdi\r
+       sub     rax, [rsp+40]      ; /* nbytes = out - beg */\r
+\r
+       cmp     eax, r15d\r
+       jb      L_clip_window        ; /* if (dist > nbytes) 4.2% */\r
+\r
+       mov     ecx, r14d         ; /* ecx = len */\r
+       mov     rsi, rdi\r
+       sub     rsi, r15          ; /* from = out - dist */\r
+\r
+       sar     ecx, 1\r
+       jnc     L_copy_two           ; /* if len % 2 == 0 */\r
+\r
+       rep     movsw\r
+       mov     al, [rsi]\r
+       mov     [rdi], al\r
+       inc     rdi\r
+\r
+       mov     rsi, r8           ; /* move in back to %rsi, toss from */\r
+       jmp     L_while_test\r
+\r
+L_copy_two:\r
+       rep     movsw\r
+       mov     rsi, r8           ; /* move in back to %rsi, toss from */\r
+       jmp     L_while_test\r
+\r
+ALIGN 4\r
+L_check_dist_one:\r
+       cmp     r15d, 1            ; /* if dist 1, is a memset */\r
+       jne     L_check_window\r
+       cmp     [rsp+40], rdi      ; /* if out == beg, outside window */\r
+       je      L_check_window\r
+\r
+       mov     ecx, r14d         ; /* ecx = len */\r
+       mov     al, [rdi-1]\r
+       mov     ah, al\r
+\r
+       sar     ecx, 1\r
+       jnc     L_set_two\r
+       mov     [rdi], al\r
+       inc     rdi\r
+\r
+L_set_two:\r
+       rep     stosw\r
+       jmp     L_while_test\r
+\r
+ALIGN 4\r
+L_test_for_second_level_length:\r
+       test    al, 64\r
+       jnz     L_test_for_end_of_block ; /* if ((op & 64) != 0) */\r
+\r
+       xor     eax, eax\r
+       inc     eax\r
+       shl     eax, cl\r
+       dec     eax\r
+       and     eax, edx         ; /* eax &= hold */\r
+       add     eax, r14d        ; /* eax += len */\r
+       mov     eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/\r
+       jmp     L_dolen\r
+\r
+ALIGN 4\r
+L_test_for_second_level_dist:\r
+       test    al, 64\r
+       jnz     L_invalid_distance_code ; /* if ((op & 64) != 0) */\r
+\r
+       xor     eax, eax\r
+       inc     eax\r
+       shl     eax, cl\r
+       dec     eax\r
+       and     eax, edx         ; /* eax &= hold */\r
+       add     eax, r15d        ; /* eax += dist */\r
+       mov     eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/\r
+       jmp     L_dodist\r
+\r
+ALIGN 4\r
+L_clip_window:\r
+       mov     ecx, eax         ; /* ecx = nbytes */\r
+       mov     eax, [rsp+92]     ; /* eax = wsize, prepare for dist cmp */\r
+       neg     ecx                ; /* nbytes = -nbytes */\r
+\r
+       cmp     eax, r15d\r
+       jb      L_invalid_distance_too_far ; /* if (dist > wsize) */\r
+\r
+       add     ecx, r15d         ; /* nbytes = dist - nbytes */\r
+       cmp     dword ptr [rsp+96], 0\r
+       jne     L_wrap_around_window ; /* if (write != 0) */\r
+\r
+       mov     rsi, [rsp+56]     ; /* from  = window */\r
+       sub     eax, ecx         ; /* eax  -= nbytes */\r
+       add     rsi, rax         ; /* from += wsize - nbytes */\r
+\r
+       mov     eax, r14d        ; /* eax = len */\r
+       cmp     r14d, ecx\r
+       jbe     L_do_copy           ; /* if (nbytes >= len) */\r
+\r
+       sub     eax, ecx         ; /* eax -= nbytes */\r
+       rep     movsb\r
+       mov     rsi, rdi\r
+       sub     rsi, r15         ; /* from = &out[ -dist ] */\r
+       jmp     L_do_copy\r
+\r
+ALIGN 4\r
+L_wrap_around_window:\r
+       mov     eax, [rsp+96]     ; /* eax = write */\r
+       cmp     ecx, eax\r
+       jbe     L_contiguous_in_window ; /* if (write >= nbytes) */\r
+\r
+       mov     esi, [rsp+92]     ; /* from  = wsize */\r
+       add     rsi, [rsp+56]     ; /* from += window */\r
+       add     rsi, rax         ; /* from += write */\r
+       sub     rsi, rcx         ; /* from -= nbytes */\r
+       sub     ecx, eax         ; /* nbytes -= write */\r
+\r
+       mov     eax, r14d        ; /* eax = len */\r
+       cmp     eax, ecx\r
+       jbe     L_do_copy           ; /* if (nbytes >= len) */\r
+\r
+       sub     eax, ecx         ; /* len -= nbytes */\r
+       rep     movsb\r
+       mov     rsi, [rsp+56]     ; /* from = window */\r
+       mov     ecx, [rsp+96]     ; /* nbytes = write */\r
+       cmp     eax, ecx\r
+       jbe     L_do_copy           ; /* if (nbytes >= len) */\r
+\r
+       sub     eax, ecx         ; /* len -= nbytes */\r
+       rep     movsb\r
+       mov     rsi, rdi\r
+       sub     rsi, r15         ; /* from = out - dist */\r
+       jmp     L_do_copy\r
+\r
+ALIGN 4\r
+L_contiguous_in_window:\r
+       mov     rsi, [rsp+56]     ; /* rsi = window */\r
+       add     rsi, rax\r
+       sub     rsi, rcx         ; /* from += write - nbytes */\r
+\r
+       mov     eax, r14d        ; /* eax = len */\r
+       cmp     eax, ecx\r
+       jbe     L_do_copy           ; /* if (nbytes >= len) */\r
+\r
+       sub     eax, ecx         ; /* len -= nbytes */\r
+       rep     movsb\r
+       mov     rsi, rdi\r
+       sub     rsi, r15         ; /* from = out - dist */\r
+       jmp     L_do_copy           ; /* if (nbytes >= len) */\r
+\r
+ALIGN 4\r
+L_do_copy:\r
+       mov     ecx, eax         ; /* ecx = len */\r
+       rep     movsb\r
+\r
+       mov     rsi, r8          ; /* move in back to %esi, toss from */\r
+       jmp     L_while_test\r
+\r
+L_test_for_end_of_block:\r
+       test    al, 32\r
+       jz      L_invalid_literal_length_code\r
+       mov     dword ptr [rsp+116], 1\r
+       jmp     L_break_loop_with_status\r
+\r
+L_invalid_literal_length_code:\r
+       mov     dword ptr [rsp+116], 2\r
+       jmp     L_break_loop_with_status\r
+\r
+L_invalid_distance_code:\r
+       mov     dword ptr [rsp+116], 3\r
+       jmp     L_break_loop_with_status\r
+\r
+L_invalid_distance_too_far:\r
+       mov     dword ptr [rsp+116], 4\r
+       jmp     L_break_loop_with_status\r
+\r
+L_break_loop:\r
+       mov     dword ptr [rsp+116], 0\r
+\r
+L_break_loop_with_status:\r
+; /* put in, out, bits, and hold back into ar and pop esp */\r
+       mov     [rsp+16], rsi     ; /* in */\r
+       mov     [rsp+32], rdi     ; /* out */\r
+       mov     [rsp+88], ebx     ; /* bits */\r
+       mov     [rsp+80], rdx     ; /* hold */\r
+\r
+       mov     rax, [rsp]       ; /* restore rbp and rsp */\r
+       mov     rbp, [rsp+8]\r
+       mov     rsp, rax\r
+\r
+\r
+\r
+       mov rsi,[rsp-8]\r
+       mov rdi,[rsp-16]\r
+       mov r12,[rsp-24]\r
+       mov r13,[rsp-32]\r
+       mov r14,[rsp-40]\r
+       mov r15,[rsp-48]\r
+       mov rbx,[rsp-56]\r
+       \r
+    ret 0\r
+;          :\r
+;          : "m" (ar)\r
+;          : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",\r
+;            "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"\r
+;    );\r
+\r
+inffas8664fnc  ENDP\r
+;_TEXT ENDS\r
+END\r
diff --git a/zlib/contrib/masmx64/readme.txt b/zlib/contrib/masmx64/readme.txt
new file mode 100644 (file)
index 0000000..ee03115
--- /dev/null
@@ -0,0 +1,28 @@
+Summary\r
+-------\r
+This directory contains ASM implementations of the functions\r
+longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t),\r
+for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits.\r
+\r
+gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits\r
+   assembly optimized version from Jean-loup Gailly original longest_match function\r
+\r
+inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing\r
+   original function from Mark Adler\r
+\r
+Use instructions\r
+----------------\r
+Copy these files into the zlib source directory.\r
+\r
+define ASMV and ASMINF in your project. Include inffas8664.c in your source tree,\r
+and inffasx64.obj and gvmat64.obj as object to link.\r
+\r
+\r
+Build instructions\r
+------------------\r
+run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe)\r
+\r
+ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK\r
+\r
+You can get Windows 2003 server DDK with ml64 and cl for AMD64 from \r
+  http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)\r
diff --git a/zlib/contrib/masmx86/bld_ml32.bat b/zlib/contrib/masmx86/bld_ml32.bat
new file mode 100644 (file)
index 0000000..99144d0
--- /dev/null
@@ -0,0 +1,2 @@
+ml /coff /Zi /c /Flgvmat32.lst  gvmat32.asm \r
+ml /coff /Zi /c /Flinffas32.lst inffas32.asm \r
index ec360e6..874bb2d 100644 (file)
-;
-; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86
-; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
-; File written by Gilles Vollant, by modifiying the longest_match
-;  from Jean-loup Gailly in deflate.c
-; It need wmask == 0x7fff
-;     (assembly code is faster with a fixed wmask)
-;
-; For Visual C++ 4.2 and ML 6.11c (version in directory \MASM611C of Win95 DDK)
-;   I compile with : "ml /coff /Zi /c gvmat32.asm"
-;
-
-;uInt longest_match_7fff(s, cur_match)
-;    deflate_state *s;
-;    IPos cur_match;                             /* current match */
-
-       NbStack         equ     76
-       cur_match       equ     dword ptr[esp+NbStack-0]
-       str_s           equ     dword ptr[esp+NbStack-4]
-; 5 dword on top (ret,ebp,esi,edi,ebx)
-       adrret          equ     dword ptr[esp+NbStack-8]
-       pushebp         equ     dword ptr[esp+NbStack-12]
-       pushedi         equ     dword ptr[esp+NbStack-16]
-       pushesi         equ     dword ptr[esp+NbStack-20]
-       pushebx         equ     dword ptr[esp+NbStack-24]
-
-       chain_length    equ     dword ptr [esp+NbStack-28]
-       limit           equ     dword ptr [esp+NbStack-32]
-       best_len        equ     dword ptr [esp+NbStack-36]
-       window          equ     dword ptr [esp+NbStack-40]
-       prev            equ     dword ptr [esp+NbStack-44]
-       scan_start      equ      word ptr [esp+NbStack-48]
-       wmask           equ     dword ptr [esp+NbStack-52]
-       match_start_ptr equ     dword ptr [esp+NbStack-56]
-       nice_match      equ     dword ptr [esp+NbStack-60]
-       scan            equ     dword ptr [esp+NbStack-64]
-
-       windowlen       equ     dword ptr [esp+NbStack-68]
-       match_start     equ     dword ptr [esp+NbStack-72]
-       strend          equ     dword ptr [esp+NbStack-76]
-       NbStackAdd      equ     (NbStack-24)
-
-    .386p
-
-    name    gvmatch
-    .MODEL  FLAT
-
-
-
-;  all the +4 offsets are due to the addition of pending_buf_size (in zlib
-;  in the deflate_state structure since the asm code was first written
-;  (if you compile with zlib 1.0.4 or older, remove the +4).
-;  Note : these value are good with a 8 bytes boundary pack structure
-    dep_chain_length    equ     70h+4
-    dep_window          equ     2ch+4
-    dep_strstart        equ     60h+4
-    dep_prev_length     equ     6ch+4
-    dep_nice_match      equ     84h+4
-    dep_w_size          equ     20h+4
-    dep_prev            equ     34h+4
-    dep_w_mask          equ     28h+4
-    dep_good_match      equ     80h+4
-    dep_match_start     equ     64h+4
-    dep_lookahead       equ     68h+4
-
-
-_TEXT                   segment
-
-IFDEF NOUNDERLINE
-                       public  longest_match_7fff
-                       public  longest_match_686
-;                        public  match_init
-ELSE
-                       public  _longest_match_7fff
-                       public  _longest_match_686
-;                        public  _match_init
-ENDIF
-
-    MAX_MATCH           equ     258
-    MIN_MATCH           equ     3
-    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)
-
-
-
-IFDEF NOUNDERLINE
-;match_init      proc near
-;                ret
-;match_init      endp
-ELSE
-;_match_init     proc near
-;                ret
-;_match_init     endp
-ENDIF
-
-
-IFDEF NOUNDERLINE
-longest_match_7fff   proc near
-ELSE
-_longest_match_7fff  proc near
-ENDIF
-
-       mov     edx,[esp+4]
-
-
-
-       push    ebp
-       push    edi
-       push    esi
-       push    ebx
-
-       sub     esp,NbStackAdd
-
-; initialize or check the variables used in match.asm.
-       mov     ebp,edx
-
-; chain_length = s->max_chain_length
-; if (prev_length>=good_match) chain_length >>= 2
-       mov     edx,[ebp+dep_chain_length]
-       mov     ebx,[ebp+dep_prev_length]
-       cmp     [ebp+dep_good_match],ebx
-       ja      noshr
-       shr     edx,2
-noshr:
-; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop
-       inc     edx
-       mov     edi,[ebp+dep_nice_match]
-       mov     chain_length,edx
-       mov     eax,[ebp+dep_lookahead]
-       cmp     eax,edi
-; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-       jae     nolookaheadnicematch
-       mov     edi,eax
-nolookaheadnicematch:
-; best_len = s->prev_length
-       mov     best_len,ebx
-
-; window = s->window
-       mov     esi,[ebp+dep_window]
-       mov     ecx,[ebp+dep_strstart]
-       mov     window,esi
-
-       mov     nice_match,edi
-; scan = window + strstart
-       add     esi,ecx
-       mov     scan,esi
-; dx = *window
-       mov     dx,word ptr [esi]
-; bx = *(window+best_len-1)
-       mov     bx,word ptr [esi+ebx-1]
-       add     esi,MAX_MATCH-1
-; scan_start = *scan
-       mov     scan_start,dx
-; strend = scan + MAX_MATCH-1
-       mov     strend,esi
-; bx = scan_end = *(window+best_len-1)
-
-;    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
-;        s->strstart - (IPos)MAX_DIST(s) : NIL;
-
-       mov     esi,[ebp+dep_w_size]
-       sub     esi,MIN_LOOKAHEAD
-; here esi = MAX_DIST(s)
-       sub     ecx,esi
-       ja      nodist
-       xor     ecx,ecx
-nodist:
-       mov     limit,ecx
-
-; prev = s->prev
-       mov     edx,[ebp+dep_prev]
-       mov     prev,edx
-
-;
-       mov     edx,dword ptr [ebp+dep_match_start]
-       mov     bp,scan_start
-       mov     eax,cur_match
-       mov     match_start,edx
-
-       mov     edx,window
-       mov     edi,edx
-       add     edi,best_len
-       mov     esi,prev
-       dec     edi
-; windowlen = window + best_len -1
-       mov     windowlen,edi
-
-       jmp     beginloop2
-       align   4
-
-; here, in the loop
-;       eax = ax = cur_match
-;       ecx = limit
-;        bx = scan_end
-;        bp = scan_start
-;       edi = windowlen (window + best_len -1)
-;       esi = prev
-
-
-;// here; chain_length <=16
-normalbeg0add16:
-       add     chain_length,16
-       jz      exitloop
-normalbeg0:
-       cmp     word ptr[edi+eax],bx
-       je      normalbeg2noroll
-rcontlabnoroll:
-; cur_match = prev[cur_match & wmask]
-       and     eax,7fffh
-       mov     ax,word ptr[esi+eax*2]
-; if cur_match > limit, go to exitloop
-       cmp     ecx,eax
-       jnb     exitloop
-; if --chain_length != 0, go to exitloop
-       dec     chain_length
-       jnz     normalbeg0
-       jmp     exitloop
-
-normalbeg2noroll:
-; if (scan_start==*(cur_match+window)) goto normalbeg2
-       cmp     bp,word ptr[edx+eax]
-       jne     rcontlabnoroll
-       jmp     normalbeg2
-
-contloop3:
-       mov     edi,windowlen
-
-; cur_match = prev[cur_match & wmask]
-       and     eax,7fffh
-       mov     ax,word ptr[esi+eax*2]
-; if cur_match > limit, go to exitloop
-       cmp     ecx,eax
-jnbexitloopshort1:
-       jnb     exitloop
-; if --chain_length != 0, go to exitloop
-
-
-; begin the main loop
-beginloop2:
-       sub     chain_length,16+1
-; if chain_length <=16, don't use the unrolled loop
-       jna     normalbeg0add16
-
-do16:
-       cmp     word ptr[edi+eax],bx
-       je      normalbeg2dc0
-
-maccn   MACRO   lab
-       and     eax,7fffh
-       mov     ax,word ptr[esi+eax*2]
-       cmp     ecx,eax
-       jnb     exitloop
-       cmp     word ptr[edi+eax],bx
-       je      lab
-       ENDM
-
-rcontloop0:
-       maccn   normalbeg2dc1
-
-rcontloop1:
-       maccn   normalbeg2dc2
-
-rcontloop2:
-       maccn   normalbeg2dc3
-
-rcontloop3:
-       maccn   normalbeg2dc4
-
-rcontloop4:
-       maccn   normalbeg2dc5
-
-rcontloop5:
-       maccn   normalbeg2dc6
-
-rcontloop6:
-       maccn   normalbeg2dc7
-
-rcontloop7:
-       maccn   normalbeg2dc8
-
-rcontloop8:
-       maccn   normalbeg2dc9
-
-rcontloop9:
-       maccn   normalbeg2dc10
-
-rcontloop10:
-       maccn   short normalbeg2dc11
-
-rcontloop11:
-       maccn   short normalbeg2dc12
-
-rcontloop12:
-       maccn   short normalbeg2dc13
-
-rcontloop13:
-       maccn   short normalbeg2dc14
-
-rcontloop14:
-       maccn   short normalbeg2dc15
-
-rcontloop15:
-       and     eax,7fffh
-       mov     ax,word ptr[esi+eax*2]
-       cmp     ecx,eax
-       jnb     exitloop
-
-       sub     chain_length,16
-       ja      do16
-       jmp     normalbeg0add16
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-normbeg MACRO   rcontlab,valsub
-; if we are here, we know that *(match+best_len-1) == scan_end
-       cmp     bp,word ptr[edx+eax]
-; if (match != scan_start) goto rcontlab
-       jne     rcontlab
-; calculate the good chain_length, and we'll compare scan and match string
-       add     chain_length,16-valsub
-       jmp     iseq
-       ENDM
-
-
-normalbeg2dc11:
-       normbeg rcontloop11,11
-
-normalbeg2dc12:
-       normbeg short rcontloop12,12
-
-normalbeg2dc13:
-       normbeg short rcontloop13,13
-
-normalbeg2dc14:
-       normbeg short rcontloop14,14
-
-normalbeg2dc15:
-       normbeg short rcontloop15,15
-
-normalbeg2dc10:
-       normbeg rcontloop10,10
-
-normalbeg2dc9:
-       normbeg rcontloop9,9
-
-normalbeg2dc8:
-       normbeg rcontloop8,8
-
-normalbeg2dc7:
-       normbeg rcontloop7,7
-
-normalbeg2dc6:
-       normbeg rcontloop6,6
-
-normalbeg2dc5:
-       normbeg rcontloop5,5
-
-normalbeg2dc4:
-       normbeg rcontloop4,4
-
-normalbeg2dc3:
-       normbeg rcontloop3,3
-
-normalbeg2dc2:
-       normbeg rcontloop2,2
-
-normalbeg2dc1:
-       normbeg rcontloop1,1
-
-normalbeg2dc0:
-       normbeg rcontloop0,0
-
-
-; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end
-
-normalbeg2:
-       mov     edi,window
-
-       cmp     bp,word ptr[edi+eax]
-       jne     contloop3                   ; if *(ushf*)match != scan_start, continue
-
-iseq:
-; if we are here, we know that *(match+best_len-1) == scan_end
-; and (match == scan_start)
-
-       mov     edi,edx
-       mov     esi,scan                    ; esi = scan
-       add     edi,eax                     ; edi = window + cur_match = match
-
-       mov     edx,[esi+3]                 ; compare manually dword at match+3
-       xor     edx,[edi+3]                 ; and scan +3
-
-       jz      begincompare                ; if equal, go to long compare
-
-; we will determine the unmatch byte and calculate len (in esi)
-       or      dl,dl
-       je      eq1rr
-       mov     esi,3
-       jmp     trfinval
-eq1rr:
-       or      dx,dx
-       je      eq1
-
-       mov     esi,4
-       jmp     trfinval
-eq1:
-       and     edx,0ffffffh
-       jz      eq11
-       mov     esi,5
-       jmp     trfinval
-eq11:
-       mov     esi,6
-       jmp     trfinval
-
-begincompare:
-       ; here we now scan and match begin same
-       add     edi,6
-       add     esi,6
-       mov     ecx,(MAX_MATCH-(2+4))/4     ; scan for at most MAX_MATCH bytes
-       repe    cmpsd                       ; loop until mismatch
-
-       je      trfin                       ; go to trfin if not unmatch
-; we determine the unmatch byte
-       sub     esi,4
-       mov     edx,[edi-4]
-       xor     edx,[esi]
-
-       or      dl,dl
-       jnz     trfin
-       inc     esi
-
-       or      dx,dx
-       jnz     trfin
-       inc     esi
-
-       and     edx,0ffffffh
-       jnz     trfin
-       inc     esi
-
-trfin:
-       sub     esi,scan          ; esi = len
-trfinval:
-; here we have finised compare, and esi contain len of equal string
-       cmp     esi,best_len        ; if len > best_len, go newbestlen
-       ja      short newbestlen
-; now we restore edx, ecx and esi, for the big loop
-       mov     esi,prev
-       mov     ecx,limit
-       mov     edx,window
-       jmp     contloop3
-
-newbestlen:
-       mov     best_len,esi        ; len become best_len
-
-       mov     match_start,eax     ; save new position as match_start
-       cmp     esi,nice_match      ; if best_len >= nice_match, exit
-       jae     exitloop
-       mov     ecx,scan
-       mov     edx,window          ; restore edx=window
-       add     ecx,esi
-       add     esi,edx
-
-       dec     esi
-       mov     windowlen,esi       ; windowlen = window + best_len-1
-       mov     bx,[ecx-1]          ; bx = *(scan+best_len-1) = scan_end
-
-; now we restore ecx and esi, for the big loop :
-       mov     esi,prev
-       mov     ecx,limit
-       jmp     contloop3
-
-exitloop:
-; exit : s->match_start=match_start
-       mov     ebx,match_start
-       mov     ebp,str_s
-       mov     ecx,best_len
-       mov     dword ptr [ebp+dep_match_start],ebx
-       mov     eax,dword ptr [ebp+dep_lookahead]
-       cmp     ecx,eax
-       ja      minexlo
-       mov     eax,ecx
-minexlo:
-; return min(best_len,s->lookahead)
-
-; restore stack and register ebx,esi,edi,ebp
-       add     esp,NbStackAdd
-
-       pop     ebx
-       pop     esi
-       pop     edi
-       pop     ebp
-       ret
-InfoAuthor:
-; please don't remove this string !
-; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!
-       db     0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah
-
-
-
-IFDEF NOUNDERLINE
-longest_match_7fff   endp
-ELSE
-_longest_match_7fff  endp
-ENDIF
-
-
-IFDEF NOUNDERLINE
-cpudetect32     proc near
-ELSE
-_cpudetect32    proc near
-ENDIF
-
-       push    ebx
-
-       pushfd                  ; push original EFLAGS
-       pop     eax             ; get original EFLAGS
-       mov     ecx, eax        ; save original EFLAGS
-       xor     eax, 40000h     ; flip AC bit in EFLAGS
-       push    eax             ; save new EFLAGS value on stack
-       popfd                   ; replace current EFLAGS value
-       pushfd                  ; get new EFLAGS
-       pop     eax             ; store new EFLAGS in EAX
-       xor     eax, ecx        ; can\92t toggle AC bit, processor=80386
-       jz      end_cpu_is_386  ; jump if 80386 processor
-       push    ecx
-       popfd                   ; restore AC bit in EFLAGS first
-
-       pushfd
-       pushfd
-       pop     ecx
-
-       mov     eax, ecx        ; get original EFLAGS
-       xor     eax, 200000h    ; flip ID bit in EFLAGS
-       push    eax             ; save new EFLAGS value on stack
-       popfd                   ; replace current EFLAGS value
-       pushfd                  ; get new EFLAGS
-       pop             eax                 ; store new EFLAGS in EAX
-       popfd                   ; restore original EFLAGS
-       xor             eax, ecx        ; can\92t toggle ID bit,
-       je              is_old_486              ; processor=old
-
-       mov     eax,1
-       db      0fh,0a2h        ;CPUID
-
-exitcpudetect:
-       pop     ebx
-       ret
-
-end_cpu_is_386:
-       mov     eax,0300h
-       jmp     exitcpudetect
-
-is_old_486:
-       mov     eax,0400h
-       jmp     exitcpudetect
-
-IFDEF NOUNDERLINE
-cpudetect32     endp
-ELSE
-_cpudetect32    endp
-ENDIF
-
-
-
-
-MAX_MATCH       equ     258
-MIN_MATCH       equ     3
-MIN_LOOKAHEAD   equ     (MAX_MATCH + MIN_MATCH + 1)
-MAX_MATCH_8_     equ     ((MAX_MATCH + 7) AND 0FFF0h)
-
-
-;;; stack frame offsets
-
-chainlenwmask  equ  esp + 0    ; high word: current chain len
-                                       ; low word: s->wmask
-window         equ  esp + 4    ; local copy of s->window
-windowbestlen  equ  esp + 8    ; s->window + bestlen
-scanstart      equ  esp + 16   ; first two bytes of string
-scanend                equ  esp + 12   ; last two bytes of string
-scanalign      equ  esp + 20   ; dword-misalignment of string
-nicematch      equ  esp + 24   ; a good enough match size
-bestlen                equ  esp + 28   ; size of best match so far
-scan           equ  esp + 32   ; ptr to string wanting match
-
-LocalVarsSize  equ 36
-;      saved ebx       byte esp + 36
-;      saved edi       byte esp + 40
-;      saved esi       byte esp + 44
-;      saved ebp       byte esp + 48
-;      return address  byte esp + 52
-deflatestate   equ  esp + 56   ; the function arguments
-curmatch       equ  esp + 60
-
-;;; Offsets for fields in the deflate_state structure. These numbers
-;;; are calculated from the definition of deflate_state, with the
-;;; assumption that the compiler will dword-align the fields. (Thus,
-;;; changing the definition of deflate_state could easily cause this
-;;; program to crash horribly, without so much as a warning at
-;;; compile time. Sigh.)
-
-dsWSize                equ 36
-dsWMask                equ 44
-dsWindow       equ 48
-dsPrev         equ 56
-dsMatchLen     equ 88
-dsPrevMatch    equ 92
-dsStrStart     equ 100
-dsMatchStart   equ 104
-dsLookahead    equ 108
-dsPrevLen      equ 112
-dsMaxChainLen  equ 116
-dsGoodMatch    equ 132
-dsNiceMatch    equ 136
-
-
-;;; match.asm -- Pentium-Pro-optimized version of longest_match()
-;;; Written for zlib 1.1.2
-;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
-;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html
-;;;
-;;; This is free software; you can redistribute it and/or modify it
-;;; under the terms of the GNU General Public License.
-
-;GLOBAL        _longest_match, _match_init
-
-
-;SECTION       .text
-
-;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
-
-;_longest_match:
-IFDEF NOUNDERLINE
-longest_match_686   proc near
-ELSE
-_longest_match_686  proc near
-ENDIF
-
-
-;;; Save registers that the compiler may be using, and adjust esp to
-;;; make room for our stack frame.
-
-               push    ebp
-               push    edi
-               push    esi
-               push    ebx
-               sub     esp, LocalVarsSize
-
-;;; Retrieve the function arguments. ecx will hold cur_match
-;;; throughout the entire function. edx will hold the pointer to the
-;;; deflate_state structure during the function's setup (before
-;;; entering the main loop.
-
-               mov     edx, [deflatestate]
-               mov     ecx, [curmatch]
-
-;;; uInt wmask = s->w_mask;
-;;; unsigned chain_length = s->max_chain_length;
-;;; if (s->prev_length >= s->good_match) {
-;;;     chain_length >>= 2;
-;;; }
-
-               mov     eax, [edx + dsPrevLen]
-               mov     ebx, [edx + dsGoodMatch]
-               cmp     eax, ebx
-               mov     eax, [edx + dsWMask]
-               mov     ebx, [edx + dsMaxChainLen]
-               jl      LastMatchGood
-               shr     ebx, 2
-LastMatchGood:
-
-;;; chainlen is decremented once beforehand so that the function can
-;;; use the sign flag instead of the zero flag for the exit test.
-;;; It is then shifted into the high word, to make room for the wmask
-;;; value, which it will always accompany.
-
-               dec     ebx
-               shl     ebx, 16
-               or      ebx, eax
-               mov     [chainlenwmask], ebx
-
-;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-
-               mov     eax, [edx + dsNiceMatch]
-               mov     ebx, [edx + dsLookahead]
-               cmp     ebx, eax
-               jl      LookaheadLess
-               mov     ebx, eax
-LookaheadLess: mov     [nicematch], ebx
-
-;;; register Bytef *scan = s->window + s->strstart;
-
-               mov     esi, [edx + dsWindow]
-               mov     [window], esi
-               mov     ebp, [edx + dsStrStart]
-               lea     edi, [esi + ebp]
-               mov     [scan], edi
-
-;;; Determine how many bytes the scan ptr is off from being
-;;; dword-aligned.
-
-               mov     eax, edi
-               neg     eax
-               and     eax, 3
-               mov     [scanalign], eax
-
-;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
-;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;
-
-               mov     eax, [edx + dsWSize]
-               sub     eax, MIN_LOOKAHEAD
-               sub     ebp, eax
-               jg      LimitPositive
-               xor     ebp, ebp
-LimitPositive:
-
-;;; int best_len = s->prev_length;
-
-               mov     eax, [edx + dsPrevLen]
-               mov     [bestlen], eax
-
-;;; Store the sum of s->window + best_len in esi locally, and in esi.
-
-               add     esi, eax
-               mov     [windowbestlen], esi
-
-;;; register ush scan_start = *(ushf*)scan;
-;;; register ush scan_end   = *(ushf*)(scan+best_len-1);
-;;; Posf *prev = s->prev;
-
-               movzx   ebx, word ptr [edi]
-               mov     [scanstart], ebx
-               movzx   ebx, word ptr [edi + eax - 1]
-               mov     [scanend], ebx
-               mov     edi, [edx + dsPrev]
-
-;;; Jump into the main loop.
-
-               mov     edx, [chainlenwmask]
-               jmp     short LoopEntry
-
-align 4
-
-;;; do {
-;;;     match = s->window + cur_match;
-;;;     if (*(ushf*)(match+best_len-1) != scan_end ||
-;;;         *(ushf*)match != scan_start) continue;
-;;;     [...]
-;;; } while ((cur_match = prev[cur_match & wmask]) > limit
-;;;          && --chain_length != 0);
-;;;
-;;; Here is the inner loop of the function. The function will spend the
-;;; majority of its time in this loop, and majority of that time will
-;;; be spent in the first ten instructions.
-;;;
-;;; Within this loop:
-;;; ebx = scanend
-;;; ecx = curmatch
-;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
-;;; esi = windowbestlen - i.e., (window + bestlen)
-;;; edi = prev
-;;; ebp = limit
-
-LookupLoop:
-               and     ecx, edx
-               movzx   ecx, word ptr [edi + ecx*2]
-               cmp     ecx, ebp
-               jbe     LeaveNow
-               sub     edx, 00010000h
-               js      LeaveNow
-LoopEntry:     movzx   eax, word ptr [esi + ecx - 1]
-               cmp     eax, ebx
-               jnz     LookupLoop
-               mov     eax, [window]
-               movzx   eax, word ptr [eax + ecx]
-               cmp     eax, [scanstart]
-               jnz     LookupLoop
-
-;;; Store the current value of chainlen.
-
-               mov     [chainlenwmask], edx
-
-;;; Point edi to the string under scrutiny, and esi to the string we
-;;; are hoping to match it up with. In actuality, esi and edi are
-;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
-;;; initialized to -(MAX_MATCH_8 - scanalign).
-
-               mov     esi, [window]
-               mov     edi, [scan]
-               add     esi, ecx
-               mov     eax, [scanalign]
-               mov     edx, 0fffffef8h; -(MAX_MATCH_8)
-               lea     edi, [edi + eax + 0108h] ;MAX_MATCH_8]
-               lea     esi, [esi + eax + 0108h] ;MAX_MATCH_8]
-
-;;; Test the strings for equality, 8 bytes at a time. At the end,
-;;; adjust edx so that it is offset to the exact byte that mismatched.
-;;;
-;;; We already know at this point that the first three bytes of the
-;;; strings match each other, and they can be safely passed over before
-;;; starting the compare loop. So what this code does is skip over 0-3
-;;; bytes, as much as necessary in order to dword-align the edi
-;;; pointer. (esi will still be misaligned three times out of four.)
-;;;
-;;; It should be confessed that this loop usually does not represent
-;;; much of the total running time. Replacing it with a more
-;;; straightforward "rep cmpsb" would not drastically degrade
-;;; performance.
-
-LoopCmps:
-               mov     eax, [esi + edx]
-               xor     eax, [edi + edx]
-               jnz     LeaveLoopCmps
-               mov     eax, [esi + edx + 4]
-               xor     eax, [edi + edx + 4]
-               jnz     LeaveLoopCmps4
-               add     edx, 8
-               jnz     LoopCmps
-               jmp     short LenMaximum
-LeaveLoopCmps4:        add     edx, 4
-LeaveLoopCmps: test    eax, 0000FFFFh
-               jnz     LenLower
-               add     edx,  2
-               shr     eax, 16
-LenLower:      sub     al, 1
-               adc     edx, 0
-
-;;; Calculate the length of the match. If it is longer than MAX_MATCH,
-;;; then automatically accept it as the best possible match and leave.
-
-               lea     eax, [edi + edx]
-               mov     edi, [scan]
-               sub     eax, edi
-               cmp     eax, MAX_MATCH
-               jge     LenMaximum
-
-;;; If the length of the match is not longer than the best match we
-;;; have so far, then forget it and return to the lookup loop.
-
-               mov     edx, [deflatestate]
-               mov     ebx, [bestlen]
-               cmp     eax, ebx
-               jg      LongerMatch
-               mov     esi, [windowbestlen]
-               mov     edi, [edx + dsPrev]
-               mov     ebx, [scanend]
-               mov     edx, [chainlenwmask]
-               jmp     LookupLoop
-
-;;;         s->match_start = cur_match;
-;;;         best_len = len;
-;;;         if (len >= nice_match) break;
-;;;         scan_end = *(ushf*)(scan+best_len-1);
-
-LongerMatch:   mov     ebx, [nicematch]
-               mov     [bestlen], eax
-               mov     [edx + dsMatchStart], ecx
-               cmp     eax, ebx
-               jge     LeaveNow
-               mov     esi, [window]
-               add     esi, eax
-               mov     [windowbestlen], esi
-               movzx   ebx, word ptr [edi + eax - 1]
-               mov     edi, [edx + dsPrev]
-               mov     [scanend], ebx
-               mov     edx, [chainlenwmask]
-               jmp     LookupLoop
-
-;;; Accept the current string, with the maximum possible length.
-
-LenMaximum:    mov     edx, [deflatestate]
-               mov     dword ptr [bestlen], MAX_MATCH
-               mov     [edx + dsMatchStart], ecx
-
-;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
-;;; return s->lookahead;
-
-LeaveNow:
-               mov     edx, [deflatestate]
-               mov     ebx, [bestlen]
-               mov     eax, [edx + dsLookahead]
-               cmp     ebx, eax
-               jg      LookaheadRet
-               mov     eax, ebx
-LookaheadRet:
-
-;;; Restore the stack and return from whence we came.
-
-               add     esp, LocalVarsSize
-               pop     ebx
-               pop     esi
-               pop     edi
-               pop     ebp
-
-               ret
-; please don't remove this string !
-; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!
-       db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah
-
-IFDEF NOUNDERLINE
-longest_match_686   endp
-ELSE
-_longest_match_686  endp
-ENDIF
-
-_TEXT   ends
-end
+; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86\r
+; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.\r
+; File written by Gilles Vollant, by modifiying the longest_match\r
+;  from Jean-loup Gailly in deflate.c\r
+;\r
+;         http://www.zlib.net\r
+;         http://www.winimage.com/zLibDll\r
+;         http://www.muppetlabs.com/~breadbox/software/assembly.html\r
+;\r
+; For Visual C++ 4.x and higher and ML 6.x and higher\r
+;   ml.exe is in directory \MASM611C of Win95 DDK\r
+;   ml.exe is also distributed in http://www.masm32.com/masmdl.htm\r
+;    and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/\r
+;\r
+; this file contain two implementation of longest_match\r
+;\r
+;  longest_match_7fff : written 1996 by Gilles Vollant optimized for \r
+;            first Pentium. Assume s->w_mask == 0x7fff\r
+;  longest_match_686 : written by Brian raiter (1998), optimized for Pentium Pro\r
+;\r
+;  for using an seembly version of longest_match, you need define ASMV in project\r
+;  There is two way in using gvmat32.asm\r
+;\r
+;  A) Suggested method\r
+;    if you want include both longest_match_7fff and longest_match_686\r
+;    compile the asm file running\r
+;           ml /coff /Zi /Flgvmat32.lst /c gvmat32.asm\r
+;    and include gvmat32c.c in your project\r
+;    if you have an old cpu (386,486 or first Pentium) and s->w_mask==0x7fff,\r
+;        longest_match_7fff will be used\r
+;    if you have a more modern CPU (Pentium Pro, II and higher)\r
+;        longest_match_686 will be used\r
+;    on old cpu with s->w_mask!=0x7fff, longest_match_686 will be used,\r
+;        but this is not a sitation you'll find often\r
+;\r
+;  B) Alternative\r
+;    if you are not interresed in old cpu performance and want the smaller\r
+;       binaries possible\r
+;\r
+;    compile the asm file running\r
+;           ml /coff /Zi /c /Flgvmat32.lst /DNOOLDPENTIUMCODE gvmat32.asm\r
+;    and do not include gvmat32c.c in your project (ou define also \r
+;              NOOLDPENTIUMCODE)\r
+;\r
+; note : as I known, longest_match_686 is very faster than longest_match_7fff\r
+;        on pentium Pro/II/III, faster (but less) in P4, but it seem\r
+;        longest_match_7fff can be faster (very very litte) on AMD Athlon64/K8\r
+;\r
+; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2\r
+\r
+;uInt longest_match_7fff(s, cur_match)\r
+;    deflate_state *s;\r
+;    IPos cur_match;                             /* current match */\r
+\r
+    NbStack         equ     76\r
+    cur_match       equ     dword ptr[esp+NbStack-0]\r
+    str_s           equ     dword ptr[esp+NbStack-4]\r
+; 5 dword on top (ret,ebp,esi,edi,ebx)\r
+    adrret          equ     dword ptr[esp+NbStack-8]\r
+    pushebp         equ     dword ptr[esp+NbStack-12]\r
+    pushedi         equ     dword ptr[esp+NbStack-16]\r
+    pushesi         equ     dword ptr[esp+NbStack-20]\r
+    pushebx         equ     dword ptr[esp+NbStack-24]\r
+\r
+    chain_length    equ     dword ptr [esp+NbStack-28]\r
+    limit           equ     dword ptr [esp+NbStack-32]\r
+    best_len        equ     dword ptr [esp+NbStack-36]\r
+    window          equ     dword ptr [esp+NbStack-40]\r
+    prev            equ     dword ptr [esp+NbStack-44]\r
+    scan_start      equ      word ptr [esp+NbStack-48]\r
+    wmask           equ     dword ptr [esp+NbStack-52]\r
+    match_start_ptr equ     dword ptr [esp+NbStack-56]\r
+    nice_match      equ     dword ptr [esp+NbStack-60]\r
+    scan            equ     dword ptr [esp+NbStack-64]\r
+\r
+    windowlen       equ     dword ptr [esp+NbStack-68]\r
+    match_start     equ     dword ptr [esp+NbStack-72]\r
+    strend          equ     dword ptr [esp+NbStack-76]\r
+    NbStackAdd      equ     (NbStack-24)\r
+\r
+    .386p\r
+\r
+    name    gvmatch\r
+    .MODEL  FLAT\r
+\r
+\r
+\r
+;  all the +zlib1222add offsets are due to the addition of fields\r
+;  in zlib in the deflate_state structure since the asm code was first written\r
+;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").\r
+;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").\r
+;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").\r
+\r
+    zlib1222add         equ     8\r
+\r
+;  Note : these value are good with a 8 bytes boundary pack structure\r
+    dep_chain_length    equ     74h+zlib1222add\r
+    dep_window          equ     30h+zlib1222add\r
+    dep_strstart        equ     64h+zlib1222add\r
+    dep_prev_length     equ     70h+zlib1222add\r
+    dep_nice_match      equ     88h+zlib1222add\r
+    dep_w_size          equ     24h+zlib1222add\r
+    dep_prev            equ     38h+zlib1222add\r
+    dep_w_mask          equ     2ch+zlib1222add\r
+    dep_good_match      equ     84h+zlib1222add\r
+    dep_match_start     equ     68h+zlib1222add\r
+    dep_lookahead       equ     6ch+zlib1222add\r
+\r
+\r
+_TEXT                   segment\r
+\r
+IFDEF NOUNDERLINE\r
+   IFDEF NOOLDPENTIUMCODE\r
+            public  longest_match\r
+            public  match_init\r
+   ELSE            \r
+            public  longest_match_7fff\r
+            public  cpudetect32\r
+            public  longest_match_686\r
+   ENDIF\r
+ELSE\r
+   IFDEF NOOLDPENTIUMCODE\r
+            public  _longest_match\r
+            public  _match_init\r
+   ELSE\r
+            public  _longest_match_7fff\r
+            public  _cpudetect32\r
+            public  _longest_match_686\r
+   ENDIF\r
+ENDIF\r
+\r
+    MAX_MATCH           equ     258\r
+    MIN_MATCH           equ     3\r
+    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)\r
+\r
+\r
+\r
+IFNDEF NOOLDPENTIUMCODE\r
+IFDEF NOUNDERLINE\r
+longest_match_7fff   proc near\r
+ELSE\r
+_longest_match_7fff  proc near\r
+ENDIF\r
+\r
+    mov     edx,[esp+4]\r
+\r
+\r
+\r
+    push    ebp\r
+    push    edi\r
+    push    esi\r
+    push    ebx\r
+\r
+    sub     esp,NbStackAdd\r
+\r
+; initialize or check the variables used in match.asm.\r
+    mov     ebp,edx\r
+\r
+; chain_length = s->max_chain_length\r
+; if (prev_length>=good_match) chain_length >>= 2\r
+    mov     edx,[ebp+dep_chain_length]\r
+    mov     ebx,[ebp+dep_prev_length]\r
+    cmp     [ebp+dep_good_match],ebx\r
+    ja      noshr\r
+    shr     edx,2\r
+noshr:\r
+; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop\r
+    inc     edx\r
+    mov     edi,[ebp+dep_nice_match]\r
+    mov     chain_length,edx\r
+    mov     eax,[ebp+dep_lookahead]\r
+    cmp     eax,edi\r
+; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;\r
+    jae     nolookaheadnicematch\r
+    mov     edi,eax\r
+nolookaheadnicematch:\r
+; best_len = s->prev_length\r
+    mov     best_len,ebx\r
+\r
+; window = s->window\r
+    mov     esi,[ebp+dep_window]\r
+    mov     ecx,[ebp+dep_strstart]\r
+    mov     window,esi\r
+\r
+    mov     nice_match,edi\r
+; scan = window + strstart\r
+    add     esi,ecx\r
+    mov     scan,esi\r
+; dx = *window\r
+    mov     dx,word ptr [esi]\r
+; bx = *(window+best_len-1)\r
+    mov     bx,word ptr [esi+ebx-1]\r
+    add     esi,MAX_MATCH-1\r
+; scan_start = *scan\r
+    mov     scan_start,dx\r
+; strend = scan + MAX_MATCH-1\r
+    mov     strend,esi\r
+; bx = scan_end = *(window+best_len-1)\r
+\r
+;    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?\r
+;        s->strstart - (IPos)MAX_DIST(s) : NIL;\r
+\r
+    mov     esi,[ebp+dep_w_size]\r
+    sub     esi,MIN_LOOKAHEAD\r
+; here esi = MAX_DIST(s)\r
+    sub     ecx,esi\r
+    ja      nodist\r
+    xor     ecx,ecx\r
+nodist:\r
+    mov     limit,ecx\r
+\r
+; prev = s->prev\r
+    mov     edx,[ebp+dep_prev]\r
+    mov     prev,edx\r
+\r
+;\r
+    mov     edx,dword ptr [ebp+dep_match_start]\r
+    mov     bp,scan_start\r
+    mov     eax,cur_match\r
+    mov     match_start,edx\r
+\r
+    mov     edx,window\r
+    mov     edi,edx\r
+    add     edi,best_len\r
+    mov     esi,prev\r
+    dec     edi\r
+; windowlen = window + best_len -1\r
+    mov     windowlen,edi\r
+\r
+    jmp     beginloop2\r
+    align   4\r
+\r
+; here, in the loop\r
+;       eax = ax = cur_match\r
+;       ecx = limit\r
+;        bx = scan_end\r
+;        bp = scan_start\r
+;       edi = windowlen (window + best_len -1)\r
+;       esi = prev\r
+\r
+\r
+;// here; chain_length <=16\r
+normalbeg0add16:\r
+    add     chain_length,16\r
+    jz      exitloop\r
+normalbeg0:\r
+    cmp     word ptr[edi+eax],bx\r
+    je      normalbeg2noroll\r
+rcontlabnoroll:\r
+; cur_match = prev[cur_match & wmask]\r
+    and     eax,7fffh\r
+    mov     ax,word ptr[esi+eax*2]\r
+; if cur_match > limit, go to exitloop\r
+    cmp     ecx,eax\r
+    jnb     exitloop\r
+; if --chain_length != 0, go to exitloop\r
+    dec     chain_length\r
+    jnz     normalbeg0\r
+    jmp     exitloop\r
+\r
+normalbeg2noroll:\r
+; if (scan_start==*(cur_match+window)) goto normalbeg2\r
+    cmp     bp,word ptr[edx+eax]\r
+    jne     rcontlabnoroll\r
+    jmp     normalbeg2\r
+\r
+contloop3:\r
+    mov     edi,windowlen\r
+\r
+; cur_match = prev[cur_match & wmask]\r
+    and     eax,7fffh\r
+    mov     ax,word ptr[esi+eax*2]\r
+; if cur_match > limit, go to exitloop\r
+    cmp     ecx,eax\r
+jnbexitloopshort1:\r
+    jnb     exitloop\r
+; if --chain_length != 0, go to exitloop\r
+\r
+\r
+; begin the main loop\r
+beginloop2:\r
+    sub     chain_length,16+1\r
+; if chain_length <=16, don't use the unrolled loop\r
+    jna     normalbeg0add16\r
+\r
+do16:\r
+    cmp     word ptr[edi+eax],bx\r
+    je      normalbeg2dc0\r
+\r
+maccn   MACRO   lab\r
+    and     eax,7fffh\r
+    mov     ax,word ptr[esi+eax*2]\r
+    cmp     ecx,eax\r
+    jnb     exitloop\r
+    cmp     word ptr[edi+eax],bx\r
+    je      lab\r
+    ENDM\r
+\r
+rcontloop0:\r
+    maccn   normalbeg2dc1\r
+\r
+rcontloop1:\r
+    maccn   normalbeg2dc2\r
+\r
+rcontloop2:\r
+    maccn   normalbeg2dc3\r
+\r
+rcontloop3:\r
+    maccn   normalbeg2dc4\r
+\r
+rcontloop4:\r
+    maccn   normalbeg2dc5\r
+\r
+rcontloop5:\r
+    maccn   normalbeg2dc6\r
+\r
+rcontloop6:\r
+    maccn   normalbeg2dc7\r
+\r
+rcontloop7:\r
+    maccn   normalbeg2dc8\r
+\r
+rcontloop8:\r
+    maccn   normalbeg2dc9\r
+\r
+rcontloop9:\r
+    maccn   normalbeg2dc10\r
+\r
+rcontloop10:\r
+    maccn   short normalbeg2dc11\r
+\r
+rcontloop11:\r
+    maccn   short normalbeg2dc12\r
+\r
+rcontloop12:\r
+    maccn   short normalbeg2dc13\r
+\r
+rcontloop13:\r
+    maccn   short normalbeg2dc14\r
+\r
+rcontloop14:\r
+    maccn   short normalbeg2dc15\r
+\r
+rcontloop15:\r
+    and     eax,7fffh\r
+    mov     ax,word ptr[esi+eax*2]\r
+    cmp     ecx,eax\r
+    jnb     exitloop\r
+\r
+    sub     chain_length,16\r
+    ja      do16\r
+    jmp     normalbeg0add16\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+normbeg MACRO   rcontlab,valsub\r
+; if we are here, we know that *(match+best_len-1) == scan_end\r
+    cmp     bp,word ptr[edx+eax]\r
+; if (match != scan_start) goto rcontlab\r
+    jne     rcontlab\r
+; calculate the good chain_length, and we'll compare scan and match string\r
+    add     chain_length,16-valsub\r
+    jmp     iseq\r
+    ENDM\r
+\r
+\r
+normalbeg2dc11:\r
+    normbeg rcontloop11,11\r
+\r
+normalbeg2dc12:\r
+    normbeg short rcontloop12,12\r
+\r
+normalbeg2dc13:\r
+    normbeg short rcontloop13,13\r
+\r
+normalbeg2dc14:\r
+    normbeg short rcontloop14,14\r
+\r
+normalbeg2dc15:\r
+    normbeg short rcontloop15,15\r
+\r
+normalbeg2dc10:\r
+    normbeg rcontloop10,10\r
+\r
+normalbeg2dc9:\r
+    normbeg rcontloop9,9\r
+\r
+normalbeg2dc8:\r
+    normbeg rcontloop8,8\r
+\r
+normalbeg2dc7:\r
+    normbeg rcontloop7,7\r
+\r
+normalbeg2dc6:\r
+    normbeg rcontloop6,6\r
+\r
+normalbeg2dc5:\r
+    normbeg rcontloop5,5\r
+\r
+normalbeg2dc4:\r
+    normbeg rcontloop4,4\r
+\r
+normalbeg2dc3:\r
+    normbeg rcontloop3,3\r
+\r
+normalbeg2dc2:\r
+    normbeg rcontloop2,2\r
+\r
+normalbeg2dc1:\r
+    normbeg rcontloop1,1\r
+\r
+normalbeg2dc0:\r
+    normbeg rcontloop0,0\r
+\r
+\r
+; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end\r
+\r
+normalbeg2:\r
+    mov     edi,window\r
+\r
+    cmp     bp,word ptr[edi+eax]\r
+    jne     contloop3                   ; if *(ushf*)match != scan_start, continue\r
+\r
+iseq:\r
+; if we are here, we know that *(match+best_len-1) == scan_end\r
+; and (match == scan_start)\r
+\r
+    mov     edi,edx\r
+    mov     esi,scan                    ; esi = scan\r
+    add     edi,eax                     ; edi = window + cur_match = match\r
+\r
+    mov     edx,[esi+3]                 ; compare manually dword at match+3\r
+    xor     edx,[edi+3]                 ; and scan +3\r
+\r
+    jz      begincompare                ; if equal, go to long compare\r
+\r
+; we will determine the unmatch byte and calculate len (in esi)\r
+    or      dl,dl\r
+    je      eq1rr\r
+    mov     esi,3\r
+    jmp     trfinval\r
+eq1rr:\r
+    or      dx,dx\r
+    je      eq1\r
+\r
+    mov     esi,4\r
+    jmp     trfinval\r
+eq1:\r
+    and     edx,0ffffffh\r
+    jz      eq11\r
+    mov     esi,5\r
+    jmp     trfinval\r
+eq11:\r
+    mov     esi,6\r
+    jmp     trfinval\r
+\r
+begincompare:\r
+    ; here we now scan and match begin same\r
+    add     edi,6\r
+    add     esi,6\r
+    mov     ecx,(MAX_MATCH-(2+4))/4     ; scan for at most MAX_MATCH bytes\r
+    repe    cmpsd                       ; loop until mismatch\r
+\r
+    je      trfin                       ; go to trfin if not unmatch\r
+; we determine the unmatch byte\r
+    sub     esi,4\r
+    mov     edx,[edi-4]\r
+    xor     edx,[esi]\r
+\r
+    or      dl,dl\r
+    jnz     trfin\r
+    inc     esi\r
+\r
+    or      dx,dx\r
+    jnz     trfin\r
+    inc     esi\r
+\r
+    and     edx,0ffffffh\r
+    jnz     trfin\r
+    inc     esi\r
+\r
+trfin:\r
+    sub     esi,scan          ; esi = len\r
+trfinval:\r
+; here we have finised compare, and esi contain len of equal string\r
+    cmp     esi,best_len        ; if len > best_len, go newbestlen\r
+    ja      short newbestlen\r
+; now we restore edx, ecx and esi, for the big loop\r
+    mov     esi,prev\r
+    mov     ecx,limit\r
+    mov     edx,window\r
+    jmp     contloop3\r
+\r
+newbestlen:\r
+    mov     best_len,esi        ; len become best_len\r
+\r
+    mov     match_start,eax     ; save new position as match_start\r
+    cmp     esi,nice_match      ; if best_len >= nice_match, exit\r
+    jae     exitloop\r
+    mov     ecx,scan\r
+    mov     edx,window          ; restore edx=window\r
+    add     ecx,esi\r
+    add     esi,edx\r
+\r
+    dec     esi\r
+    mov     windowlen,esi       ; windowlen = window + best_len-1\r
+    mov     bx,[ecx-1]          ; bx = *(scan+best_len-1) = scan_end\r
+\r
+; now we restore ecx and esi, for the big loop :\r
+    mov     esi,prev\r
+    mov     ecx,limit\r
+    jmp     contloop3\r
+\r
+exitloop:\r
+; exit : s->match_start=match_start\r
+    mov     ebx,match_start\r
+    mov     ebp,str_s\r
+    mov     ecx,best_len\r
+    mov     dword ptr [ebp+dep_match_start],ebx\r
+    mov     eax,dword ptr [ebp+dep_lookahead]\r
+    cmp     ecx,eax\r
+    ja      minexlo\r
+    mov     eax,ecx\r
+minexlo:\r
+; return min(best_len,s->lookahead)\r
+\r
+; restore stack and register ebx,esi,edi,ebp\r
+    add     esp,NbStackAdd\r
+\r
+    pop     ebx\r
+    pop     esi\r
+    pop     edi\r
+    pop     ebp\r
+    ret\r
+InfoAuthor:\r
+; please don't remove this string !\r
+; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!\r
+    db     0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah\r
+\r
+\r
+\r
+IFDEF NOUNDERLINE\r
+longest_match_7fff   endp\r
+ELSE\r
+_longest_match_7fff  endp\r
+ENDIF\r
+\r
+\r
+IFDEF NOUNDERLINE\r
+cpudetect32     proc near\r
+ELSE\r
+_cpudetect32    proc near\r
+ENDIF\r
+\r
+    push    ebx\r
+\r
+    pushfd                  ; push original EFLAGS\r
+    pop     eax             ; get original EFLAGS\r
+    mov     ecx, eax        ; save original EFLAGS\r
+    xor     eax, 40000h     ; flip AC bit in EFLAGS\r
+    push    eax             ; save new EFLAGS value on stack\r
+    popfd                   ; replace current EFLAGS value\r
+    pushfd                  ; get new EFLAGS\r
+    pop     eax             ; store new EFLAGS in EAX\r
+    xor     eax, ecx        ; can\92t toggle AC bit, processor=80386\r
+    jz      end_cpu_is_386  ; jump if 80386 processor\r
+    push    ecx\r
+    popfd                   ; restore AC bit in EFLAGS first\r
+\r
+    pushfd\r
+    pushfd\r
+    pop     ecx\r
+\r
+    mov     eax, ecx        ; get original EFLAGS\r
+    xor     eax, 200000h    ; flip ID bit in EFLAGS\r
+    push    eax             ; save new EFLAGS value on stack\r
+    popfd                   ; replace current EFLAGS value\r
+    pushfd                  ; get new EFLAGS\r
+    pop     eax             ; store new EFLAGS in EAX\r
+    popfd                   ; restore original EFLAGS\r
+    xor     eax, ecx        ; can\92t toggle ID bit,\r
+    je      is_old_486      ; processor=old\r
+\r
+    mov     eax,1\r
+    db      0fh,0a2h        ;CPUID\r
+\r
+exitcpudetect:\r
+    pop ebx\r
+    ret\r
+\r
+end_cpu_is_386:\r
+    mov     eax,0300h\r
+    jmp     exitcpudetect\r
+\r
+is_old_486:\r
+    mov     eax,0400h\r
+    jmp     exitcpudetect\r
+\r
+IFDEF NOUNDERLINE\r
+cpudetect32     endp\r
+ELSE\r
+_cpudetect32    endp\r
+ENDIF\r
+ENDIF\r
+\r
+MAX_MATCH       equ     258\r
+MIN_MATCH       equ     3\r
+MIN_LOOKAHEAD   equ     (MAX_MATCH + MIN_MATCH + 1)\r
+MAX_MATCH_8_     equ     ((MAX_MATCH + 7) AND 0FFF0h)\r
+\r
+\r
+;;; stack frame offsets\r
+\r
+chainlenwmask   equ  esp + 0    ; high word: current chain len\r
+                    ; low word: s->wmask\r
+window      equ  esp + 4    ; local copy of s->window\r
+windowbestlen   equ  esp + 8    ; s->window + bestlen\r
+scanstart   equ  esp + 16   ; first two bytes of string\r
+scanend     equ  esp + 12   ; last two bytes of string\r
+scanalign   equ  esp + 20   ; dword-misalignment of string\r
+nicematch   equ  esp + 24   ; a good enough match size\r
+bestlen     equ  esp + 28   ; size of best match so far\r
+scan        equ  esp + 32   ; ptr to string wanting match\r
+\r
+LocalVarsSize   equ 36\r
+;   saved ebx   byte esp + 36\r
+;   saved edi   byte esp + 40\r
+;   saved esi   byte esp + 44\r
+;   saved ebp   byte esp + 48\r
+;   return address  byte esp + 52\r
+deflatestate    equ  esp + 56   ; the function arguments\r
+curmatch    equ  esp + 60\r
+\r
+;;; Offsets for fields in the deflate_state structure. These numbers\r
+;;; are calculated from the definition of deflate_state, with the\r
+;;; assumption that the compiler will dword-align the fields. (Thus,\r
+;;; changing the definition of deflate_state could easily cause this\r
+;;; program to crash horribly, without so much as a warning at\r
+;;; compile time. Sigh.)\r
+\r
+dsWSize     equ 36+zlib1222add\r
+dsWMask     equ 44+zlib1222add\r
+dsWindow    equ 48+zlib1222add\r
+dsPrev      equ 56+zlib1222add\r
+dsMatchLen  equ 88+zlib1222add\r
+dsPrevMatch equ 92+zlib1222add\r
+dsStrStart  equ 100+zlib1222add\r
+dsMatchStart    equ 104+zlib1222add\r
+dsLookahead equ 108+zlib1222add\r
+dsPrevLen   equ 112+zlib1222add\r
+dsMaxChainLen   equ 116+zlib1222add\r
+dsGoodMatch equ 132+zlib1222add\r
+dsNiceMatch equ 136+zlib1222add\r
+\r
+\r
+;;; match.asm -- Pentium-Pro-optimized version of longest_match()\r
+;;; Written for zlib 1.1.2\r
+;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>\r
+;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html\r
+;;;\r
+;;; This is free software; you can redistribute it and/or modify it\r
+;;; under the terms of the GNU General Public License.\r
+\r
+;GLOBAL _longest_match, _match_init\r
+\r
+\r
+;SECTION    .text\r
+\r
+;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)\r
+\r
+;_longest_match:\r
+IFDEF NOOLDPENTIUMCODE\r
+    IFDEF NOUNDERLINE\r
+    longest_match       proc near\r
+    ELSE\r
+    _longest_match      proc near\r
+    ENDIF\r
+ELSE\r
+    IFDEF NOUNDERLINE\r
+    longest_match_686   proc near\r
+    ELSE\r
+    _longest_match_686  proc near\r
+    ENDIF\r
+ENDIF\r
+\r
+;;; Save registers that the compiler may be using, and adjust esp to\r
+;;; make room for our stack frame.\r
+\r
+        push    ebp\r
+        push    edi\r
+        push    esi\r
+        push    ebx\r
+        sub esp, LocalVarsSize\r
+\r
+;;; Retrieve the function arguments. ecx will hold cur_match\r
+;;; throughout the entire function. edx will hold the pointer to the\r
+;;; deflate_state structure during the function's setup (before\r
+;;; entering the main loop.\r
+\r
+        mov edx, [deflatestate]\r
+        mov ecx, [curmatch]\r
+\r
+;;; uInt wmask = s->w_mask;\r
+;;; unsigned chain_length = s->max_chain_length;\r
+;;; if (s->prev_length >= s->good_match) {\r
+;;;     chain_length >>= 2;\r
+;;; }\r
+\r
+        mov eax, [edx + dsPrevLen]\r
+        mov ebx, [edx + dsGoodMatch]\r
+        cmp eax, ebx\r
+        mov eax, [edx + dsWMask]\r
+        mov ebx, [edx + dsMaxChainLen]\r
+        jl  LastMatchGood\r
+        shr ebx, 2\r
+LastMatchGood:\r
+\r
+;;; chainlen is decremented once beforehand so that the function can\r
+;;; use the sign flag instead of the zero flag for the exit test.\r
+;;; It is then shifted into the high word, to make room for the wmask\r
+;;; value, which it will always accompany.\r
+\r
+        dec ebx\r
+        shl ebx, 16\r
+        or  ebx, eax\r
+        mov [chainlenwmask], ebx\r
+\r
+;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;\r
+\r
+        mov eax, [edx + dsNiceMatch]\r
+        mov ebx, [edx + dsLookahead]\r
+        cmp ebx, eax\r
+        jl  LookaheadLess\r
+        mov ebx, eax\r
+LookaheadLess:  mov [nicematch], ebx\r
+\r
+;;; register Bytef *scan = s->window + s->strstart;\r
+\r
+        mov esi, [edx + dsWindow]\r
+        mov [window], esi\r
+        mov ebp, [edx + dsStrStart]\r
+        lea edi, [esi + ebp]\r
+        mov [scan], edi\r
+\r
+;;; Determine how many bytes the scan ptr is off from being\r
+;;; dword-aligned.\r
+\r
+        mov eax, edi\r
+        neg eax\r
+        and eax, 3\r
+        mov [scanalign], eax\r
+\r
+;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?\r
+;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;\r
+\r
+        mov eax, [edx + dsWSize]\r
+        sub eax, MIN_LOOKAHEAD\r
+        sub ebp, eax\r
+        jg  LimitPositive\r
+        xor ebp, ebp\r
+LimitPositive:\r
+\r
+;;; int best_len = s->prev_length;\r
+\r
+        mov eax, [edx + dsPrevLen]\r
+        mov [bestlen], eax\r
+\r
+;;; Store the sum of s->window + best_len in esi locally, and in esi.\r
+\r
+        add esi, eax\r
+        mov [windowbestlen], esi\r
+\r
+;;; register ush scan_start = *(ushf*)scan;\r
+;;; register ush scan_end   = *(ushf*)(scan+best_len-1);\r
+;;; Posf *prev = s->prev;\r
+\r
+        movzx   ebx, word ptr [edi]\r
+        mov [scanstart], ebx\r
+        movzx   ebx, word ptr [edi + eax - 1]\r
+        mov [scanend], ebx\r
+        mov edi, [edx + dsPrev]\r
+\r
+;;; Jump into the main loop.\r
+\r
+        mov edx, [chainlenwmask]\r
+        jmp short LoopEntry\r
+\r
+align 4\r
+\r
+;;; do {\r
+;;;     match = s->window + cur_match;\r
+;;;     if (*(ushf*)(match+best_len-1) != scan_end ||\r
+;;;         *(ushf*)match != scan_start) continue;\r
+;;;     [...]\r
+;;; } while ((cur_match = prev[cur_match & wmask]) > limit\r
+;;;          && --chain_length != 0);\r
+;;;\r
+;;; Here is the inner loop of the function. The function will spend the\r
+;;; majority of its time in this loop, and majority of that time will\r
+;;; be spent in the first ten instructions.\r
+;;;\r
+;;; Within this loop:\r
+;;; ebx = scanend\r
+;;; ecx = curmatch\r
+;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)\r
+;;; esi = windowbestlen - i.e., (window + bestlen)\r
+;;; edi = prev\r
+;;; ebp = limit\r
+\r
+LookupLoop:\r
+        and ecx, edx\r
+        movzx   ecx, word ptr [edi + ecx*2]\r
+        cmp ecx, ebp\r
+        jbe LeaveNow\r
+        sub edx, 00010000h\r
+        js  LeaveNow\r
+LoopEntry:  movzx   eax, word ptr [esi + ecx - 1]\r
+        cmp eax, ebx\r
+        jnz LookupLoop\r
+        mov eax, [window]\r
+        movzx   eax, word ptr [eax + ecx]\r
+        cmp eax, [scanstart]\r
+        jnz LookupLoop\r
+\r
+;;; Store the current value of chainlen.\r
+\r
+        mov [chainlenwmask], edx\r
+\r
+;;; Point edi to the string under scrutiny, and esi to the string we\r
+;;; are hoping to match it up with. In actuality, esi and edi are\r
+;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is\r
+;;; initialized to -(MAX_MATCH_8 - scanalign).\r
+\r
+        mov esi, [window]\r
+        mov edi, [scan]\r
+        add esi, ecx\r
+        mov eax, [scanalign]\r
+        mov edx, 0fffffef8h; -(MAX_MATCH_8)\r
+        lea edi, [edi + eax + 0108h] ;MAX_MATCH_8]\r
+        lea esi, [esi + eax + 0108h] ;MAX_MATCH_8]\r
+\r
+;;; Test the strings for equality, 8 bytes at a time. At the end,\r
+;;; adjust edx so that it is offset to the exact byte that mismatched.\r
+;;;\r
+;;; We already know at this point that the first three bytes of the\r
+;;; strings match each other, and they can be safely passed over before\r
+;;; starting the compare loop. So what this code does is skip over 0-3\r
+;;; bytes, as much as necessary in order to dword-align the edi\r
+;;; pointer. (esi will still be misaligned three times out of four.)\r
+;;;\r
+;;; It should be confessed that this loop usually does not represent\r
+;;; much of the total running time. Replacing it with a more\r
+;;; straightforward "rep cmpsb" would not drastically degrade\r
+;;; performance.\r
+\r
+LoopCmps:\r
+        mov eax, [esi + edx]\r
+        xor eax, [edi + edx]\r
+        jnz LeaveLoopCmps\r
+        mov eax, [esi + edx + 4]\r
+        xor eax, [edi + edx + 4]\r
+        jnz LeaveLoopCmps4\r
+        add edx, 8\r
+        jnz LoopCmps\r
+        jmp short LenMaximum\r
+LeaveLoopCmps4: add edx, 4\r
+LeaveLoopCmps:  test    eax, 0000FFFFh\r
+        jnz LenLower\r
+        add edx,  2\r
+        shr eax, 16\r
+LenLower:   sub al, 1\r
+        adc edx, 0\r
+\r
+;;; Calculate the length of the match. If it is longer than MAX_MATCH,\r
+;;; then automatically accept it as the best possible match and leave.\r
+\r
+        lea eax, [edi + edx]\r
+        mov edi, [scan]\r
+        sub eax, edi\r
+        cmp eax, MAX_MATCH\r
+        jge LenMaximum\r
+\r
+;;; If the length of the match is not longer than the best match we\r
+;;; have so far, then forget it and return to the lookup loop.\r
+\r
+        mov edx, [deflatestate]\r
+        mov ebx, [bestlen]\r
+        cmp eax, ebx\r
+        jg  LongerMatch\r
+        mov esi, [windowbestlen]\r
+        mov edi, [edx + dsPrev]\r
+        mov ebx, [scanend]\r
+        mov edx, [chainlenwmask]\r
+        jmp LookupLoop\r
+\r
+;;;         s->match_start = cur_match;\r
+;;;         best_len = len;\r
+;;;         if (len >= nice_match) break;\r
+;;;         scan_end = *(ushf*)(scan+best_len-1);\r
+\r
+LongerMatch:    mov ebx, [nicematch]\r
+        mov [bestlen], eax\r
+        mov [edx + dsMatchStart], ecx\r
+        cmp eax, ebx\r
+        jge LeaveNow\r
+        mov esi, [window]\r
+        add esi, eax\r
+        mov [windowbestlen], esi\r
+        movzx   ebx, word ptr [edi + eax - 1]\r
+        mov edi, [edx + dsPrev]\r
+        mov [scanend], ebx\r
+        mov edx, [chainlenwmask]\r
+        jmp LookupLoop\r
+\r
+;;; Accept the current string, with the maximum possible length.\r
+\r
+LenMaximum: mov edx, [deflatestate]\r
+        mov dword ptr [bestlen], MAX_MATCH\r
+        mov [edx + dsMatchStart], ecx\r
+\r
+;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;\r
+;;; return s->lookahead;\r
+\r
+LeaveNow:\r
+        mov edx, [deflatestate]\r
+        mov ebx, [bestlen]\r
+        mov eax, [edx + dsLookahead]\r
+        cmp ebx, eax\r
+        jg  LookaheadRet\r
+        mov eax, ebx\r
+LookaheadRet:\r
+\r
+;;; Restore the stack and return from whence we came.\r
+\r
+        add esp, LocalVarsSize\r
+        pop ebx\r
+        pop esi\r
+        pop edi\r
+        pop ebp\r
+\r
+        ret\r
+; please don't remove this string !\r
+; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!\r
+    db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah\r
+\r
+\r
+IFDEF NOOLDPENTIUMCODE\r
+    IFDEF NOUNDERLINE\r
+    longest_match       endp\r
+    ELSE\r
+    _longest_match      endp\r
+    ENDIF\r
+\r
+    IFDEF NOUNDERLINE\r
+    match_init      proc near\r
+                    ret\r
+    match_init      endp\r
+    ELSE\r
+    _match_init     proc near\r
+                    ret\r
+    _match_init     endp\r
+    ENDIF    \r
+ELSE\r
+    IFDEF NOUNDERLINE\r
+    longest_match_686   endp\r
+    ELSE\r
+    _longest_match_686  endp\r
+    ENDIF\r
+ENDIF\r
+\r
+_TEXT   ends\r
+end\r
index 9ed25f3..7ad2b27 100644 (file)
-/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86
- * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
- * File written by Gilles Vollant, by modifiying the longest_match
- *  from Jean-loup Gailly in deflate.c
- *  it prepare all parameters and call the assembly longest_match_gvasm
- *  longest_match execute standard C code is wmask != 0x7fff
- *     (assembly code is faster with a fixed wmask)
- *
- */
-
-#include "deflate.h"
-
-#ifdef ASMV
-#define NIL 0
-
-#define UNALIGNED_OK
-
-
-/* if your C compiler don't add underline before function name,
-        define ADD_UNDERLINE_ASMFUNC */
-#ifdef ADD_UNDERLINE_ASMFUNC
-#define longest_match_7fff _longest_match_7fff
-#define longest_match_686  _longest_match_686
-#define cpudetect32        _cpudetect32
-#endif
-
-
-
-void match_init()
-{
-}
-
-unsigned long cpudetect32();
-
-uInt longest_match_c(
-    deflate_state *s,
-    IPos cur_match);                             /* current match */
-
-
-uInt longest_match_7fff(
-    deflate_state *s,
-    IPos cur_match);                             /* current match */
-
-uInt longest_match_686(
-    deflate_state *s,
-    IPos cur_match);                             /* current match */
-
-uInt longest_match(
-    deflate_state *s,
-    IPos cur_match)                             /* current match */
-{
-    static uInt iIsPPro=2;
-
-    if ((s->w_mask == 0x7fff) && (iIsPPro==0))
-        return longest_match_7fff(s,cur_match);
-
-    if (iIsPPro==1)
-        return longest_match_686(s,cur_match);
-
-    if (iIsPPro==2)
-        iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
-
-    return longest_match_c(s,cur_match);
-}
-
-
-
-uInt longest_match_c(s, cur_match)
-    deflate_state *s;
-    IPos cur_match;                             /* current match */
-{
-    unsigned chain_length = s->max_chain_length;/* max hash chain length */
-    register Bytef *scan = s->window + s->strstart; /* current string */
-    register Bytef *match;                       /* matched string */
-    register int len;                           /* length of current match */
-    int best_len = s->prev_length;              /* best match length so far */
-    int nice_match = s->nice_match;             /* stop if match long enough */
-    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
-        s->strstart - (IPos)MAX_DIST(s) : NIL;
-    /* Stop when cur_match becomes <= limit. To simplify the code,
-     * we prevent matches with the string of window index 0.
-     */
-    Posf *prev = s->prev;
-    uInt wmask = s->w_mask;
-
-#ifdef UNALIGNED_OK
-    /* Compare two bytes at a time. Note: this is not always beneficial.
-     * Try with and without -DUNALIGNED_OK to check.
-     */
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
-    register ush scan_start = *(ushf*)scan;
-    register ush scan_end   = *(ushf*)(scan+best_len-1);
-#else
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
-    register Byte scan_end1  = scan[best_len-1];
-    register Byte scan_end   = scan[best_len];
-#endif
-
-    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
-     * It is easy to get rid of this optimization if necessary.
-     */
-    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
-    /* Do not waste too much time if we already have a good match: */
-    if (s->prev_length >= s->good_match) {
-        chain_length >>= 2;
-    }
-    /* Do not look for matches beyond the end of the input. This is necessary
-     * to make deflate deterministic.
-     */
-    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-
-    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
-
-    do {
-        Assert(cur_match < s->strstart, "no future");
-        match = s->window + cur_match;
-
-        /* Skip to next match if the match length cannot increase
-         * or if the match length is less than 2:
-         */
-#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
-        /* This code assumes sizeof(unsigned short) == 2. Do not use
-         * UNALIGNED_OK if your compiler uses a different size.
-         */
-        if (*(ushf*)(match+best_len-1) != scan_end ||
-            *(ushf*)match != scan_start) continue;
-
-        /* It is not necessary to compare scan[2] and match[2] since they are
-         * always equal when the other bytes match, given that the hash keys
-         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
-         * strstart+3, +5, ... up to strstart+257. We check for insufficient
-         * lookahead only every 4th comparison; the 128th check will be made
-         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
-         * necessary to put more guard bytes at the end of the window, or
-         * to check more often for insufficient lookahead.
-         */
-        Assert(scan[2] == match[2], "scan[2]?");
-        scan++, match++;
-        do {
-        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 scan < strend);
-        /* The funny "do {}" generates better code on most compilers */
-
-        /* Here, scan <= window+strstart+257 */
-        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-        if (*scan == *match) scan++;
-
-        len = (MAX_MATCH - 1) - (int)(strend-scan);
-        scan = strend - (MAX_MATCH-1);
-
-#else /* UNALIGNED_OK */
-
-        if (match[best_len]   != scan_end  ||
-            match[best_len-1] != scan_end1 ||
-            *match            != *scan     ||
-            *++match          != scan[1])      continue;
-
-        /* The check at best_len-1 can be removed because it will be made
-         * again later. (This heuristic is not always a win.)
-         * It is not necessary to compare scan[2] and match[2] since they
-         * are always equal when the other bytes match, given that
-         * the hash keys are equal and that HASH_BITS >= 8.
-         */
-        scan += 2, match++;
-        Assert(*scan == *match, "match[2]?");
-
-        /* We check for insufficient lookahead only every 8th comparison;
-         * the 256th check will be made at strstart+258.
-         */
-        do {
-        } while (*++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 scan < strend);
-
-        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-
-        len = MAX_MATCH - (int)(strend - scan);
-        scan = strend - MAX_MATCH;
-
-#endif /* UNALIGNED_OK */
-
-        if (len > best_len) {
-            s->match_start = cur_match;
-            best_len = len;
-            if (len >= nice_match) break;
-#ifdef UNALIGNED_OK
-            scan_end = *(ushf*)(scan+best_len-1);
-#else
-            scan_end1  = scan[best_len-1];
-            scan_end   = scan[best_len];
-#endif
-        }
-    } while ((cur_match = prev[cur_match & wmask]) > limit
-             && --chain_length != 0);
-
-    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
-    return s->lookahead;
-}
-
-#endif /* ASMV */
+/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86\r
+ * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.\r
+ * File written by Gilles Vollant, by modifiying the longest_match\r
+ *  from Jean-loup Gailly in deflate.c\r
+ *  it prepare all parameters and call the assembly longest_match_gvasm\r
+ *  longest_match execute standard C code is wmask != 0x7fff\r
+ *     (assembly code is faster with a fixed wmask)\r
+ *\r
+ * Read comment at beginning of gvmat32.asm for more information\r
+ */\r
+\r
+#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE))\r
+#include "deflate.h"\r
+\r
+/* if your C compiler don't add underline before function name,\r
+        define ADD_UNDERLINE_ASMFUNC */\r
+#ifdef ADD_UNDERLINE_ASMFUNC\r
+#define longest_match_7fff _longest_match_7fff\r
+#define longest_match_686  _longest_match_686\r
+#define cpudetect32        _cpudetect32\r
+#endif\r
+\r
+\r
+unsigned long cpudetect32();\r
+\r
+uInt longest_match_c(\r
+    deflate_state *s,\r
+    IPos cur_match);                             /* current match */\r
+\r
+\r
+uInt longest_match_7fff(\r
+    deflate_state *s,\r
+    IPos cur_match);                             /* current match */\r
+\r
+uInt longest_match_686(\r
+    deflate_state *s,\r
+    IPos cur_match);                             /* current match */\r
+\r
+\r
+static uInt iIsPPro=2;\r
+\r
+void match_init ()\r
+{\r
+    iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;\r
+}\r
+\r
+uInt longest_match(\r
+    deflate_state *s,\r
+    IPos cur_match)                             /* current match */\r
+{\r
+    if (iIsPPro!=0)\r
+        return longest_match_686(s,cur_match);\r
+\r
+    if (s->w_mask != 0x7fff)\r
+        return longest_match_686(s,cur_match);\r
+\r
+    /* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */\r
+        return longest_match_7fff(s,cur_match);\r
+}\r
+\r
+\r
+#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */\r
index 7d76e1c..4a20512 100644 (file)
-; 75 "inffast.S"
-;FILE "inffast.S"
-
-;;;GLOBAL _inflate_fast
-
-;;;SECTION .text
-
-
-
-       .586p
-       .mmx
-
-       name    inflate_fast_x86
-       .MODEL  FLAT
-
-_DATA                  segment
-inflate_fast_use_mmx:
-       dd      1
-
-
-_TEXT                  segment
-PUBLIC _inflate_fast
-
-ALIGN 4
-_inflate_fast:
-       jmp inflate_fast_entry
-
-
-
-ALIGN 4
-       db      'Fast decoding Code from Chris Anderson'
-       db      0
-
-ALIGN 4
-invalid_literal_length_code_msg:
-       db      'invalid literal/length code'
-       db      0
-
-ALIGN 4
-invalid_distance_code_msg:
-       db      'invalid distance code'
-       db      0
-
-ALIGN 4
-invalid_distance_too_far_msg:
-       db      'invalid distance too far back'
-       db      0
-
-
-ALIGN 4
-inflate_fast_mask:
-dd     0
-dd     1
-dd     3
-dd     7
-dd     15
-dd     31
-dd     63
-dd     127
-dd     255
-dd     511
-dd     1023
-dd     2047
-dd     4095
-dd     8191
-dd     16383
-dd     32767
-dd     65535
-dd     131071
-dd     262143
-dd     524287
-dd     1048575
-dd     2097151
-dd     4194303
-dd     8388607
-dd     16777215
-dd     33554431
-dd     67108863
-dd     134217727
-dd     268435455
-dd     536870911
-dd     1073741823
-dd     2147483647
-dd     4294967295
-
-
-
-mode_state      equ    0       ;/* state->mode */
-wsize_state     equ    32      ;/* state->wsize */
-write_state     equ    (36+4)  ;/* state->write */
-window_state    equ    (40+4)  ;/* state->window */
-hold_state      equ    (44+4)  ;/* state->hold */
-bits_state      equ    (48+4)  ;/* state->bits */
-lencode_state   equ    (64+4)  ;/* state->lencode */
-distcode_state  equ    (68+4)  ;/* state->distcode */
-lenbits_state   equ    (72+4)  ;/* state->lenbits */
-distbits_state  equ    (76+4)  ;/* state->distbits */
-
-
-;;SECTION .text
-; 205 "inffast.S"
-;GLOBAL        inflate_fast_use_mmx
-
-;SECTION .data
-
-
-; GLOBAL inflate_fast_use_mmx:object
-;.size inflate_fast_use_mmx, 4
-; 226 "inffast.S"
-;SECTION .text
-
-ALIGN 4
-inflate_fast_entry:
-       push  edi
-       push  esi
-       push  ebp
-       push  ebx
-       pushfd
-       sub  esp,64
-       cld
-
-
-
-
-       mov  esi, [esp+88]
-       mov  edi, [esi+28]
-
-
-
-
-
-
-
-       mov  edx, [esi+4]
-       mov  eax, [esi+0]
-
-       add  edx,eax
-       sub  edx,11
-
-       mov  [esp+44],eax
-       mov  [esp+20],edx
-
-       mov  ebp, [esp+92]
-       mov  ecx, [esi+16]
-       mov  ebx, [esi+12]
-
-       sub  ebp,ecx
-       neg  ebp
-       add  ebp,ebx
-
-       sub  ecx,257
-       add  ecx,ebx
-
-       mov  [esp+60],ebx
-       mov  [esp+40],ebp
-       mov  [esp+16],ecx
-; 285 "inffast.S"
-       mov  eax, [edi+lencode_state]
-       mov  ecx, [edi+distcode_state]
-
-       mov  [esp+8],eax
-       mov  [esp+12],ecx
-
-       mov  eax,1
-       mov  ecx, [edi+lenbits_state]
-       shl  eax,cl
-       dec  eax
-       mov  [esp+0],eax
-
-       mov  eax,1
-       mov  ecx, [edi+distbits_state]
-       shl  eax,cl
-       dec  eax
-       mov  [esp+4],eax
-
-       mov  eax, [edi+wsize_state]
-       mov  ecx, [edi+write_state]
-       mov  edx, [edi+window_state]
-
-       mov  [esp+52],eax
-       mov  [esp+48],ecx
-       mov  [esp+56],edx
-
-       mov  ebp, [edi+hold_state]
-       mov  ebx, [edi+bits_state]
-; 321 "inffast.S"
-       mov  esi, [esp+44]
-       mov  ecx, [esp+20]
-       cmp  ecx,esi
-       ja   L_align_long
-
-       add  ecx,11
-       sub  ecx,esi
-       mov  eax,12
-       sub  eax,ecx
-       lea  edi, [esp+28]
-       rep movsb
-       mov  ecx,eax
-       xor  eax,eax
-       rep stosb
-       lea  esi, [esp+28]
-       mov  [esp+20],esi
-       jmp  L_is_aligned
-
-
-L_align_long:
-       test  esi,3
-       jz   L_is_aligned
-       xor  eax,eax
-       mov  al, [esi]
-       inc  esi
-       mov  ecx,ebx
-       add  ebx,8
-       shl  eax,cl
-       or  ebp,eax
-       jmp L_align_long
-
-L_is_aligned:
-       mov  edi, [esp+60]
-; 366 "inffast.S"
-L_check_mmx:
-       cmp  dword ptr [inflate_fast_use_mmx],2
-       je   L_init_mmx
-       ja   L_do_loop
-
-       push  eax
-       push  ebx
-       push  ecx
-       push  edx
-       pushfd
-       mov  eax, [esp]
-       xor  dword ptr [esp],0200000h
-
-
-
-
-       popfd
-       pushfd
-       pop  edx
-       xor  edx,eax
-       jz   L_dont_use_mmx
-       xor  eax,eax
-       cpuid
-       cmp  ebx,0756e6547h
-       jne  L_dont_use_mmx
-       cmp  ecx,06c65746eh
-       jne  L_dont_use_mmx
-       cmp  edx,049656e69h
-       jne  L_dont_use_mmx
-       mov  eax,1
-       cpuid
-       shr  eax,8
-       and  eax,15
-       cmp  eax,6
-       jne  L_dont_use_mmx
-       test  edx,0800000h
-       jnz  L_use_mmx
-       jmp  L_dont_use_mmx
-L_use_mmx:
-       mov  dword ptr [inflate_fast_use_mmx],2
-       jmp  L_check_mmx_pop
-L_dont_use_mmx:
-       mov  dword ptr [inflate_fast_use_mmx],3
-L_check_mmx_pop:
-       pop  edx
-       pop  ecx
-       pop  ebx
-       pop  eax
-       jmp  L_check_mmx
-; 426 "inffast.S"
-ALIGN 4
-L_do_loop:
-; 437 "inffast.S"
-       cmp  bl,15
-       ja   L_get_length_code
-
-       xor  eax,eax
-       lodsw
-       mov  cl,bl
-       add  bl,16
-       shl  eax,cl
-       or  ebp,eax
-
-L_get_length_code:
-       mov  edx, [esp+0]
-       mov  ecx, [esp+8]
-       and  edx,ebp
-       mov  eax, [ecx+edx*4]
-
-L_dolen:
-
-
-
-
-
-
-       mov  cl,ah
-       sub  bl,ah
-       shr  ebp,cl
-
-
-
-
-
-
-       test  al,al
-       jnz   L_test_for_length_base
-
-       shr  eax,16
-       stosb
-
-L_while_test:
-
-
-       cmp  [esp+16],edi
-       jbe  L_break_loop
-
-       cmp  [esp+20],esi
-       ja   L_do_loop
-       jmp  L_break_loop
-
-L_test_for_length_base:
-; 502 "inffast.S"
-       mov  edx,eax
-       shr  edx,16
-       mov  cl,al
-
-       test  al,16
-       jz   L_test_for_second_level_length
-       and  cl,15
-       jz   L_save_len
-       cmp  bl,cl
-       jae  L_add_bits_to_len
-
-       mov  ch,cl
-       xor  eax,eax
-       lodsw
-       mov  cl,bl
-       add  bl,16
-       shl  eax,cl
-       or  ebp,eax
-       mov  cl,ch
-
-L_add_bits_to_len:
-       mov  eax,1
-       shl  eax,cl
-       dec  eax
-       sub  bl,cl
-       and  eax,ebp
-       shr  ebp,cl
-       add  edx,eax
-
-L_save_len:
-       mov  [esp+24],edx
-
-
-L_decode_distance:
-; 549 "inffast.S"
-       cmp  bl,15
-       ja   L_get_distance_code
-
-       xor  eax,eax
-       lodsw
-       mov  cl,bl
-       add  bl,16
-       shl  eax,cl
-       or  ebp,eax
-
-L_get_distance_code:
-       mov  edx, [esp+4]
-       mov  ecx, [esp+12]
-       and  edx,ebp
-       mov  eax, [ecx+edx*4]
-
-
-L_dodist:
-       mov  edx,eax
-       shr  edx,16
-       mov  cl,ah
-       sub  bl,ah
-       shr  ebp,cl
-; 584 "inffast.S"
-       mov  cl,al
-
-       test  al,16
-       jz  L_test_for_second_level_dist
-       and  cl,15
-       jz  L_check_dist_one
-       cmp  bl,cl
-       jae  L_add_bits_to_dist
-
-       mov  ch,cl
-       xor  eax,eax
-       lodsw
-       mov  cl,bl
-       add  bl,16
-       shl  eax,cl
-       or  ebp,eax
-       mov  cl,ch
-
-L_add_bits_to_dist:
-       mov  eax,1
-       shl  eax,cl
-       dec  eax
-       sub  bl,cl
-       and  eax,ebp
-       shr  ebp,cl
-       add  edx,eax
-       jmp  L_check_window
-
-L_check_window:
-; 625 "inffast.S"
-       mov  [esp+44],esi
-       mov  eax,edi
-       sub  eax, [esp+40]
-
-       cmp  eax,edx
-       jb   L_clip_window
-
-       mov  ecx, [esp+24]
-       mov  esi,edi
-       sub  esi,edx
-
-       sub  ecx,3
-       mov  al, [esi]
-       mov  [edi],al
-       mov  al, [esi+1]
-       mov  dl, [esi+2]
-       add  esi,3
-       mov  [edi+1],al
-       mov  [edi+2],dl
-       add  edi,3
-       rep movsb
-
-       mov  esi, [esp+44]
-       jmp  L_while_test
-
-ALIGN 4
-L_check_dist_one:
-       cmp  edx,1
-       jne  L_check_window
-       cmp  [esp+40],edi
-       je  L_check_window
-
-       dec  edi
-       mov  ecx, [esp+24]
-       mov  al, [edi]
-       sub  ecx,3
-
-       mov  [edi+1],al
-       mov  [edi+2],al
-       mov  [edi+3],al
-       add  edi,4
-       rep stosb
-
-       jmp  L_while_test
-
-ALIGN 4
-L_test_for_second_level_length:
-
-
-
-
-       test  al,64
-       jnz   L_test_for_end_of_block
-
-       mov  eax,1
-       shl  eax,cl
-       dec  eax
-       and  eax,ebp
-       add  eax,edx
-       mov  edx, [esp+8]
-       mov  eax, [edx+eax*4]
-       jmp  L_dolen
-
-ALIGN 4
-L_test_for_second_level_dist:
-
-
-
-
-       test  al,64
-       jnz   L_invalid_distance_code
-
-       mov  eax,1
-       shl  eax,cl
-       dec  eax
-       and  eax,ebp
-       add  eax,edx
-       mov  edx, [esp+12]
-       mov  eax, [edx+eax*4]
-       jmp  L_dodist
-
-ALIGN 4
-L_clip_window:
-; 721 "inffast.S"
-       mov  ecx,eax
-       mov  eax, [esp+52]
-       neg  ecx
-       mov  esi, [esp+56]
-
-       cmp  eax,edx
-       jb   L_invalid_distance_too_far
-
-       add  ecx,edx
-       cmp  dword ptr [esp+48],0
-       jne  L_wrap_around_window
-
-       sub  eax,ecx
-       add  esi,eax
-; 749 "inffast.S"
-       mov  eax, [esp+24]
-       cmp  eax,ecx
-       jbe  L_do_copy1
-
-       sub  eax,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,edx
-       jmp  L_do_copy1
-
-       cmp  eax,ecx
-       jbe  L_do_copy1
-
-       sub  eax,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,edx
-       jmp  L_do_copy1
-
-L_wrap_around_window:
-; 793 "inffast.S"
-       mov  eax, [esp+48]
-       cmp  ecx,eax
-       jbe  L_contiguous_in_window
-
-       add  esi, [esp+52]
-       add  esi,eax
-       sub  esi,ecx
-       sub  ecx,eax
-
-
-       mov  eax, [esp+24]
-       cmp  eax,ecx
-       jbe  L_do_copy1
-
-       sub  eax,ecx
-       rep movsb
-       mov  esi, [esp+56]
-       mov  ecx, [esp+48]
-       cmp  eax,ecx
-       jbe  L_do_copy1
-
-       sub  eax,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,edx
-       jmp  L_do_copy1
-
-L_contiguous_in_window:
-; 836 "inffast.S"
-       add  esi,eax
-       sub  esi,ecx
-
-
-       mov  eax, [esp+24]
-       cmp  eax,ecx
-       jbe  L_do_copy1
-
-       sub  eax,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,edx
-
-L_do_copy1:
-; 862 "inffast.S"
-       mov  ecx,eax
-       rep movsb
-
-       mov  esi, [esp+44]
-       jmp  L_while_test
-; 878 "inffast.S"
-ALIGN 4
-L_init_mmx:
-       emms
-
-
-
-
-
-       movd mm0,ebp
-       mov  ebp,ebx
-; 896 "inffast.S"
-       movd mm4,[esp+0]
-       movq mm3,mm4
-       movd mm5,[esp+4]
-       movq mm2,mm5
-       pxor mm1,mm1
-       mov  ebx, [esp+8]
-       jmp  L_do_loop_mmx
-
-ALIGN 4
-L_do_loop_mmx:
-       psrlq mm0,mm1
-
-       cmp  ebp,32
-       ja  L_get_length_code_mmx
-
-       movd mm6,ebp
-       movd mm7,[esi]
-       add  esi,4
-       psllq mm7,mm6
-       add  ebp,32
-       por mm0,mm7
-
-L_get_length_code_mmx:
-       pand mm4,mm0
-       movd eax,mm4
-       movq mm4,mm3
-       mov  eax, [ebx+eax*4]
-
-L_dolen_mmx:
-       movzx  ecx,ah
-       movd mm1,ecx
-       sub  ebp,ecx
-
-       test  al,al
-       jnz L_test_for_length_base_mmx
-
-       shr  eax,16
-       stosb
-
-L_while_test_mmx:
-
-
-       cmp  [esp+16],edi
-       jbe L_break_loop
-
-       cmp  [esp+20],esi
-       ja L_do_loop_mmx
-       jmp L_break_loop
-
-L_test_for_length_base_mmx:
-
-       mov  edx,eax
-       shr  edx,16
-
-       test  al,16
-       jz  L_test_for_second_level_length_mmx
-       and  eax,15
-       jz L_decode_distance_mmx
-
-       psrlq mm0,mm1
-       movd mm1,eax
-       movd ecx,mm0
-       sub  ebp,eax
-       and  ecx, [inflate_fast_mask+eax*4]
-       add  edx,ecx
-
-L_decode_distance_mmx:
-       psrlq mm0,mm1
-
-       cmp  ebp,32
-       ja L_get_dist_code_mmx
-
-       movd mm6,ebp
-       movd mm7,[esi]
-       add  esi,4
-       psllq mm7,mm6
-       add  ebp,32
-       por mm0,mm7
-
-L_get_dist_code_mmx:
-       mov  ebx, [esp+12]
-       pand mm5,mm0
-       movd eax,mm5
-       movq mm5,mm2
-       mov  eax, [ebx+eax*4]
-
-L_dodist_mmx:
-
-       movzx  ecx,ah
-       mov  ebx,eax
-       shr  ebx,16
-       sub  ebp,ecx
-       movd mm1,ecx
-
-       test  al,16
-       jz L_test_for_second_level_dist_mmx
-       and  eax,15
-       jz L_check_dist_one_mmx
-
-L_add_bits_to_dist_mmx:
-       psrlq mm0,mm1
-       movd mm1,eax
-       movd ecx,mm0
-       sub  ebp,eax
-       and  ecx, [inflate_fast_mask+eax*4]
-       add  ebx,ecx
-
-L_check_window_mmx:
-       mov  [esp+44],esi
-       mov  eax,edi
-       sub  eax, [esp+40]
-
-       cmp  eax,ebx
-       jb L_clip_window_mmx
-
-       mov  ecx,edx
-       mov  esi,edi
-       sub  esi,ebx
-
-       sub  ecx,3
-       mov  al, [esi]
-       mov  [edi],al
-       mov  al, [esi+1]
-       mov  dl, [esi+2]
-       add  esi,3
-       mov  [edi+1],al
-       mov  [edi+2],dl
-       add  edi,3
-       rep movsb
-
-       mov  esi, [esp+44]
-       mov  ebx, [esp+8]
-       jmp  L_while_test_mmx
-
-ALIGN 4
-L_check_dist_one_mmx:
-       cmp  ebx,1
-       jne  L_check_window_mmx
-       cmp  [esp+40],edi
-       je   L_check_window_mmx
-
-       dec  edi
-       mov  ecx,edx
-       mov  al, [edi]
-       sub  ecx,3
-
-       mov  [edi+1],al
-       mov  [edi+2],al
-       mov  [edi+3],al
-       add  edi,4
-       rep stosb
-
-       mov  ebx, [esp+8]
-       jmp  L_while_test_mmx
-
-ALIGN 4
-L_test_for_second_level_length_mmx:
-       test  al,64
-       jnz L_test_for_end_of_block
-
-       and  eax,15
-       psrlq mm0,mm1
-       movd ecx,mm0
-       and  ecx, [inflate_fast_mask+eax*4]
-       add  ecx,edx
-       mov  eax, [ebx+ecx*4]
-       jmp L_dolen_mmx
-
-ALIGN 4
-L_test_for_second_level_dist_mmx:
-       test  al,64
-       jnz L_invalid_distance_code
-
-       and  eax,15
-       psrlq mm0,mm1
-       movd ecx,mm0
-       and  ecx, [inflate_fast_mask+eax*4]
-       mov  eax, [esp+12]
-       add  ecx,ebx
-       mov  eax, [eax+ecx*4]
-       jmp  L_dodist_mmx
-
-ALIGN 4
-L_clip_window_mmx:
-
-       mov  ecx,eax
-       mov  eax, [esp+52]
-       neg  ecx
-       mov  esi, [esp+56]
-
-       cmp  eax,ebx
-       jb  L_invalid_distance_too_far
-
-       add  ecx,ebx
-       cmp  dword ptr [esp+48],0
-       jne  L_wrap_around_window_mmx
-
-       sub  eax,ecx
-       add  esi,eax
-
-       cmp  edx,ecx
-       jbe  L_do_copy1_mmx
-
-       sub  edx,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,ebx
-       jmp  L_do_copy1_mmx
-
-       cmp  edx,ecx
-       jbe  L_do_copy1_mmx
-
-       sub  edx,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,ebx
-       jmp  L_do_copy1_mmx
-
-L_wrap_around_window_mmx:
-
-       mov  eax, [esp+48]
-       cmp  ecx,eax
-       jbe  L_contiguous_in_window_mmx
-
-       add  esi, [esp+52]
-       add  esi,eax
-       sub  esi,ecx
-       sub  ecx,eax
-
-
-       cmp  edx,ecx
-       jbe  L_do_copy1_mmx
-
-       sub  edx,ecx
-       rep movsb
-       mov  esi, [esp+56]
-       mov  ecx, [esp+48]
-       cmp  edx,ecx
-       jbe  L_do_copy1_mmx
-
-       sub  edx,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,ebx
-       jmp  L_do_copy1_mmx
-
-L_contiguous_in_window_mmx:
-
-       add  esi,eax
-       sub  esi,ecx
-
-
-       cmp  edx,ecx
-       jbe  L_do_copy1_mmx
-
-       sub  edx,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,ebx
-
-L_do_copy1_mmx:
-
-
-       mov  ecx,edx
-       rep movsb
-
-       mov  esi, [esp+44]
-       mov  ebx, [esp+8]
-       jmp  L_while_test_mmx
-; 1174 "inffast.S"
-L_invalid_distance_code:
-
-
-
-
-
-       mov  ecx, invalid_distance_code_msg
-       mov  edx,26
-       jmp  L_update_stream_state
-
-L_test_for_end_of_block:
-
-
-
-
-
-       test  al,32
-       jz  L_invalid_literal_length_code
-
-       mov  ecx,0
-       mov  edx,11
-       jmp  L_update_stream_state
-
-L_invalid_literal_length_code:
-
-
-
-
-
-       mov  ecx, invalid_literal_length_code_msg
-       mov  edx,26
-       jmp  L_update_stream_state
-
-L_invalid_distance_too_far:
-
-
-
-       mov  esi, [esp+44]
-       mov  ecx, invalid_distance_too_far_msg
-       mov  edx,26
-       jmp  L_update_stream_state
-
-L_update_stream_state:
-
-       mov  eax, [esp+88]
-       test  ecx,ecx
-       jz  L_skip_msg
-       mov  [eax+24],ecx
-L_skip_msg:
-       mov  eax, [eax+28]
-       mov  [eax+mode_state],edx
-       jmp  L_break_loop
-
-ALIGN 4
-L_break_loop:
-; 1243 "inffast.S"
-       cmp  dword ptr [inflate_fast_use_mmx],2
-       jne  L_update_next_in
-
-
-
-       mov  ebx,ebp
-
-L_update_next_in:
-; 1266 "inffast.S"
-       mov  eax, [esp+88]
-       mov  ecx,ebx
-       mov  edx, [eax+28]
-       shr  ecx,3
-       sub  esi,ecx
-       shl  ecx,3
-       sub  ebx,ecx
-       mov  [eax+12],edi
-       mov  [edx+bits_state],ebx
-       mov  ecx,ebx
-
-       lea  ebx, [esp+28]
-       cmp  [esp+20],ebx
-       jne  L_buf_not_used
-
-       sub  esi,ebx
-       mov  ebx, [eax+0]
-       mov  [esp+20],ebx
-       add  esi,ebx
-       mov  ebx, [eax+4]
-       sub  ebx,11
-       add  [esp+20],ebx
-
-L_buf_not_used:
-       mov  [eax+0],esi
-
-       mov  ebx,1
-       shl  ebx,cl
-       dec  ebx
-
-
-
-
-
-       cmp  dword ptr [inflate_fast_use_mmx],2
-       jne  L_update_hold
-
-
-
-       psrlq mm0,mm1
-       movd ebp,mm0
-
-       emms
-
-L_update_hold:
-
-
-
-       and  ebp,ebx
-       mov  [edx+hold_state],ebp
-
-
-
-
-       mov  ebx, [esp+20]
-       cmp  ebx,esi
-       jbe  L_last_is_smaller
-
-       sub  ebx,esi
-       add  ebx,11
-       mov  [eax+4],ebx
-       jmp  L_fixup_out
-L_last_is_smaller:
-       sub  esi,ebx
-       neg  esi
-       add  esi,11
-       mov  [eax+4],esi
-
-
-
-
-L_fixup_out:
-
-       mov  ebx, [esp+16]
-       cmp  ebx,edi
-       jbe  L_end_is_smaller
-
-       sub  ebx,edi
-       add  ebx,257
-       mov  [eax+16],ebx
-       jmp  L_done
-L_end_is_smaller:
-       sub  edi,ebx
-       neg  edi
-       add  edi,257
-       mov  [eax+16],edi
-
-
-
-
-
-L_done:
-       add  esp,64
-       popfd
-       pop  ebx
-       pop  ebp
-       pop  esi
-       pop  edi
-       ret
-
-
-
-
-_TEXT  ends
-end
+;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding\r
+; *\r
+; * inffas32.asm is derivated from inffas86.c, with translation of assembly code\r
+; *\r
+; * Copyright (C) 1995-2003 Mark Adler\r
+; * For conditions of distribution and use, see copyright notice in zlib.h\r
+; *\r
+; * Copyright (C) 2003 Chris Anderson <christop@charm.net>\r
+; * Please use the copyright conditions above.\r
+; *\r
+; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from\r
+; * the gcc -S output of zlib-1.2.0/inffast.c.  Zlib-1.2.0 is in beta release at\r
+; * the moment.  I have successfully compiled and tested this code with gcc2.96,\r
+; * gcc3.2, icc5.0, msvc6.0.  It is very close to the speed of inffast.S\r
+; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX\r
+; * enabled.  I will attempt to merge the MMX code into this version.  Newer\r
+; * versions of this and inffast.S can be found at\r
+; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/\r
+; * \r
+; * 2005 : modification by Gilles Vollant\r
+; */\r
+; For Visual C++ 4.x and higher and ML 6.x and higher\r
+;   ml.exe is in directory \MASM611C of Win95 DDK\r
+;   ml.exe is also distributed in http://www.masm32.com/masmdl.htm\r
+;    and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/\r
+;\r
+;\r
+;   compile with command line option\r
+;   ml  /coff /Zi /c /Flinffas32.lst inffas32.asm\r
+\r
+;   if you define NO_GZIP (see inflate.h), compile with\r
+;   ml  /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm\r
+\r
+\r
+; zlib122sup is 0 fort zlib 1.2.2.1 and lower\r
+; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head \r
+;        in inflate_state in inflate.h)\r
+zlib1222sup      equ    8\r
+\r
+\r
+IFDEF GUNZIP\r
+  INFLATE_MODE_TYPE    equ 11\r
+  INFLATE_MODE_BAD     equ 26\r
+ELSE\r
+  IFNDEF NO_GUNZIP\r
+    INFLATE_MODE_TYPE    equ 11\r
+    INFLATE_MODE_BAD     equ 26\r
+  ELSE\r
+    INFLATE_MODE_TYPE    equ 3\r
+    INFLATE_MODE_BAD     equ 17\r
+  ENDIF\r
+ENDIF\r
+\r
+\r
+; 75 "inffast.S"\r
+;FILE "inffast.S"\r
+\r
+;;;GLOBAL _inflate_fast\r
+\r
+;;;SECTION .text\r
+\r
+\r
+\r
+       .586p\r
+       .mmx\r
+\r
+       name    inflate_fast_x86\r
+       .MODEL  FLAT\r
+\r
+_DATA                  segment\r
+inflate_fast_use_mmx:\r
+       dd      1\r
+\r
+\r
+_TEXT                  segment\r
+PUBLIC _inflate_fast\r
+\r
+ALIGN 4\r
+_inflate_fast:\r
+       jmp inflate_fast_entry\r
+\r
+\r
+\r
+ALIGN 4\r
+       db      'Fast decoding Code from Chris Anderson'\r
+       db      0\r
+\r
+ALIGN 4\r
+invalid_literal_length_code_msg:\r
+       db      'invalid literal/length code'\r
+       db      0\r
+\r
+ALIGN 4\r
+invalid_distance_code_msg:\r
+       db      'invalid distance code'\r
+       db      0\r
+\r
+ALIGN 4\r
+invalid_distance_too_far_msg:\r
+       db      'invalid distance too far back'\r
+       db      0\r
+\r
+\r
+ALIGN 4\r
+inflate_fast_mask:\r
+dd     0\r
+dd     1\r
+dd     3\r
+dd     7\r
+dd     15\r
+dd     31\r
+dd     63\r
+dd     127\r
+dd     255\r
+dd     511\r
+dd     1023\r
+dd     2047\r
+dd     4095\r
+dd     8191\r
+dd     16383\r
+dd     32767\r
+dd     65535\r
+dd     131071\r
+dd     262143\r
+dd     524287\r
+dd     1048575\r
+dd     2097151\r
+dd     4194303\r
+dd     8388607\r
+dd     16777215\r
+dd     33554431\r
+dd     67108863\r
+dd     134217727\r
+dd     268435455\r
+dd     536870911\r
+dd     1073741823\r
+dd     2147483647\r
+dd     4294967295\r
+\r
+\r
+mode_state      equ    0       ;/* state->mode */\r
+wsize_state     equ    (32+zlib1222sup)        ;/* state->wsize */\r
+write_state     equ    (36+4+zlib1222sup)      ;/* state->write */\r
+window_state    equ    (40+4+zlib1222sup)      ;/* state->window */\r
+hold_state      equ    (44+4+zlib1222sup)      ;/* state->hold */\r
+bits_state      equ    (48+4+zlib1222sup)      ;/* state->bits */\r
+lencode_state   equ    (64+4+zlib1222sup)      ;/* state->lencode */\r
+distcode_state  equ    (68+4+zlib1222sup)      ;/* state->distcode */\r
+lenbits_state   equ    (72+4+zlib1222sup)      ;/* state->lenbits */\r
+distbits_state  equ    (76+4+zlib1222sup)      ;/* state->distbits */\r
+\r
+\r
+;;SECTION .text\r
+; 205 "inffast.S"\r
+;GLOBAL        inflate_fast_use_mmx\r
+\r
+;SECTION .data\r
+\r
+\r
+; GLOBAL inflate_fast_use_mmx:object\r
+;.size inflate_fast_use_mmx, 4\r
+; 226 "inffast.S"\r
+;SECTION .text\r
+\r
+ALIGN 4\r
+inflate_fast_entry:\r
+       push  edi\r
+       push  esi\r
+       push  ebp\r
+       push  ebx\r
+       pushfd\r
+       sub  esp,64\r
+       cld\r
+\r
+\r
+\r
+\r
+       mov  esi, [esp+88]\r
+       mov  edi, [esi+28]\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+       mov  edx, [esi+4]\r
+       mov  eax, [esi+0]\r
+\r
+       add  edx,eax\r
+       sub  edx,11\r
+\r
+       mov  [esp+44],eax\r
+       mov  [esp+20],edx\r
+\r
+       mov  ebp, [esp+92]\r
+       mov  ecx, [esi+16]\r
+       mov  ebx, [esi+12]\r
+\r
+       sub  ebp,ecx\r
+       neg  ebp\r
+       add  ebp,ebx\r
+\r
+       sub  ecx,257\r
+       add  ecx,ebx\r
+\r
+       mov  [esp+60],ebx\r
+       mov  [esp+40],ebp\r
+       mov  [esp+16],ecx\r
+; 285 "inffast.S"\r
+       mov  eax, [edi+lencode_state]\r
+       mov  ecx, [edi+distcode_state]\r
+\r
+       mov  [esp+8],eax\r
+       mov  [esp+12],ecx\r
+\r
+       mov  eax,1\r
+       mov  ecx, [edi+lenbits_state]\r
+       shl  eax,cl\r
+       dec  eax\r
+       mov  [esp+0],eax\r
+\r
+       mov  eax,1\r
+       mov  ecx, [edi+distbits_state]\r
+       shl  eax,cl\r
+       dec  eax\r
+       mov  [esp+4],eax\r
+\r
+       mov  eax, [edi+wsize_state]\r
+       mov  ecx, [edi+write_state]\r
+       mov  edx, [edi+window_state]\r
+\r
+       mov  [esp+52],eax\r
+       mov  [esp+48],ecx\r
+       mov  [esp+56],edx\r
+\r
+       mov  ebp, [edi+hold_state]\r
+       mov  ebx, [edi+bits_state]\r
+; 321 "inffast.S"\r
+       mov  esi, [esp+44]\r
+       mov  ecx, [esp+20]\r
+       cmp  ecx,esi\r
+       ja   L_align_long\r
+\r
+       add  ecx,11\r
+       sub  ecx,esi\r
+       mov  eax,12\r
+       sub  eax,ecx\r
+       lea  edi, [esp+28]\r
+       rep movsb\r
+       mov  ecx,eax\r
+       xor  eax,eax\r
+       rep stosb\r
+       lea  esi, [esp+28]\r
+       mov  [esp+20],esi\r
+       jmp  L_is_aligned\r
+\r
+\r
+L_align_long:\r
+       test  esi,3\r
+       jz   L_is_aligned\r
+       xor  eax,eax\r
+       mov  al, [esi]\r
+       inc  esi\r
+       mov  ecx,ebx\r
+       add  ebx,8\r
+       shl  eax,cl\r
+       or  ebp,eax\r
+       jmp L_align_long\r
+\r
+L_is_aligned:\r
+       mov  edi, [esp+60]\r
+; 366 "inffast.S"\r
+L_check_mmx:\r
+       cmp  dword ptr [inflate_fast_use_mmx],2\r
+       je   L_init_mmx\r
+       ja   L_do_loop\r
+\r
+       push  eax\r
+       push  ebx\r
+       push  ecx\r
+       push  edx\r
+       pushfd\r
+       mov  eax, [esp]\r
+       xor  dword ptr [esp],0200000h\r
+\r
+\r
+\r
+\r
+       popfd\r
+       pushfd\r
+       pop  edx\r
+       xor  edx,eax\r
+       jz   L_dont_use_mmx\r
+       xor  eax,eax\r
+       cpuid\r
+       cmp  ebx,0756e6547h\r
+       jne  L_dont_use_mmx\r
+       cmp  ecx,06c65746eh\r
+       jne  L_dont_use_mmx\r
+       cmp  edx,049656e69h\r
+       jne  L_dont_use_mmx\r
+       mov  eax,1\r
+       cpuid\r
+       shr  eax,8\r
+       and  eax,15\r
+       cmp  eax,6\r
+       jne  L_dont_use_mmx\r
+       test  edx,0800000h\r
+       jnz  L_use_mmx\r
+       jmp  L_dont_use_mmx\r
+L_use_mmx:\r
+       mov  dword ptr [inflate_fast_use_mmx],2\r
+       jmp  L_check_mmx_pop\r
+L_dont_use_mmx:\r
+       mov  dword ptr [inflate_fast_use_mmx],3\r
+L_check_mmx_pop:\r
+       pop  edx\r
+       pop  ecx\r
+       pop  ebx\r
+       pop  eax\r
+       jmp  L_check_mmx\r
+; 426 "inffast.S"\r
+ALIGN 4\r
+L_do_loop:\r
+; 437 "inffast.S"\r
+       cmp  bl,15\r
+       ja   L_get_length_code\r
+\r
+       xor  eax,eax\r
+       lodsw\r
+       mov  cl,bl\r
+       add  bl,16\r
+       shl  eax,cl\r
+       or  ebp,eax\r
+\r
+L_get_length_code:\r
+       mov  edx, [esp+0]\r
+       mov  ecx, [esp+8]\r
+       and  edx,ebp\r
+       mov  eax, [ecx+edx*4]\r
+\r
+L_dolen:\r
+\r
+\r
+\r
+\r
+\r
+\r
+       mov  cl,ah\r
+       sub  bl,ah\r
+       shr  ebp,cl\r
+\r
+\r
+\r
+\r
+\r
+\r
+       test  al,al\r
+       jnz   L_test_for_length_base\r
+\r
+       shr  eax,16\r
+       stosb\r
+\r
+L_while_test:\r
+\r
+\r
+       cmp  [esp+16],edi\r
+       jbe  L_break_loop\r
+\r
+       cmp  [esp+20],esi\r
+       ja   L_do_loop\r
+       jmp  L_break_loop\r
+\r
+L_test_for_length_base:\r
+; 502 "inffast.S"\r
+       mov  edx,eax\r
+       shr  edx,16\r
+       mov  cl,al\r
+\r
+       test  al,16\r
+       jz   L_test_for_second_level_length\r
+       and  cl,15\r
+       jz   L_save_len\r
+       cmp  bl,cl\r
+       jae  L_add_bits_to_len\r
+\r
+       mov  ch,cl\r
+       xor  eax,eax\r
+       lodsw\r
+       mov  cl,bl\r
+       add  bl,16\r
+       shl  eax,cl\r
+       or  ebp,eax\r
+       mov  cl,ch\r
+\r
+L_add_bits_to_len:\r
+       mov  eax,1\r
+       shl  eax,cl\r
+       dec  eax\r
+       sub  bl,cl\r
+       and  eax,ebp\r
+       shr  ebp,cl\r
+       add  edx,eax\r
+\r
+L_save_len:\r
+       mov  [esp+24],edx\r
+\r
+\r
+L_decode_distance:\r
+; 549 "inffast.S"\r
+       cmp  bl,15\r
+       ja   L_get_distance_code\r
+\r
+       xor  eax,eax\r
+       lodsw\r
+       mov  cl,bl\r
+       add  bl,16\r
+       shl  eax,cl\r
+       or  ebp,eax\r
+\r
+L_get_distance_code:\r
+       mov  edx, [esp+4]\r
+       mov  ecx, [esp+12]\r
+       and  edx,ebp\r
+       mov  eax, [ecx+edx*4]\r
+\r
+\r
+L_dodist:\r
+       mov  edx,eax\r
+       shr  edx,16\r
+       mov  cl,ah\r
+       sub  bl,ah\r
+       shr  ebp,cl\r
+; 584 "inffast.S"\r
+       mov  cl,al\r
+\r
+       test  al,16\r
+       jz  L_test_for_second_level_dist\r
+       and  cl,15\r
+       jz  L_check_dist_one\r
+       cmp  bl,cl\r
+       jae  L_add_bits_to_dist\r
+\r
+       mov  ch,cl\r
+       xor  eax,eax\r
+       lodsw\r
+       mov  cl,bl\r
+       add  bl,16\r
+       shl  eax,cl\r
+       or  ebp,eax\r
+       mov  cl,ch\r
+\r
+L_add_bits_to_dist:\r
+       mov  eax,1\r
+       shl  eax,cl\r
+       dec  eax\r
+       sub  bl,cl\r
+       and  eax,ebp\r
+       shr  ebp,cl\r
+       add  edx,eax\r
+       jmp  L_check_window\r
+\r
+L_check_window:\r
+; 625 "inffast.S"\r
+       mov  [esp+44],esi\r
+       mov  eax,edi\r
+       sub  eax, [esp+40]\r
+\r
+       cmp  eax,edx\r
+       jb   L_clip_window\r
+\r
+       mov  ecx, [esp+24]\r
+       mov  esi,edi\r
+       sub  esi,edx\r
+\r
+       sub  ecx,3\r
+       mov  al, [esi]\r
+       mov  [edi],al\r
+       mov  al, [esi+1]\r
+       mov  dl, [esi+2]\r
+       add  esi,3\r
+       mov  [edi+1],al\r
+       mov  [edi+2],dl\r
+       add  edi,3\r
+       rep movsb\r
+\r
+       mov  esi, [esp+44]\r
+       jmp  L_while_test\r
+\r
+ALIGN 4\r
+L_check_dist_one:\r
+       cmp  edx,1\r
+       jne  L_check_window\r
+       cmp  [esp+40],edi\r
+       je  L_check_window\r
+\r
+       dec  edi\r
+       mov  ecx, [esp+24]\r
+       mov  al, [edi]\r
+       sub  ecx,3\r
+\r
+       mov  [edi+1],al\r
+       mov  [edi+2],al\r
+       mov  [edi+3],al\r
+       add  edi,4\r
+       rep stosb\r
+\r
+       jmp  L_while_test\r
+\r
+ALIGN 4\r
+L_test_for_second_level_length:\r
+\r
+\r
+\r
+\r
+       test  al,64\r
+       jnz   L_test_for_end_of_block\r
+\r
+       mov  eax,1\r
+       shl  eax,cl\r
+       dec  eax\r
+       and  eax,ebp\r
+       add  eax,edx\r
+       mov  edx, [esp+8]\r
+       mov  eax, [edx+eax*4]\r
+       jmp  L_dolen\r
+\r
+ALIGN 4\r
+L_test_for_second_level_dist:\r
+\r
+\r
+\r
+\r
+       test  al,64\r
+       jnz   L_invalid_distance_code\r
+\r
+       mov  eax,1\r
+       shl  eax,cl\r
+       dec  eax\r
+       and  eax,ebp\r
+       add  eax,edx\r
+       mov  edx, [esp+12]\r
+       mov  eax, [edx+eax*4]\r
+       jmp  L_dodist\r
+\r
+ALIGN 4\r
+L_clip_window:\r
+; 721 "inffast.S"\r
+       mov  ecx,eax\r
+       mov  eax, [esp+52]\r
+       neg  ecx\r
+       mov  esi, [esp+56]\r
+\r
+       cmp  eax,edx\r
+       jb   L_invalid_distance_too_far\r
+\r
+       add  ecx,edx\r
+       cmp  dword ptr [esp+48],0\r
+       jne  L_wrap_around_window\r
+\r
+       sub  eax,ecx\r
+       add  esi,eax\r
+; 749 "inffast.S"\r
+       mov  eax, [esp+24]\r
+       cmp  eax,ecx\r
+       jbe  L_do_copy1\r
+\r
+       sub  eax,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,edx\r
+       jmp  L_do_copy1\r
+\r
+       cmp  eax,ecx\r
+       jbe  L_do_copy1\r
+\r
+       sub  eax,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,edx\r
+       jmp  L_do_copy1\r
+\r
+L_wrap_around_window:\r
+; 793 "inffast.S"\r
+       mov  eax, [esp+48]\r
+       cmp  ecx,eax\r
+       jbe  L_contiguous_in_window\r
+\r
+       add  esi, [esp+52]\r
+       add  esi,eax\r
+       sub  esi,ecx\r
+       sub  ecx,eax\r
+\r
+\r
+       mov  eax, [esp+24]\r
+       cmp  eax,ecx\r
+       jbe  L_do_copy1\r
+\r
+       sub  eax,ecx\r
+       rep movsb\r
+       mov  esi, [esp+56]\r
+       mov  ecx, [esp+48]\r
+       cmp  eax,ecx\r
+       jbe  L_do_copy1\r
+\r
+       sub  eax,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,edx\r
+       jmp  L_do_copy1\r
+\r
+L_contiguous_in_window:\r
+; 836 "inffast.S"\r
+       add  esi,eax\r
+       sub  esi,ecx\r
+\r
+\r
+       mov  eax, [esp+24]\r
+       cmp  eax,ecx\r
+       jbe  L_do_copy1\r
+\r
+       sub  eax,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,edx\r
+\r
+L_do_copy1:\r
+; 862 "inffast.S"\r
+       mov  ecx,eax\r
+       rep movsb\r
+\r
+       mov  esi, [esp+44]\r
+       jmp  L_while_test\r
+; 878 "inffast.S"\r
+ALIGN 4\r
+L_init_mmx:\r
+       emms\r
+\r
+\r
+\r
+\r
+\r
+       movd mm0,ebp\r
+       mov  ebp,ebx\r
+; 896 "inffast.S"\r
+       movd mm4,[esp+0]\r
+       movq mm3,mm4\r
+       movd mm5,[esp+4]\r
+       movq mm2,mm5\r
+       pxor mm1,mm1\r
+       mov  ebx, [esp+8]\r
+       jmp  L_do_loop_mmx\r
+\r
+ALIGN 4\r
+L_do_loop_mmx:\r
+       psrlq mm0,mm1\r
+\r
+       cmp  ebp,32\r
+       ja  L_get_length_code_mmx\r
+\r
+       movd mm6,ebp\r
+       movd mm7,[esi]\r
+       add  esi,4\r
+       psllq mm7,mm6\r
+       add  ebp,32\r
+       por mm0,mm7\r
+\r
+L_get_length_code_mmx:\r
+       pand mm4,mm0\r
+       movd eax,mm4\r
+       movq mm4,mm3\r
+       mov  eax, [ebx+eax*4]\r
+\r
+L_dolen_mmx:\r
+       movzx  ecx,ah\r
+       movd mm1,ecx\r
+       sub  ebp,ecx\r
+\r
+       test  al,al\r
+       jnz L_test_for_length_base_mmx\r
+\r
+       shr  eax,16\r
+       stosb\r
+\r
+L_while_test_mmx:\r
+\r
+\r
+       cmp  [esp+16],edi\r
+       jbe L_break_loop\r
+\r
+       cmp  [esp+20],esi\r
+       ja L_do_loop_mmx\r
+       jmp L_break_loop\r
+\r
+L_test_for_length_base_mmx:\r
+\r
+       mov  edx,eax\r
+       shr  edx,16\r
+\r
+       test  al,16\r
+       jz  L_test_for_second_level_length_mmx\r
+       and  eax,15\r
+       jz L_decode_distance_mmx\r
+\r
+       psrlq mm0,mm1\r
+       movd mm1,eax\r
+       movd ecx,mm0\r
+       sub  ebp,eax\r
+       and  ecx, [inflate_fast_mask+eax*4]\r
+       add  edx,ecx\r
+\r
+L_decode_distance_mmx:\r
+       psrlq mm0,mm1\r
+\r
+       cmp  ebp,32\r
+       ja L_get_dist_code_mmx\r
+\r
+       movd mm6,ebp\r
+       movd mm7,[esi]\r
+       add  esi,4\r
+       psllq mm7,mm6\r
+       add  ebp,32\r
+       por mm0,mm7\r
+\r
+L_get_dist_code_mmx:\r
+       mov  ebx, [esp+12]\r
+       pand mm5,mm0\r
+       movd eax,mm5\r
+       movq mm5,mm2\r
+       mov  eax, [ebx+eax*4]\r
+\r
+L_dodist_mmx:\r
+\r
+       movzx  ecx,ah\r
+       mov  ebx,eax\r
+       shr  ebx,16\r
+       sub  ebp,ecx\r
+       movd mm1,ecx\r
+\r
+       test  al,16\r
+       jz L_test_for_second_level_dist_mmx\r
+       and  eax,15\r
+       jz L_check_dist_one_mmx\r
+\r
+L_add_bits_to_dist_mmx:\r
+       psrlq mm0,mm1\r
+       movd mm1,eax\r
+       movd ecx,mm0\r
+       sub  ebp,eax\r
+       and  ecx, [inflate_fast_mask+eax*4]\r
+       add  ebx,ecx\r
+\r
+L_check_window_mmx:\r
+       mov  [esp+44],esi\r
+       mov  eax,edi\r
+       sub  eax, [esp+40]\r
+\r
+       cmp  eax,ebx\r
+       jb L_clip_window_mmx\r
+\r
+       mov  ecx,edx\r
+       mov  esi,edi\r
+       sub  esi,ebx\r
+\r
+       sub  ecx,3\r
+       mov  al, [esi]\r
+       mov  [edi],al\r
+       mov  al, [esi+1]\r
+       mov  dl, [esi+2]\r
+       add  esi,3\r
+       mov  [edi+1],al\r
+       mov  [edi+2],dl\r
+       add  edi,3\r
+       rep movsb\r
+\r
+       mov  esi, [esp+44]\r
+       mov  ebx, [esp+8]\r
+       jmp  L_while_test_mmx\r
+\r
+ALIGN 4\r
+L_check_dist_one_mmx:\r
+       cmp  ebx,1\r
+       jne  L_check_window_mmx\r
+       cmp  [esp+40],edi\r
+       je   L_check_window_mmx\r
+\r
+       dec  edi\r
+       mov  ecx,edx\r
+       mov  al, [edi]\r
+       sub  ecx,3\r
+\r
+       mov  [edi+1],al\r
+       mov  [edi+2],al\r
+       mov  [edi+3],al\r
+       add  edi,4\r
+       rep stosb\r
+\r
+       mov  ebx, [esp+8]\r
+       jmp  L_while_test_mmx\r
+\r
+ALIGN 4\r
+L_test_for_second_level_length_mmx:\r
+       test  al,64\r
+       jnz L_test_for_end_of_block\r
+\r
+       and  eax,15\r
+       psrlq mm0,mm1\r
+       movd ecx,mm0\r
+       and  ecx, [inflate_fast_mask+eax*4]\r
+       add  ecx,edx\r
+       mov  eax, [ebx+ecx*4]\r
+       jmp L_dolen_mmx\r
+\r
+ALIGN 4\r
+L_test_for_second_level_dist_mmx:\r
+       test  al,64\r
+       jnz L_invalid_distance_code\r
+\r
+       and  eax,15\r
+       psrlq mm0,mm1\r
+       movd ecx,mm0\r
+       and  ecx, [inflate_fast_mask+eax*4]\r
+       mov  eax, [esp+12]\r
+       add  ecx,ebx\r
+       mov  eax, [eax+ecx*4]\r
+       jmp  L_dodist_mmx\r
+\r
+ALIGN 4\r
+L_clip_window_mmx:\r
+\r
+       mov  ecx,eax\r
+       mov  eax, [esp+52]\r
+       neg  ecx\r
+       mov  esi, [esp+56]\r
+\r
+       cmp  eax,ebx\r
+       jb  L_invalid_distance_too_far\r
+\r
+       add  ecx,ebx\r
+       cmp  dword ptr [esp+48],0\r
+       jne  L_wrap_around_window_mmx\r
+\r
+       sub  eax,ecx\r
+       add  esi,eax\r
+\r
+       cmp  edx,ecx\r
+       jbe  L_do_copy1_mmx\r
+\r
+       sub  edx,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,ebx\r
+       jmp  L_do_copy1_mmx\r
+\r
+       cmp  edx,ecx\r
+       jbe  L_do_copy1_mmx\r
+\r
+       sub  edx,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,ebx\r
+       jmp  L_do_copy1_mmx\r
+\r
+L_wrap_around_window_mmx:\r
+\r
+       mov  eax, [esp+48]\r
+       cmp  ecx,eax\r
+       jbe  L_contiguous_in_window_mmx\r
+\r
+       add  esi, [esp+52]\r
+       add  esi,eax\r
+       sub  esi,ecx\r
+       sub  ecx,eax\r
+\r
+\r
+       cmp  edx,ecx\r
+       jbe  L_do_copy1_mmx\r
+\r
+       sub  edx,ecx\r
+       rep movsb\r
+       mov  esi, [esp+56]\r
+       mov  ecx, [esp+48]\r
+       cmp  edx,ecx\r
+       jbe  L_do_copy1_mmx\r
+\r
+       sub  edx,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,ebx\r
+       jmp  L_do_copy1_mmx\r
+\r
+L_contiguous_in_window_mmx:\r
+\r
+       add  esi,eax\r
+       sub  esi,ecx\r
+\r
+\r
+       cmp  edx,ecx\r
+       jbe  L_do_copy1_mmx\r
+\r
+       sub  edx,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,ebx\r
+\r
+L_do_copy1_mmx:\r
+\r
+\r
+       mov  ecx,edx\r
+       rep movsb\r
+\r
+       mov  esi, [esp+44]\r
+       mov  ebx, [esp+8]\r
+       jmp  L_while_test_mmx\r
+; 1174 "inffast.S"\r
+L_invalid_distance_code:\r
+\r
+\r
+\r
+\r
+\r
+       mov  ecx, invalid_distance_code_msg\r
+       mov  edx,INFLATE_MODE_BAD\r
+       jmp  L_update_stream_state\r
+\r
+L_test_for_end_of_block:\r
+\r
+\r
+\r
+\r
+\r
+       test  al,32\r
+       jz  L_invalid_literal_length_code\r
+\r
+       mov  ecx,0\r
+       mov  edx,INFLATE_MODE_TYPE\r
+       jmp  L_update_stream_state\r
+\r
+L_invalid_literal_length_code:\r
+\r
+\r
+\r
+\r
+\r
+       mov  ecx, invalid_literal_length_code_msg\r
+       mov  edx,INFLATE_MODE_BAD\r
+       jmp  L_update_stream_state\r
+\r
+L_invalid_distance_too_far:\r
+\r
+\r
+\r
+       mov  esi, [esp+44]\r
+       mov  ecx, invalid_distance_too_far_msg\r
+       mov  edx,INFLATE_MODE_BAD\r
+       jmp  L_update_stream_state\r
+\r
+L_update_stream_state:\r
+\r
+       mov  eax, [esp+88]\r
+       test  ecx,ecx\r
+       jz  L_skip_msg\r
+       mov  [eax+24],ecx\r
+L_skip_msg:\r
+       mov  eax, [eax+28]\r
+       mov  [eax+mode_state],edx\r
+       jmp  L_break_loop\r
+\r
+ALIGN 4\r
+L_break_loop:\r
+; 1243 "inffast.S"\r
+       cmp  dword ptr [inflate_fast_use_mmx],2\r
+       jne  L_update_next_in\r
+\r
+\r
+\r
+       mov  ebx,ebp\r
+\r
+L_update_next_in:\r
+; 1266 "inffast.S"\r
+       mov  eax, [esp+88]\r
+       mov  ecx,ebx\r
+       mov  edx, [eax+28]\r
+       shr  ecx,3\r
+       sub  esi,ecx\r
+       shl  ecx,3\r
+       sub  ebx,ecx\r
+       mov  [eax+12],edi\r
+       mov  [edx+bits_state],ebx\r
+       mov  ecx,ebx\r
+\r
+       lea  ebx, [esp+28]\r
+       cmp  [esp+20],ebx\r
+       jne  L_buf_not_used\r
+\r
+       sub  esi,ebx\r
+       mov  ebx, [eax+0]\r
+       mov  [esp+20],ebx\r
+       add  esi,ebx\r
+       mov  ebx, [eax+4]\r
+       sub  ebx,11\r
+       add  [esp+20],ebx\r
+\r
+L_buf_not_used:\r
+       mov  [eax+0],esi\r
+\r
+       mov  ebx,1\r
+       shl  ebx,cl\r
+       dec  ebx\r
+\r
+\r
+\r
+\r
+\r
+       cmp  dword ptr [inflate_fast_use_mmx],2\r
+       jne  L_update_hold\r
+\r
+\r
+\r
+       psrlq mm0,mm1\r
+       movd ebp,mm0\r
+\r
+       emms\r
+\r
+L_update_hold:\r
+\r
+\r
+\r
+       and  ebp,ebx\r
+       mov  [edx+hold_state],ebp\r
+\r
+\r
+\r
+\r
+       mov  ebx, [esp+20]\r
+       cmp  ebx,esi\r
+       jbe  L_last_is_smaller\r
+\r
+       sub  ebx,esi\r
+       add  ebx,11\r
+       mov  [eax+4],ebx\r
+       jmp  L_fixup_out\r
+L_last_is_smaller:\r
+       sub  esi,ebx\r
+       neg  esi\r
+       add  esi,11\r
+       mov  [eax+4],esi\r
+\r
+\r
+\r
+\r
+L_fixup_out:\r
+\r
+       mov  ebx, [esp+16]\r
+       cmp  ebx,edi\r
+       jbe  L_end_is_smaller\r
+\r
+       sub  ebx,edi\r
+       add  ebx,257\r
+       mov  [eax+16],ebx\r
+       jmp  L_done\r
+L_end_is_smaller:\r
+       sub  edi,ebx\r
+       neg  edi\r
+       add  edi,257\r
+       mov  [eax+16],edi\r
+\r
+\r
+\r
+\r
+\r
+L_done:\r
+       add  esp,64\r
+       popfd\r
+       pop  ebx\r
+       pop  ebp\r
+       pop  esi\r
+       pop  edi\r
+       ret\r
+\r
+_TEXT  ends\r
+end\r
index 4be4d16..e62af14 100644 (file)
@@ -1,63 +1,67 @@
-Change in 1.01b (20 may 04)
-- Integrate patch from Debian package (submited by Mark Brown)
-- Add tools mztools from Xavier Roche
-
-Change in 1.01 (8 may 04)
-- fix buffer overrun risk in unzip.c (Xavier Roche)
-- fix a minor buffer insecurity in minizip.c (Mike Whittaker)
-
-Change in 1.00: (10 sept 03)
-- rename to 1.00
-- cosmetic code change
-
-Change in 0.22: (19 May 03)
-- crypting support (unless you define NOCRYPT)
-- append file in existing zipfile
-
-Change in 0.21: (10 Mar 03)
-- bug fixes
-
-Change in 0.17: (27 Jan 02)
-- bug fixes
-
-Change in 0.16: (19 Jan 02)
-- Support of ioapi for virtualize zip file access
-
-Change in 0.15: (19 Mar 98)
-- fix memory leak in minizip.c
-
-Change in 0.14: (10 Mar 98)
-- fix bugs in minizip.c sample for zipping big file
-- fix problem in month in date handling
-- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for
-    comment handling
-
-Change in 0.13: (6 Mar 98)
-- fix bugs in zip.c
-- add real minizip sample
-
-Change in 0.12: (4 Mar 98)
-- add zip.c and zip.h for creates .zip file
-- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly)
-- fix miniunz.c for file without specific record for directory
-
-Change in 0.11: (3 Mar 98)
-- fix bug in unzGetCurrentFileInfo for get extra field and comment
-- enhance miniunz sample, remove the bad unztst.c sample
-
-Change in 0.10: (2 Mar 98)
-- fix bug in unzReadCurrentFile
-- rename unzip* to unz* function and structure
-- remove Windows-like hungary notation variable name
-- modify some structure in unzip.h
-- add somes comment in source
-- remove unzipGetcCurrentFile function
-- replace ZUNZEXPORT by ZEXPORT
-- add unzGetLocalExtrafield for get the local extrafield info
-- add a new sample, miniunz.c
-
-Change in 0.4: (25 Feb 98)
-- suppress the type unzipFileInZip.
-  Only on file in the zipfile can be open at the same time
-- fix somes typo in code
-- added tm_unz structure in unzip_file_info (date/time in readable format)
+Change in 1.01e (12 feb 05)\r
+- Fix in zipOpen2 for globalcomment (Rolf Kalbermatter)\r
+- Fix possible memory leak in unzip.c (Zoran Stevanovic)\r
+\r
+Change in 1.01b (20 may 04)\r
+- Integrate patch from Debian package (submited by Mark Brown)\r
+- Add tools mztools from Xavier Roche\r
+\r
+Change in 1.01 (8 may 04)\r
+- fix buffer overrun risk in unzip.c (Xavier Roche)\r
+- fix a minor buffer insecurity in minizip.c (Mike Whittaker)\r
+\r
+Change in 1.00: (10 sept 03)\r
+- rename to 1.00\r
+- cosmetic code change\r
+\r
+Change in 0.22: (19 May 03)\r
+- crypting support (unless you define NOCRYPT)\r
+- append file in existing zipfile\r
+\r
+Change in 0.21: (10 Mar 03)\r
+- bug fixes\r
+\r
+Change in 0.17: (27 Jan 02)\r
+- bug fixes\r
+\r
+Change in 0.16: (19 Jan 02)\r
+- Support of ioapi for virtualize zip file access\r
+\r
+Change in 0.15: (19 Mar 98)\r
+- fix memory leak in minizip.c\r
+\r
+Change in 0.14: (10 Mar 98)\r
+- fix bugs in minizip.c sample for zipping big file\r
+- fix problem in month in date handling\r
+- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for\r
+    comment handling\r
+\r
+Change in 0.13: (6 Mar 98)\r
+- fix bugs in zip.c\r
+- add real minizip sample\r
+\r
+Change in 0.12: (4 Mar 98)\r
+- add zip.c and zip.h for creates .zip file\r
+- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly)\r
+- fix miniunz.c for file without specific record for directory\r
+\r
+Change in 0.11: (3 Mar 98)\r
+- fix bug in unzGetCurrentFileInfo for get extra field and comment\r
+- enhance miniunz sample, remove the bad unztst.c sample\r
+\r
+Change in 0.10: (2 Mar 98)\r
+- fix bug in unzReadCurrentFile\r
+- rename unzip* to unz* function and structure\r
+- remove Windows-like hungary notation variable name\r
+- modify some structure in unzip.h\r
+- add somes comment in source\r
+- remove unzipGetcCurrentFile function\r
+- replace ZUNZEXPORT by ZEXPORT\r
+- add unzGetLocalExtrafield for get the local extrafield info\r
+- add a new sample, miniunz.c\r
+\r
+Change in 0.4: (25 Feb 98)\r
+- suppress the type unzipFileInZip.\r
+  Only on file in the zipfile can be open at the same time\r
+- fix somes typo in code\r
+- added tm_unz structure in unzip_file_info (date/time in readable format)\r
index 7f8a634..f14a628 100644 (file)
-/* crypt.h -- base code for crypt/uncrypt ZIPfile
-
-
-   Version 1.01, May 8th, 2004
-
-   Copyright (C) 1998-2004 Gilles Vollant
-
-   This code is a modified version of crypting code in Infozip distribution
-
-   The encryption/decryption parts of this source code (as opposed to the
-   non-echoing password parts) were originally written in Europe.  The
-   whole source package can be freely distributed, including from the USA.
-   (Prior to January 2000, re-export from the US was a violation of US law.)
-
-   This encryption code is a direct transcription of the algorithm from
-   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
-   file (appnote.txt) is distributed with the PKZIP program (even in the
-   version without encryption capabilities).
-
-   If you don't need crypting in your application, just define symbols
-   NOCRYPT and NOUNCRYPT.
-
-   This code support the "Traditional PKWARE Encryption".
-
-   The new AES encryption added on Zip format by Winzip (see the page
-   http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
-   Encryption is not supported.
-*/
-
-#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
-
-/***********************************************************************
- * Return the next byte in the pseudo-random sequence
- */
-static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
-{
-    unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an
-                     * unpredictable manner on 16-bit systems; not a problem
-                     * with any known compiler so far, though */
-
-    temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
-    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
-}
-
-/***********************************************************************
- * Update the encryption keys with the next byte of plain text
- */
-static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
-{
-    (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
-    (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
-    (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
-    {
-      register int keyshift = (int)((*(pkeys+1)) >> 24);
-      (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
-    }
-    return c;
-}
-
-
-/***********************************************************************
- * Initialize the encryption keys and the random header according to
- * the given password.
- */
-static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
-{
-    *(pkeys+0) = 305419896L;
-    *(pkeys+1) = 591751049L;
-    *(pkeys+2) = 878082192L;
-    while (*passwd != '\0') {
-        update_keys(pkeys,pcrc_32_tab,(int)*passwd);
-        passwd++;
-    }
-}
-
-#define zdecode(pkeys,pcrc_32_tab,c) \
-    (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
-
-#define zencode(pkeys,pcrc_32_tab,c,t) \
-    (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
-
-#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
-
-#define RAND_HEAD_LEN  12
-   /* "last resort" source for second part of crypt seed pattern */
-#  ifndef ZCR_SEED2
-#    define ZCR_SEED2 3141592654UL     /* use PI as default pattern */
-#  endif
-
-static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
-    const char *passwd;         /* password string */
-    unsigned char *buf;         /* where to write header */
-    int bufSize;
-    unsigned long* pkeys;
-    const unsigned long* pcrc_32_tab;
-    unsigned long crcForCrypting;
-{
-    int n;                       /* index in random header */
-    int t;                       /* temporary */
-    int c;                       /* random byte */
-    unsigned char header[RAND_HEAD_LEN-2]; /* random header */
-    static unsigned calls = 0;   /* ensure different random header each time */
-
-    if (bufSize<RAND_HEAD_LEN)
-      return 0;
-
-    /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
-     * output of rand() to get less predictability, since rand() is
-     * often poorly implemented.
-     */
-    if (++calls == 1)
-    {
-        srand((unsigned)(time(NULL) ^ ZCR_SEED2));
-    }
-    init_keys(passwd, pkeys, pcrc_32_tab);
-    for (n = 0; n < RAND_HEAD_LEN-2; n++)
-    {
-        c = (rand() >> 7) & 0xff;
-        header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
-    }
-    /* Encrypt random header (last two bytes is high word of crc) */
-    init_keys(passwd, pkeys, pcrc_32_tab);
-    for (n = 0; n < RAND_HEAD_LEN-2; n++)
-    {
-        buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
-    }
-    buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
-    buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
-    return n;
-}
-
-#endif
+/* crypt.h -- base code for crypt/uncrypt ZIPfile\r
+\r
+\r
+   Version 1.01e, February 12th, 2005\r
+\r
+   Copyright (C) 1998-2005 Gilles Vollant\r
+\r
+   This code is a modified version of crypting code in Infozip distribution\r
+\r
+   The encryption/decryption parts of this source code (as opposed to the\r
+   non-echoing password parts) were originally written in Europe.  The\r
+   whole source package can be freely distributed, including from the USA.\r
+   (Prior to January 2000, re-export from the US was a violation of US law.)\r
+\r
+   This encryption code is a direct transcription of the algorithm from\r
+   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This\r
+   file (appnote.txt) is distributed with the PKZIP program (even in the\r
+   version without encryption capabilities).\r
+\r
+   If you don't need crypting in your application, just define symbols\r
+   NOCRYPT and NOUNCRYPT.\r
+\r
+   This code support the "Traditional PKWARE Encryption".\r
+\r
+   The new AES encryption added on Zip format by Winzip (see the page\r
+   http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong\r
+   Encryption is not supported.\r
+*/\r
+\r
+#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))\r
+\r
+/***********************************************************************\r
+ * Return the next byte in the pseudo-random sequence\r
+ */\r
+static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)\r
+{\r
+    unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an\r
+                     * unpredictable manner on 16-bit systems; not a problem\r
+                     * with any known compiler so far, though */\r
+\r
+    temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;\r
+    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);\r
+}\r
+\r
+/***********************************************************************\r
+ * Update the encryption keys with the next byte of plain text\r
+ */\r
+static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)\r
+{\r
+    (*(pkeys+0)) = CRC32((*(pkeys+0)), c);\r
+    (*(pkeys+1)) += (*(pkeys+0)) & 0xff;\r
+    (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;\r
+    {\r
+      register int keyshift = (int)((*(pkeys+1)) >> 24);\r
+      (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);\r
+    }\r
+    return c;\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ * Initialize the encryption keys and the random header according to\r
+ * the given password.\r
+ */\r
+static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)\r
+{\r
+    *(pkeys+0) = 305419896L;\r
+    *(pkeys+1) = 591751049L;\r
+    *(pkeys+2) = 878082192L;\r
+    while (*passwd != '\0') {\r
+        update_keys(pkeys,pcrc_32_tab,(int)*passwd);\r
+        passwd++;\r
+    }\r
+}\r
+\r
+#define zdecode(pkeys,pcrc_32_tab,c) \\r
+    (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))\r
+\r
+#define zencode(pkeys,pcrc_32_tab,c,t) \\r
+    (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))\r
+\r
+#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED\r
+\r
+#define RAND_HEAD_LEN  12\r
+   /* "last resort" source for second part of crypt seed pattern */\r
+#  ifndef ZCR_SEED2\r
+#    define ZCR_SEED2 3141592654UL     /* use PI as default pattern */\r
+#  endif\r
+\r
+static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)\r
+    const char *passwd;         /* password string */\r
+    unsigned char *buf;         /* where to write header */\r
+    int bufSize;\r
+    unsigned long* pkeys;\r
+    const unsigned long* pcrc_32_tab;\r
+    unsigned long crcForCrypting;\r
+{\r
+    int n;                       /* index in random header */\r
+    int t;                       /* temporary */\r
+    int c;                       /* random byte */\r
+    unsigned char header[RAND_HEAD_LEN-2]; /* random header */\r
+    static unsigned calls = 0;   /* ensure different random header each time */\r
+\r
+    if (bufSize<RAND_HEAD_LEN)\r
+      return 0;\r
+\r
+    /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the\r
+     * output of rand() to get less predictability, since rand() is\r
+     * often poorly implemented.\r
+     */\r
+    if (++calls == 1)\r
+    {\r
+        srand((unsigned)(time(NULL) ^ ZCR_SEED2));\r
+    }\r
+    init_keys(passwd, pkeys, pcrc_32_tab);\r
+    for (n = 0; n < RAND_HEAD_LEN-2; n++)\r
+    {\r
+        c = (rand() >> 7) & 0xff;\r
+        header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);\r
+    }\r
+    /* Encrypt random header (last two bytes is high word of crc) */\r
+    init_keys(passwd, pkeys, pcrc_32_tab);\r
+    for (n = 0; n < RAND_HEAD_LEN-2; n++)\r
+    {\r
+        buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);\r
+    }\r
+    buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);\r
+    buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);\r
+    return n;\r
+}\r
+\r
+#endif\r
index c9e69f2..7f20c18 100644 (file)
-/* ioapi.c -- IO base function header for compress/uncompress .zip
-   files using zlib + zip or unzip API
-
-   Version 1.01, May 8th, 2004
-
-   Copyright (C) 1998-2004 Gilles Vollant
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "zlib.h"
-#include "ioapi.h"
-
-
-
-/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
-
-#ifndef SEEK_CUR
-#define SEEK_CUR    1
-#endif
-
-#ifndef SEEK_END
-#define SEEK_END    2
-#endif
-
-#ifndef SEEK_SET
-#define SEEK_SET    0
-#endif
-
-voidpf ZCALLBACK fopen_file_func OF((
-   voidpf opaque,
-   const char* filename,
-   int mode));
-
-uLong ZCALLBACK fread_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   void* buf,
-   uLong size));
-
-uLong ZCALLBACK fwrite_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   const void* buf,
-   uLong size));
-
-long ZCALLBACK ftell_file_func OF((
-   voidpf opaque,
-   voidpf stream));
-
-long ZCALLBACK fseek_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   uLong offset,
-   int origin));
-
-int ZCALLBACK fclose_file_func OF((
-   voidpf opaque,
-   voidpf stream));
-
-int ZCALLBACK ferror_file_func OF((
-   voidpf opaque,
-   voidpf stream));
-
-
-voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
-   voidpf opaque;
-   const char* filename;
-   int mode;
-{
-    FILE* file = NULL;
-    const char* mode_fopen = NULL;
-    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
-        mode_fopen = "rb";
-    else
-    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
-        mode_fopen = "r+b";
-    else
-    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
-        mode_fopen = "wb";
-
-    if ((filename!=NULL) && (mode_fopen != NULL))
-        file = fopen(filename, mode_fopen);
-    return file;
-}
-
-
-uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
-   voidpf opaque;
-   voidpf stream;
-   void* buf;
-   uLong size;
-{
-    uLong ret;
-    ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
-    return ret;
-}
-
-
-uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
-   voidpf opaque;
-   voidpf stream;
-   const void* buf;
-   uLong size;
-{
-    uLong ret;
-    ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
-    return ret;
-}
-
-long ZCALLBACK ftell_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
-{
-    long ret;
-    ret = ftell((FILE *)stream);
-    return ret;
-}
-
-long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
-   voidpf opaque;
-   voidpf stream;
-   uLong offset;
-   int origin;
-{
-    int fseek_origin=0;
-    long ret;
-    switch (origin)
-    {
-    case ZLIB_FILEFUNC_SEEK_CUR :
-        fseek_origin = SEEK_CUR;
-        break;
-    case ZLIB_FILEFUNC_SEEK_END :
-        fseek_origin = SEEK_END;
-        break;
-    case ZLIB_FILEFUNC_SEEK_SET :
-        fseek_origin = SEEK_SET;
-        break;
-    default: return -1;
-    }
-    ret = 0;
-    fseek((FILE *)stream, offset, fseek_origin);
-    return ret;
-}
-
-int ZCALLBACK fclose_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
-{
-    int ret;
-    ret = fclose((FILE *)stream);
-    return ret;
-}
-
-int ZCALLBACK ferror_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
-{
-    int ret;
-    ret = ferror((FILE *)stream);
-    return ret;
-}
-
-void fill_fopen_filefunc (pzlib_filefunc_def)
-  zlib_filefunc_def* pzlib_filefunc_def;
-{
-    pzlib_filefunc_def->zopen_file = fopen_file_func;
-    pzlib_filefunc_def->zread_file = fread_file_func;
-    pzlib_filefunc_def->zwrite_file = fwrite_file_func;
-    pzlib_filefunc_def->ztell_file = ftell_file_func;
-    pzlib_filefunc_def->zseek_file = fseek_file_func;
-    pzlib_filefunc_def->zclose_file = fclose_file_func;
-    pzlib_filefunc_def->zerror_file = ferror_file_func;
-    pzlib_filefunc_def->opaque = NULL;
-}
+/* ioapi.c -- IO base function header for compress/uncompress .zip\r
+   files using zlib + zip or unzip API\r
+\r
+   Version 1.01e, February 12th, 2005\r
+\r
+   Copyright (C) 1998-2005 Gilles Vollant\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "zlib.h"\r
+#include "ioapi.h"\r
+\r
+\r
+\r
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */\r
+\r
+#ifndef SEEK_CUR\r
+#define SEEK_CUR    1\r
+#endif\r
+\r
+#ifndef SEEK_END\r
+#define SEEK_END    2\r
+#endif\r
+\r
+#ifndef SEEK_SET\r
+#define SEEK_SET    0\r
+#endif\r
+\r
+voidpf ZCALLBACK fopen_file_func OF((\r
+   voidpf opaque,\r
+   const char* filename,\r
+   int mode));\r
+\r
+uLong ZCALLBACK fread_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream,\r
+   void* buf,\r
+   uLong size));\r
+\r
+uLong ZCALLBACK fwrite_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream,\r
+   const void* buf,\r
+   uLong size));\r
+\r
+long ZCALLBACK ftell_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream));\r
+\r
+long ZCALLBACK fseek_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream,\r
+   uLong offset,\r
+   int origin));\r
+\r
+int ZCALLBACK fclose_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream));\r
+\r
+int ZCALLBACK ferror_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream));\r
+\r
+\r
+voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)\r
+   voidpf opaque;\r
+   const char* filename;\r
+   int mode;\r
+{\r
+    FILE* file = NULL;\r
+    const char* mode_fopen = NULL;\r
+    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)\r
+        mode_fopen = "rb";\r
+    else\r
+    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)\r
+        mode_fopen = "r+b";\r
+    else\r
+    if (mode & ZLIB_FILEFUNC_MODE_CREATE)\r
+        mode_fopen = "wb";\r
+\r
+    if ((filename!=NULL) && (mode_fopen != NULL))\r
+        file = fopen(filename, mode_fopen);\r
+    return file;\r
+}\r
+\r
+\r
+uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+   void* buf;\r
+   uLong size;\r
+{\r
+    uLong ret;\r
+    ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);\r
+    return ret;\r
+}\r
+\r
+\r
+uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+   const void* buf;\r
+   uLong size;\r
+{\r
+    uLong ret;\r
+    ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);\r
+    return ret;\r
+}\r
+\r
+long ZCALLBACK ftell_file_func (opaque, stream)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+{\r
+    long ret;\r
+    ret = ftell((FILE *)stream);\r
+    return ret;\r
+}\r
+\r
+long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+   uLong offset;\r
+   int origin;\r
+{\r
+    int fseek_origin=0;\r
+    long ret;\r
+    switch (origin)\r
+    {\r
+    case ZLIB_FILEFUNC_SEEK_CUR :\r
+        fseek_origin = SEEK_CUR;\r
+        break;\r
+    case ZLIB_FILEFUNC_SEEK_END :\r
+        fseek_origin = SEEK_END;\r
+        break;\r
+    case ZLIB_FILEFUNC_SEEK_SET :\r
+        fseek_origin = SEEK_SET;\r
+        break;\r
+    default: return -1;\r
+    }\r
+    ret = 0;\r
+    fseek((FILE *)stream, offset, fseek_origin);\r
+    return ret;\r
+}\r
+\r
+int ZCALLBACK fclose_file_func (opaque, stream)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+{\r
+    int ret;\r
+    ret = fclose((FILE *)stream);\r
+    return ret;\r
+}\r
+\r
+int ZCALLBACK ferror_file_func (opaque, stream)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+{\r
+    int ret;\r
+    ret = ferror((FILE *)stream);\r
+    return ret;\r
+}\r
+\r
+void fill_fopen_filefunc (pzlib_filefunc_def)\r
+  zlib_filefunc_def* pzlib_filefunc_def;\r
+{\r
+    pzlib_filefunc_def->zopen_file = fopen_file_func;\r
+    pzlib_filefunc_def->zread_file = fread_file_func;\r
+    pzlib_filefunc_def->zwrite_file = fwrite_file_func;\r
+    pzlib_filefunc_def->ztell_file = ftell_file_func;\r
+    pzlib_filefunc_def->zseek_file = fseek_file_func;\r
+    pzlib_filefunc_def->zclose_file = fclose_file_func;\r
+    pzlib_filefunc_def->zerror_file = ferror_file_func;\r
+    pzlib_filefunc_def->opaque = NULL;\r
+}\r
index b761161..e73a3b2 100644 (file)
@@ -1,75 +1,75 @@
-/* ioapi.h -- IO base function header for compress/uncompress .zip
-   files using zlib + zip or unzip API
-
-   Version 1.01, May 8th, 2004
-
-   Copyright (C) 1998-2004 Gilles Vollant
-*/
-
-#ifndef _ZLIBIOAPI_H
-#define _ZLIBIOAPI_H
-
-
-#define ZLIB_FILEFUNC_SEEK_CUR (1)
-#define ZLIB_FILEFUNC_SEEK_END (2)
-#define ZLIB_FILEFUNC_SEEK_SET (0)
-
-#define ZLIB_FILEFUNC_MODE_READ      (1)
-#define ZLIB_FILEFUNC_MODE_WRITE     (2)
-#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
-
-#define ZLIB_FILEFUNC_MODE_EXISTING (4)
-#define ZLIB_FILEFUNC_MODE_CREATE   (8)
-
-
-#ifndef ZCALLBACK
-
-#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
-#define ZCALLBACK CALLBACK
-#else
-#define ZCALLBACK
-#endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
-typedef uLong  (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
-typedef uLong  (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
-typedef long   (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
-typedef long   (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
-typedef int    (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
-typedef int    (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
-
-typedef struct zlib_filefunc_def_s
-{
-    open_file_func      zopen_file;
-    read_file_func      zread_file;
-    write_file_func     zwrite_file;
-    tell_file_func      ztell_file;
-    seek_file_func      zseek_file;
-    close_file_func     zclose_file;
-    testerror_file_func zerror_file;
-    voidpf              opaque;
-} zlib_filefunc_def;
-
-
-
-void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
-
-#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
-#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
-#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
-#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
-#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
-#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
+/* ioapi.h -- IO base function header for compress/uncompress .zip\r
+   files using zlib + zip or unzip API\r
+\r
+   Version 1.01e, February 12th, 2005\r
+\r
+   Copyright (C) 1998-2005 Gilles Vollant\r
+*/\r
+\r
+#ifndef _ZLIBIOAPI_H\r
+#define _ZLIBIOAPI_H\r
+\r
+\r
+#define ZLIB_FILEFUNC_SEEK_CUR (1)\r
+#define ZLIB_FILEFUNC_SEEK_END (2)\r
+#define ZLIB_FILEFUNC_SEEK_SET (0)\r
+\r
+#define ZLIB_FILEFUNC_MODE_READ      (1)\r
+#define ZLIB_FILEFUNC_MODE_WRITE     (2)\r
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)\r
+\r
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)\r
+#define ZLIB_FILEFUNC_MODE_CREATE   (8)\r
+\r
+\r
+#ifndef ZCALLBACK\r
+\r
+#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)\r
+#define ZCALLBACK CALLBACK\r
+#else\r
+#define ZCALLBACK\r
+#endif\r
+#endif\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));\r
+typedef uLong  (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));\r
+typedef uLong  (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));\r
+typedef long   (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));\r
+typedef long   (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));\r
+typedef int    (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));\r
+typedef int    (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));\r
+\r
+typedef struct zlib_filefunc_def_s\r
+{\r
+    open_file_func      zopen_file;\r
+    read_file_func      zread_file;\r
+    write_file_func     zwrite_file;\r
+    tell_file_func      ztell_file;\r
+    seek_file_func      zseek_file;\r
+    close_file_func     zclose_file;\r
+    testerror_file_func zerror_file;\r
+    voidpf              opaque;\r
+} zlib_filefunc_def;\r
+\r
+\r
+\r
+void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));\r
+\r
+#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))\r
+#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))\r
+#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))\r
+#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))\r
+#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))\r
+#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
index 940dc0b..694bc03 100644 (file)
-/* iowin32.c -- IO base function header for compress/uncompress .zip
-   files using zlib + zip or unzip API
-   This IO API version uses the Win32 API (for Microsoft Windows)
-
-   Version 1.01, May 8th, 2004
-
-   Copyright (C) 1998-2004 Gilles Vollant
-*/
-
-#include <stdlib.h>
-
-#include "zlib.h"
-#include "ioapi.h"
-#include "iowin32.h"
-
-#ifndef INVALID_HANDLE_VALUE
-#define INVALID_HANDLE_VALUE (0xFFFFFFFF)
-#endif
-
-#ifndef INVALID_SET_FILE_POINTER
-#define INVALID_SET_FILE_POINTER ((DWORD)-1)
-#endif
-
-voidpf ZCALLBACK win32_open_file_func OF((
-   voidpf opaque,
-   const char* filename,
-   int mode));
-
-uLong ZCALLBACK win32_read_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   void* buf,
-   uLong size));
-
-uLong ZCALLBACK win32_write_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   const void* buf,
-   uLong size));
-
-long ZCALLBACK win32_tell_file_func OF((
-   voidpf opaque,
-   voidpf stream));
-
-long ZCALLBACK win32_seek_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   uLong offset,
-   int origin));
-
-int ZCALLBACK win32_close_file_func OF((
-   voidpf opaque,
-   voidpf stream));
-
-int ZCALLBACK win32_error_file_func OF((
-   voidpf opaque,
-   voidpf stream));
-
-typedef struct
-{
-    HANDLE hf;
-    int error;
-} WIN32FILE_IOWIN;
-
-voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode)
-   voidpf opaque;
-   const char* filename;
-   int mode;
-{
-    const char* mode_fopen = NULL;
-    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
-    HANDLE hFile = 0;
-    voidpf ret=NULL;
-
-    dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0;
-
-    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
-    {
-        dwDesiredAccess = GENERIC_READ;
-        dwCreationDisposition = OPEN_EXISTING;
-        dwShareMode = FILE_SHARE_READ;
-    }
-    else
-    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
-    {
-        dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
-        dwCreationDisposition = OPEN_EXISTING;
-    }
-    else
-    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
-    {
-        dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
-        dwCreationDisposition = CREATE_ALWAYS;
-    }
-
-    if ((filename!=NULL) && (dwDesiredAccess != 0))
-        hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL,
-                      dwCreationDisposition, dwFlagsAndAttributes, NULL);
-
-    if (hFile == INVALID_HANDLE_VALUE)
-        hFile = NULL;
-
-    if (hFile != NULL)
-    {
-        WIN32FILE_IOWIN w32fiow;
-        w32fiow.hf = hFile;
-        w32fiow.error = 0;
-        ret = malloc(sizeof(WIN32FILE_IOWIN));
-        if (ret==NULL)
-            CloseHandle(hFile);
-        else *((WIN32FILE_IOWIN*)ret) = w32fiow;
-    }
-    return ret;
-}
-
-
-uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size)
-   voidpf opaque;
-   voidpf stream;
-   void* buf;
-   uLong size;
-{
-    uLong ret=0;
-    HANDLE hFile = NULL;
-    if (stream!=NULL)
-        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
-    if (hFile != NULL)
-        if (!ReadFile(hFile, buf, size, &ret, NULL))
-        {
-            DWORD dwErr = GetLastError();
-            if (dwErr == ERROR_HANDLE_EOF)
-                dwErr = 0;
-            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
-        }
-
-    return ret;
-}
-
-
-uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size)
-   voidpf opaque;
-   voidpf stream;
-   const void* buf;
-   uLong size;
-{
-    uLong ret=0;
-    HANDLE hFile = NULL;
-    if (stream!=NULL)
-        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
-
-    if (hFile !=NULL)
-        if (!WriteFile(hFile, buf, size, &ret, NULL))
-        {
-            DWORD dwErr = GetLastError();
-            if (dwErr == ERROR_HANDLE_EOF)
-                dwErr = 0;
-            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
-        }
-
-    return ret;
-}
-
-long ZCALLBACK win32_tell_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
-{
-    long ret=-1;
-    HANDLE hFile = NULL;
-    if (stream!=NULL)
-        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
-    if (hFile != NULL)
-    {
-        DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
-        if (dwSet == INVALID_SET_FILE_POINTER)
-        {
-            DWORD dwErr = GetLastError();
-            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
-            ret = -1;
-        }
-        else
-            ret=(long)dwSet;
-    }
-    return ret;
-}
-
-long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)
-   voidpf opaque;
-   voidpf stream;
-   uLong offset;
-   int origin;
-{
-    DWORD dwMoveMethod=0xFFFFFFFF;
-    HANDLE hFile = NULL;
-
-    long ret=-1;
-    if (stream!=NULL)
-        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
-    switch (origin)
-    {
-    case ZLIB_FILEFUNC_SEEK_CUR :
-        dwMoveMethod = FILE_CURRENT;
-        break;
-    case ZLIB_FILEFUNC_SEEK_END :
-        dwMoveMethod = FILE_END;
-        break;
-    case ZLIB_FILEFUNC_SEEK_SET :
-        dwMoveMethod = FILE_BEGIN;
-        break;
-    default: return -1;
-    }
-
-    if (hFile != NULL)
-    {
-        DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod);
-        if (dwSet == INVALID_SET_FILE_POINTER)
-        {
-            DWORD dwErr = GetLastError();
-            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
-            ret = -1;
-        }
-        else
-            ret=0;
-    }
-    return ret;
-}
-
-int ZCALLBACK win32_close_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
-{
-    int ret=-1;
-
-    if (stream!=NULL)
-    {
-        HANDLE hFile;
-        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
-        if (hFile != NULL)
-        {
-            CloseHandle(hFile);
-            ret=0;
-        }
-        free(stream);
-    }
-    return ret;
-}
-
-int ZCALLBACK win32_error_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
-{
-    int ret=-1;
-    if (stream!=NULL)
-    {
-        ret = ((WIN32FILE_IOWIN*)stream) -> error;
-    }
-    return ret;
-}
-
-void fill_win32_filefunc (pzlib_filefunc_def)
-  zlib_filefunc_def* pzlib_filefunc_def;
-{
-    pzlib_filefunc_def->zopen_file = win32_open_file_func;
-    pzlib_filefunc_def->zread_file = win32_read_file_func;
-    pzlib_filefunc_def->zwrite_file = win32_write_file_func;
-    pzlib_filefunc_def->ztell_file = win32_tell_file_func;
-    pzlib_filefunc_def->zseek_file = win32_seek_file_func;
-    pzlib_filefunc_def->zclose_file = win32_close_file_func;
-    pzlib_filefunc_def->zerror_file = win32_error_file_func;
-    pzlib_filefunc_def->opaque=NULL;
-}
+/* iowin32.c -- IO base function header for compress/uncompress .zip\r
+   files using zlib + zip or unzip API\r
+   This IO API version uses the Win32 API (for Microsoft Windows)\r
+\r
+   Version 1.01e, February 12th, 2005\r
+\r
+   Copyright (C) 1998-2005 Gilles Vollant\r
+*/\r
+\r
+#include <stdlib.h>\r
+\r
+#include "zlib.h"\r
+#include "ioapi.h"\r
+#include "iowin32.h"\r
+\r
+#ifndef INVALID_HANDLE_VALUE\r
+#define INVALID_HANDLE_VALUE (0xFFFFFFFF)\r
+#endif\r
+\r
+#ifndef INVALID_SET_FILE_POINTER\r
+#define INVALID_SET_FILE_POINTER ((DWORD)-1)\r
+#endif\r
+\r
+voidpf ZCALLBACK win32_open_file_func OF((\r
+   voidpf opaque,\r
+   const char* filename,\r
+   int mode));\r
+\r
+uLong ZCALLBACK win32_read_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream,\r
+   void* buf,\r
+   uLong size));\r
+\r
+uLong ZCALLBACK win32_write_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream,\r
+   const void* buf,\r
+   uLong size));\r
+\r
+long ZCALLBACK win32_tell_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream));\r
+\r
+long ZCALLBACK win32_seek_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream,\r
+   uLong offset,\r
+   int origin));\r
+\r
+int ZCALLBACK win32_close_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream));\r
+\r
+int ZCALLBACK win32_error_file_func OF((\r
+   voidpf opaque,\r
+   voidpf stream));\r
+\r
+typedef struct\r
+{\r
+    HANDLE hf;\r
+    int error;\r
+} WIN32FILE_IOWIN;\r
+\r
+voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode)\r
+   voidpf opaque;\r
+   const char* filename;\r
+   int mode;\r
+{\r
+    const char* mode_fopen = NULL;\r
+    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;\r
+    HANDLE hFile = 0;\r
+    voidpf ret=NULL;\r
+\r
+    dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0;\r
+\r
+    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)\r
+    {\r
+        dwDesiredAccess = GENERIC_READ;\r
+        dwCreationDisposition = OPEN_EXISTING;\r
+        dwShareMode = FILE_SHARE_READ;\r
+    }\r
+    else\r
+    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)\r
+    {\r
+        dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;\r
+        dwCreationDisposition = OPEN_EXISTING;\r
+    }\r
+    else\r
+    if (mode & ZLIB_FILEFUNC_MODE_CREATE)\r
+    {\r
+        dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;\r
+        dwCreationDisposition = CREATE_ALWAYS;\r
+    }\r
+\r
+    if ((filename!=NULL) && (dwDesiredAccess != 0))\r
+        hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL,\r
+                      dwCreationDisposition, dwFlagsAndAttributes, NULL);\r
+\r
+    if (hFile == INVALID_HANDLE_VALUE)\r
+        hFile = NULL;\r
+\r
+    if (hFile != NULL)\r
+    {\r
+        WIN32FILE_IOWIN w32fiow;\r
+        w32fiow.hf = hFile;\r
+        w32fiow.error = 0;\r
+        ret = malloc(sizeof(WIN32FILE_IOWIN));\r
+        if (ret==NULL)\r
+            CloseHandle(hFile);\r
+        else *((WIN32FILE_IOWIN*)ret) = w32fiow;\r
+    }\r
+    return ret;\r
+}\r
+\r
+\r
+uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+   void* buf;\r
+   uLong size;\r
+{\r
+    uLong ret=0;\r
+    HANDLE hFile = NULL;\r
+    if (stream!=NULL)\r
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;\r
+    if (hFile != NULL)\r
+        if (!ReadFile(hFile, buf, size, &ret, NULL))\r
+        {\r
+            DWORD dwErr = GetLastError();\r
+            if (dwErr == ERROR_HANDLE_EOF)\r
+                dwErr = 0;\r
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;\r
+        }\r
+\r
+    return ret;\r
+}\r
+\r
+\r
+uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+   const void* buf;\r
+   uLong size;\r
+{\r
+    uLong ret=0;\r
+    HANDLE hFile = NULL;\r
+    if (stream!=NULL)\r
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;\r
+\r
+    if (hFile !=NULL)\r
+        if (!WriteFile(hFile, buf, size, &ret, NULL))\r
+        {\r
+            DWORD dwErr = GetLastError();\r
+            if (dwErr == ERROR_HANDLE_EOF)\r
+                dwErr = 0;\r
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;\r
+        }\r
+\r
+    return ret;\r
+}\r
+\r
+long ZCALLBACK win32_tell_file_func (opaque, stream)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+{\r
+    long ret=-1;\r
+    HANDLE hFile = NULL;\r
+    if (stream!=NULL)\r
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;\r
+    if (hFile != NULL)\r
+    {\r
+        DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);\r
+        if (dwSet == INVALID_SET_FILE_POINTER)\r
+        {\r
+            DWORD dwErr = GetLastError();\r
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;\r
+            ret = -1;\r
+        }\r
+        else\r
+            ret=(long)dwSet;\r
+    }\r
+    return ret;\r
+}\r
+\r
+long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+   uLong offset;\r
+   int origin;\r
+{\r
+    DWORD dwMoveMethod=0xFFFFFFFF;\r
+    HANDLE hFile = NULL;\r
+\r
+    long ret=-1;\r
+    if (stream!=NULL)\r
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;\r
+    switch (origin)\r
+    {\r
+    case ZLIB_FILEFUNC_SEEK_CUR :\r
+        dwMoveMethod = FILE_CURRENT;\r
+        break;\r
+    case ZLIB_FILEFUNC_SEEK_END :\r
+        dwMoveMethod = FILE_END;\r
+        break;\r
+    case ZLIB_FILEFUNC_SEEK_SET :\r
+        dwMoveMethod = FILE_BEGIN;\r
+        break;\r
+    default: return -1;\r
+    }\r
+\r
+    if (hFile != NULL)\r
+    {\r
+        DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod);\r
+        if (dwSet == INVALID_SET_FILE_POINTER)\r
+        {\r
+            DWORD dwErr = GetLastError();\r
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;\r
+            ret = -1;\r
+        }\r
+        else\r
+            ret=0;\r
+    }\r
+    return ret;\r
+}\r
+\r
+int ZCALLBACK win32_close_file_func (opaque, stream)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+{\r
+    int ret=-1;\r
+\r
+    if (stream!=NULL)\r
+    {\r
+        HANDLE hFile;\r
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;\r
+        if (hFile != NULL)\r
+        {\r
+            CloseHandle(hFile);\r
+            ret=0;\r
+        }\r
+        free(stream);\r
+    }\r
+    return ret;\r
+}\r
+\r
+int ZCALLBACK win32_error_file_func (opaque, stream)\r
+   voidpf opaque;\r
+   voidpf stream;\r
+{\r
+    int ret=-1;\r
+    if (stream!=NULL)\r
+    {\r
+        ret = ((WIN32FILE_IOWIN*)stream) -> error;\r
+    }\r
+    return ret;\r
+}\r
+\r
+void fill_win32_filefunc (pzlib_filefunc_def)\r
+  zlib_filefunc_def* pzlib_filefunc_def;\r
+{\r
+    pzlib_filefunc_def->zopen_file = win32_open_file_func;\r
+    pzlib_filefunc_def->zread_file = win32_read_file_func;\r
+    pzlib_filefunc_def->zwrite_file = win32_write_file_func;\r
+    pzlib_filefunc_def->ztell_file = win32_tell_file_func;\r
+    pzlib_filefunc_def->zseek_file = win32_seek_file_func;\r
+    pzlib_filefunc_def->zclose_file = win32_close_file_func;\r
+    pzlib_filefunc_def->zerror_file = win32_error_file_func;\r
+    pzlib_filefunc_def->opaque=NULL;\r
+}\r
index 8774fe7..e9c5f8b 100644 (file)
@@ -1,21 +1,21 @@
-/* iowin32.h -- IO base function header for compress/uncompress .zip
-   files using zlib + zip or unzip API
-   This IO API version uses the Win32 API (for Microsoft Windows)
-
-   Version 1.01, May 8th, 2004
-
-   Copyright (C) 1998-2004 Gilles Vollant
-*/
-
-#include <windows.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
-
-#ifdef __cplusplus
-}
-#endif
+/* iowin32.h -- IO base function header for compress/uncompress .zip\r
+   files using zlib + zip or unzip API\r
+   This IO API version uses the Win32 API (for Microsoft Windows)\r
+\r
+   Version 1.01e, February 12th, 2005\r
+\r
+   Copyright (C) 1998-2005 Gilles Vollant\r
+*/\r
+\r
+#include <windows.h>\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
index a6b06a2..82d8702 100644 (file)
-/*
-   miniunz.c
-   Version 1.01b, May 30th, 2004
-
-   Copyright (C) 1998-2004 Gilles Vollant
-*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#ifdef unix
-# include <unistd.h>
-# include <utime.h>
-#else
-# include <direct.h>
-# include <io.h>
-#endif
-
-#include "unzip.h"
-
-#define CASESENSITIVITY (0)
-#define WRITEBUFFERSIZE (8192)
-#define MAXFILENAME (256)
-
-#ifdef WIN32
-#define USEWIN32IOAPI
-#include "iowin32.h"
-#endif
-/*
-  mini unzip, demo of unzip package
-
-  usage :
-  Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir]
-
-  list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT
-    if it exists
-*/
-
-
-/* change_file_date : change the date/time of a file
-    filename : the filename of the file where date/time must be modified
-    dosdate : the new date at the MSDos format (4 bytes)
-    tmu_date : the SAME new date at the tm_unz format */
-void change_file_date(filename,dosdate,tmu_date)
-    const char *filename;
-    uLong dosdate;
-    tm_unz tmu_date;
-{
-#ifdef WIN32
-  HANDLE hFile;
-  FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
-
-  hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE,
-                      0,NULL,OPEN_EXISTING,0,NULL);
-  GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
-  DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
-  LocalFileTimeToFileTime(&ftLocal,&ftm);
-  SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
-  CloseHandle(hFile);
-#else
-#ifdef unix
-  struct utimbuf ut;
-  struct tm newdate;
-  newdate.tm_sec = tmu_date.tm_sec;
-  newdate.tm_min=tmu_date.tm_min;
-  newdate.tm_hour=tmu_date.tm_hour;
-  newdate.tm_mday=tmu_date.tm_mday;
-  newdate.tm_mon=tmu_date.tm_mon;
-  if (tmu_date.tm_year > 1900)
-      newdate.tm_year=tmu_date.tm_year - 1900;
-  else
-      newdate.tm_year=tmu_date.tm_year ;
-  newdate.tm_isdst=-1;
-
-  ut.actime=ut.modtime=mktime(&newdate);
-  utime(filename,&ut);
-#endif
-#endif
-}
-
-
-/* mymkdir and change_file_date are not 100 % portable
-   As I don't know well Unix, I wait feedback for the unix portion */
-
-int mymkdir(dirname)
-    const char* dirname;
-{
-    int ret=0;
-#ifdef WIN32
-    ret = mkdir(dirname);
-#else
-#ifdef unix
-    ret = mkdir (dirname,0775);
-#endif
-#endif
-    return ret;
-}
-
-int makedir (newdir)
-    char *newdir;
-{
-  char *buffer ;
-  char *p;
-  int  len = (int)strlen(newdir);
-
-  if (len <= 0)
-    return 0;
-
-  buffer = (char*)malloc(len+1);
-  strcpy(buffer,newdir);
-
-  if (buffer[len-1] == '/') {
-    buffer[len-1] = '\0';
-  }
-  if (mymkdir(buffer) == 0)
-    {
-      free(buffer);
-      return 1;
-    }
-
-  p = buffer+1;
-  while (1)
-    {
-      char hold;
-
-      while(*p && *p != '\\' && *p != '/')
-        p++;
-      hold = *p;
-      *p = 0;
-      if ((mymkdir(buffer) == -1) && (errno == ENOENT))
-        {
-          printf("couldn't create directory %s\n",buffer);
-          free(buffer);
-          return 0;
-        }
-      if (hold == 0)
-        break;
-      *p++ = hold;
-    }
-  free(buffer);
-  return 1;
-}
-
-void do_banner()
-{
-    printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n");
-    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
-}
-
-void do_help()
-{
-    printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \
-           "  -e  Extract without pathname (junk paths)\n" \
-           "  -x  Extract with pathname\n" \
-           "  -v  list files\n" \
-           "  -l  list files\n" \
-           "  -d  directory to extract into\n" \
-           "  -o  overwrite files without prompting\n" \
-           "  -p  extract crypted file using password\n\n");
-}
-
-
-int do_list(uf)
-    unzFile uf;
-{
-    uLong i;
-    unz_global_info gi;
-    int err;
-
-    err = unzGetGlobalInfo (uf,&gi);
-    if (err!=UNZ_OK)
-        printf("error %d with zipfile in unzGetGlobalInfo \n",err);
-    printf(" Length  Method   Size  Ratio   Date    Time   CRC-32     Name\n");
-    printf(" ------  ------   ----  -----   ----    ----   ------     ----\n");
-    for (i=0;i<gi.number_entry;i++)
-    {
-        char filename_inzip[256];
-        unz_file_info file_info;
-        uLong ratio=0;
-        const char *string_method;
-        char charCrypt=' ';
-        err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
-        if (err!=UNZ_OK)
-        {
-            printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
-            break;
-        }
-        if (file_info.uncompressed_size>0)
-            ratio = (file_info.compressed_size*100)/file_info.uncompressed_size;
-
-        /* display a '*' if the file is crypted */
-        if ((file_info.flag & 1) != 0)
-            charCrypt='*';
-
-        if (file_info.compression_method==0)
-            string_method="Stored";
-        else
-        if (file_info.compression_method==Z_DEFLATED)
-        {
-            uInt iLevel=(uInt)((file_info.flag & 0x6)/2);
-            if (iLevel==0)
-              string_method="Defl:N";
-            else if (iLevel==1)
-              string_method="Defl:X";
-            else if ((iLevel==2) || (iLevel==3))
-              string_method="Defl:F"; /* 2:fast , 3 : extra fast*/
-        }
-        else
-            string_method="Unkn. ";
-
-        printf("%7lu  %6s%c%7lu %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",
-                file_info.uncompressed_size,string_method,
-                charCrypt,
-                file_info.compressed_size,
-                ratio,
-                (uLong)file_info.tmu_date.tm_mon + 1,
-                (uLong)file_info.tmu_date.tm_mday,
-                (uLong)file_info.tmu_date.tm_year % 100,
-                (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min,
-                (uLong)file_info.crc,filename_inzip);
-        if ((i+1)<gi.number_entry)
-        {
-            err = unzGoToNextFile(uf);
-            if (err!=UNZ_OK)
-            {
-                printf("error %d with zipfile in unzGoToNextFile\n",err);
-                break;
-            }
-        }
-    }
-
-    return 0;
-}
-
-
-int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
-    unzFile uf;
-    const int* popt_extract_without_path;
-    int* popt_overwrite;
-    const char* password;
-{
-    char filename_inzip[256];
-    char* filename_withoutpath;
-    char* p;
-    int err=UNZ_OK;
-    FILE *fout=NULL;
-    void* buf;
-    uInt size_buf;
-
-    unz_file_info file_info;
-    uLong ratio=0;
-    err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
-
-    if (err!=UNZ_OK)
-    {
-        printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
-        return err;
-    }
-
-    size_buf = WRITEBUFFERSIZE;
-    buf = (void*)malloc(size_buf);
-    if (buf==NULL)
-    {
-        printf("Error allocating memory\n");
-        return UNZ_INTERNALERROR;
-    }
-
-    p = filename_withoutpath = filename_inzip;
-    while ((*p) != '\0')
-    {
-        if (((*p)=='/') || ((*p)=='\\'))
-            filename_withoutpath = p+1;
-        p++;
-    }
-
-    if ((*filename_withoutpath)=='\0')
-    {
-        if ((*popt_extract_without_path)==0)
-        {
-            printf("creating directory: %s\n",filename_inzip);
-            mymkdir(filename_inzip);
-        }
-    }
-    else
-    {
-        const char* write_filename;
-        int skip=0;
-
-        if ((*popt_extract_without_path)==0)
-            write_filename = filename_inzip;
-        else
-            write_filename = filename_withoutpath;
-
-        err = unzOpenCurrentFilePassword(uf,password);
-        if (err!=UNZ_OK)
-        {
-            printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
-        }
-
-        if (((*popt_overwrite)==0) && (err==UNZ_OK))
-        {
-            char rep=0;
-            FILE* ftestexist;
-            ftestexist = fopen(write_filename,"rb");
-            if (ftestexist!=NULL)
-            {
-                fclose(ftestexist);
-                do
-                {
-                    char answer[128];
-                    int ret;
-
-                    printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename);
-                    ret = scanf("%1s",answer);
-                    if (ret != 1)
-                    {
-                       exit(EXIT_FAILURE);
-                    }
-                    rep = answer[0] ;
-                    if ((rep>='a') && (rep<='z'))
-                        rep -= 0x20;
-                }
-                while ((rep!='Y') && (rep!='N') && (rep!='A'));
-            }
-
-            if (rep == 'N')
-                skip = 1;
-
-            if (rep == 'A')
-                *popt_overwrite=1;
-        }
-
-        if ((skip==0) && (err==UNZ_OK))
-        {
-            fout=fopen(write_filename,"wb");
-
-            /* some zipfile don't contain directory alone before file */
-            if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
-                                (filename_withoutpath!=(char*)filename_inzip))
-            {
-                char c=*(filename_withoutpath-1);
-                *(filename_withoutpath-1)='\0';
-                makedir(write_filename);
-                *(filename_withoutpath-1)=c;
-                fout=fopen(write_filename,"wb");
-            }
-
-            if (fout==NULL)
-            {
-                printf("error opening %s\n",write_filename);
-            }
-        }
-
-        if (fout!=NULL)
-        {
-            printf(" extracting: %s\n",write_filename);
-
-            do
-            {
-                err = unzReadCurrentFile(uf,buf,size_buf);
-                if (err<0)
-                {
-                    printf("error %d with zipfile in unzReadCurrentFile\n",err);
-                    break;
-                }
-                if (err>0)
-                    if (fwrite(buf,err,1,fout)!=1)
-                    {
-                        printf("error in writing extracted file\n");
-                        err=UNZ_ERRNO;
-                        break;
-                    }
-            }
-            while (err>0);
-            if (fout)
-                    fclose(fout);
-
-            if (err==0)
-                change_file_date(write_filename,file_info.dosDate,
-                                 file_info.tmu_date);
-        }
-
-        if (err==UNZ_OK)
-        {
-            err = unzCloseCurrentFile (uf);
-            if (err!=UNZ_OK)
-            {
-                printf("error %d with zipfile in unzCloseCurrentFile\n",err);
-            }
-        }
-        else
-            unzCloseCurrentFile(uf); /* don't lose the error */
-    }
-
-    free(buf);
-    return err;
-}
-
-
-int do_extract(uf,opt_extract_without_path,opt_overwrite,password)
-    unzFile uf;
-    int opt_extract_without_path;
-    int opt_overwrite;
-    const char* password;
-{
-    uLong i;
-    unz_global_info gi;
-    int err;
-    FILE* fout=NULL;
-
-    err = unzGetGlobalInfo (uf,&gi);
-    if (err!=UNZ_OK)
-        printf("error %d with zipfile in unzGetGlobalInfo \n",err);
-
-    for (i=0;i<gi.number_entry;i++)
-    {
-        if (do_extract_currentfile(uf,&opt_extract_without_path,
-                                      &opt_overwrite,
-                                      password) != UNZ_OK)
-            break;
-
-        if ((i+1)<gi.number_entry)
-        {
-            err = unzGoToNextFile(uf);
-            if (err!=UNZ_OK)
-            {
-                printf("error %d with zipfile in unzGoToNextFile\n",err);
-                break;
-            }
-        }
-    }
-
-    return 0;
-}
-
-int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite,password)
-    unzFile uf;
-    const char* filename;
-    int opt_extract_without_path;
-    int opt_overwrite;
-    const char* password;
-{
-    int err = UNZ_OK;
-    if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)
-    {
-        printf("file %s not found in the zipfile\n",filename);
-        return 2;
-    }
-
-    if (do_extract_currentfile(uf,&opt_extract_without_path,
-                                      &opt_overwrite,
-                                      password) == UNZ_OK)
-        return 0;
-    else
-        return 1;
-}
-
-
-int main(argc,argv)
-    int argc;
-    char *argv[];
-{
-    const char *zipfilename=NULL;
-    const char *filename_to_extract=NULL;
-    const char *password=NULL;
-    char filename_try[MAXFILENAME+16] = "";
-    int i;
-    int opt_do_list=0;
-    int opt_do_extract=1;
-    int opt_do_extract_withoutpath=0;
-    int opt_overwrite=0;
-    int opt_extractdir=0;
-    const char *dirname=NULL;
-    unzFile uf=NULL;
-
-    do_banner();
-    if (argc==1)
-    {
-        do_help();
-        return 0;
-    }
-    else
-    {
-        for (i=1;i<argc;i++)
-        {
-            if ((*argv[i])=='-')
-            {
-                const char *p=argv[i]+1;
-
-                while ((*p)!='\0')
-                {
-                    char c=*(p++);;
-                    if ((c=='l') || (c=='L'))
-                        opt_do_list = 1;
-                    if ((c=='v') || (c=='V'))
-                        opt_do_list = 1;
-                    if ((c=='x') || (c=='X'))
-                        opt_do_extract = 1;
-                    if ((c=='e') || (c=='E'))
-                        opt_do_extract = opt_do_extract_withoutpath = 1;
-                    if ((c=='o') || (c=='O'))
-                        opt_overwrite=1;
-                    if ((c=='d') || (c=='D'))
-                    {
-                        opt_extractdir=1;
-                        dirname=argv[i+1];
-                    }
-
-                    if (((c=='p') || (c=='P')) && (i+1<argc))
-                    {
-                        password=argv[i+1];
-                        i++;
-                    }
-                }
-            }
-            else
-            {
-                if (zipfilename == NULL)
-                    zipfilename = argv[i];
-                else if ((filename_to_extract==NULL) && (!opt_extractdir))
-                        filename_to_extract = argv[i] ;
-            }
-        }
-    }
-
-    if (zipfilename!=NULL)
-    {
-
-#        ifdef USEWIN32IOAPI
-        zlib_filefunc_def ffunc;
-#        endif
-
-        strncpy(filename_try, zipfilename,MAXFILENAME-1);
-        /* strncpy doesnt append the trailing NULL, of the string is too long. */
-        filename_try[ MAXFILENAME ] = '\0';
-
-#        ifdef USEWIN32IOAPI
-        fill_win32_filefunc(&ffunc);
-        uf = unzOpen2(zipfilename,&ffunc);
-#        else
-        uf = unzOpen(zipfilename);
-#        endif
-        if (uf==NULL)
-        {
-            strcat(filename_try,".zip");
-#            ifdef USEWIN32IOAPI
-            uf = unzOpen2(filename_try,&ffunc);
-#            else
-            uf = unzOpen(filename_try);
-#            endif
-        }
-    }
-
-    if (uf==NULL)
-    {
-        printf("Cannot open %s or %s.zip\n",zipfilename,zipfilename);
-        return 1;
-    }
-    printf("%s opened\n",filename_try);
-
-    if (opt_do_list==1)
-        return do_list(uf);
-    else if (opt_do_extract==1)
-    {
-        if (opt_extractdir && chdir(dirname))
-        {
-          printf("Error changing into %s, aborting\n", dirname);
-          exit(-1);
-        }
-
-        if (filename_to_extract == NULL)
-            return do_extract(uf,opt_do_extract_withoutpath,opt_overwrite,password);
-        else
-            return do_extract_onefile(uf,filename_to_extract,
-                                      opt_do_extract_withoutpath,opt_overwrite,password);
-    }
-    unzCloseCurrentFile(uf);
-
-    return 0;
-}
+/*\r
+   miniunz.c\r
+   Version 1.01e, February 12th, 2005\r
+\r
+   Copyright (C) 1998-2005 Gilles Vollant\r
+*/\r
+\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <time.h>\r
+#include <errno.h>\r
+#include <fcntl.h>\r
+\r
+#ifdef unix\r
+# include <unistd.h>\r
+# include <utime.h>\r
+#else\r
+# include <direct.h>\r
+# include <io.h>\r
+#endif\r
+\r
+#include "unzip.h"\r
+\r
+#define CASESENSITIVITY (0)\r
+#define WRITEBUFFERSIZE (8192)\r
+#define MAXFILENAME (256)\r
+\r
+#ifdef WIN32\r
+#define USEWIN32IOAPI\r
+#include "iowin32.h"\r
+#endif\r
+/*\r
+  mini unzip, demo of unzip package\r
+\r
+  usage :\r
+  Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir]\r
+\r
+  list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT\r
+    if it exists\r
+*/\r
+\r
+\r
+/* change_file_date : change the date/time of a file\r
+    filename : the filename of the file where date/time must be modified\r
+    dosdate : the new date at the MSDos format (4 bytes)\r
+    tmu_date : the SAME new date at the tm_unz format */\r
+void change_file_date(filename,dosdate,tmu_date)\r
+    const char *filename;\r
+    uLong dosdate;\r
+    tm_unz tmu_date;\r
+{\r
+#ifdef WIN32\r
+  HANDLE hFile;\r
+  FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;\r
+\r
+  hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE,\r
+                      0,NULL,OPEN_EXISTING,0,NULL);\r
+  GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);\r
+  DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);\r
+  LocalFileTimeToFileTime(&ftLocal,&ftm);\r
+  SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);\r
+  CloseHandle(hFile);\r
+#else\r
+#ifdef unix\r
+  struct utimbuf ut;\r
+  struct tm newdate;\r
+  newdate.tm_sec = tmu_date.tm_sec;\r
+  newdate.tm_min=tmu_date.tm_min;\r
+  newdate.tm_hour=tmu_date.tm_hour;\r
+  newdate.tm_mday=tmu_date.tm_mday;\r
+  newdate.tm_mon=tmu_date.tm_mon;\r
+  if (tmu_date.tm_year > 1900)\r
+      newdate.tm_year=tmu_date.tm_year - 1900;\r
+  else\r
+      newdate.tm_year=tmu_date.tm_year ;\r
+  newdate.tm_isdst=-1;\r
+\r
+  ut.actime=ut.modtime=mktime(&newdate);\r
+  utime(filename,&ut);\r
+#endif\r
+#endif\r
+}\r
+\r
+\r
+/* mymkdir and change_file_date are not 100 % portable\r
+   As I don't know well Unix, I wait feedback for the unix portion */\r
+\r
+int mymkdir(dirname)\r
+    const char* dirname;\r
+{\r
+    int ret=0;\r
+#ifdef WIN32\r
+    ret = mkdir(dirname);\r
+#else\r
+#ifdef unix\r
+    ret = mkdir (dirname,0775);\r
+#endif\r
+#endif\r
+    return ret;\r
+}\r
+\r
+int makedir (newdir)\r
+    char *newdir;\r
+{\r
+  char *buffer ;\r
+  char *p;\r
+  int  len = (int)strlen(newdir);\r
+\r
+  if (len <= 0)\r
+    return 0;\r
+\r
+  buffer = (char*)malloc(len+1);\r
+  strcpy(buffer,newdir);\r
+\r
+  if (buffer[len-1] == '/') {\r
+    buffer[len-1] = '\0';\r
+  }\r
+  if (mymkdir(buffer) == 0)\r
+    {\r
+      free(buffer);\r
+      return 1;\r
+    }\r
+\r
+  p = buffer+1;\r
+  while (1)\r
+    {\r
+      char hold;\r
+\r
+      while(*p && *p != '\\' && *p != '/')\r
+        p++;\r
+      hold = *p;\r
+      *p = 0;\r
+      if ((mymkdir(buffer) == -1) && (errno == ENOENT))\r
+        {\r
+          printf("couldn't create directory %s\n",buffer);\r
+          free(buffer);\r
+          return 0;\r
+        }\r
+      if (hold == 0)\r
+        break;\r
+      *p++ = hold;\r
+    }\r
+  free(buffer);\r
+  return 1;\r
+}\r
+\r
+void do_banner()\r
+{\r
+    printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n");\r
+    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");\r
+}\r
+\r
+void do_help()\r
+{\r
+    printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \\r
+           "  -e  Extract without pathname (junk paths)\n" \\r
+           "  -x  Extract with pathname\n" \\r
+           "  -v  list files\n" \\r
+           "  -l  list files\n" \\r
+           "  -d  directory to extract into\n" \\r
+           "  -o  overwrite files without prompting\n" \\r
+           "  -p  extract crypted file using password\n\n");\r
+}\r
+\r
+\r
+int do_list(uf)\r
+    unzFile uf;\r
+{\r
+    uLong i;\r
+    unz_global_info gi;\r
+    int err;\r
+\r
+    err = unzGetGlobalInfo (uf,&gi);\r
+    if (err!=UNZ_OK)\r
+        printf("error %d with zipfile in unzGetGlobalInfo \n",err);\r
+    printf(" Length  Method   Size  Ratio   Date    Time   CRC-32     Name\n");\r
+    printf(" ------  ------   ----  -----   ----    ----   ------     ----\n");\r
+    for (i=0;i<gi.number_entry;i++)\r
+    {\r
+        char filename_inzip[256];\r
+        unz_file_info file_info;\r
+        uLong ratio=0;\r
+        const char *string_method;\r
+        char charCrypt=' ';\r
+        err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);\r
+        if (err!=UNZ_OK)\r
+        {\r
+            printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);\r
+            break;\r
+        }\r
+        if (file_info.uncompressed_size>0)\r
+            ratio = (file_info.compressed_size*100)/file_info.uncompressed_size;\r
+\r
+        /* display a '*' if the file is crypted */\r
+        if ((file_info.flag & 1) != 0)\r
+            charCrypt='*';\r
+\r
+        if (file_info.compression_method==0)\r
+            string_method="Stored";\r
+        else\r
+        if (file_info.compression_method==Z_DEFLATED)\r
+        {\r
+            uInt iLevel=(uInt)((file_info.flag & 0x6)/2);\r
+            if (iLevel==0)\r
+              string_method="Defl:N";\r
+            else if (iLevel==1)\r
+              string_method="Defl:X";\r
+            else if ((iLevel==2) || (iLevel==3))\r
+              string_method="Defl:F"; /* 2:fast , 3 : extra fast*/\r
+        }\r
+        else\r
+            string_method="Unkn. ";\r
+\r
+        printf("%7lu  %6s%c%7lu %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",\r
+                file_info.uncompressed_size,string_method,\r
+                charCrypt,\r
+                file_info.compressed_size,\r
+                ratio,\r
+                (uLong)file_info.tmu_date.tm_mon + 1,\r
+                (uLong)file_info.tmu_date.tm_mday,\r
+                (uLong)file_info.tmu_date.tm_year % 100,\r
+                (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min,\r
+                (uLong)file_info.crc,filename_inzip);\r
+        if ((i+1)<gi.number_entry)\r
+        {\r
+            err = unzGoToNextFile(uf);\r
+            if (err!=UNZ_OK)\r
+            {\r
+                printf("error %d with zipfile in unzGoToNextFile\n",err);\r
+                break;\r
+            }\r
+        }\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+\r
+int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)\r
+    unzFile uf;\r
+    const int* popt_extract_without_path;\r
+    int* popt_overwrite;\r
+    const char* password;\r
+{\r
+    char filename_inzip[256];\r
+    char* filename_withoutpath;\r
+    char* p;\r
+    int err=UNZ_OK;\r
+    FILE *fout=NULL;\r
+    void* buf;\r
+    uInt size_buf;\r
+\r
+    unz_file_info file_info;\r
+    uLong ratio=0;\r
+    err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);\r
+\r
+    if (err!=UNZ_OK)\r
+    {\r
+        printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);\r
+        return err;\r
+    }\r
+\r
+    size_buf = WRITEBUFFERSIZE;\r
+    buf = (void*)malloc(size_buf);\r
+    if (buf==NULL)\r
+    {\r
+        printf("Error allocating memory\n");\r
+        return UNZ_INTERNALERROR;\r
+    }\r
+\r
+    p = filename_withoutpath = filename_inzip;\r
+    while ((*p) != '\0')\r
+    {\r
+        if (((*p)=='/') || ((*p)=='\\'))\r
+            filename_withoutpath = p+1;\r
+        p++;\r
+    }\r
+\r
+    if ((*filename_withoutpath)=='\0')\r
+    {\r
+        if ((*popt_extract_without_path)==0)\r
+        {\r
+            printf("creating directory: %s\n",filename_inzip);\r
+            mymkdir(filename_inzip);\r
+        }\r
+    }\r
+    else\r
+    {\r
+        const char* write_filename;\r
+        int skip=0;\r
+\r
+        if ((*popt_extract_without_path)==0)\r
+            write_filename = filename_inzip;\r
+        else\r
+            write_filename = filename_withoutpath;\r
+\r
+        err = unzOpenCurrentFilePassword(uf,password);\r
+        if (err!=UNZ_OK)\r
+        {\r
+            printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);\r
+        }\r
+\r
+        if (((*popt_overwrite)==0) && (err==UNZ_OK))\r
+        {\r
+            char rep=0;\r
+            FILE* ftestexist;\r
+            ftestexist = fopen(write_filename,"rb");\r
+            if (ftestexist!=NULL)\r
+            {\r
+                fclose(ftestexist);\r
+                do\r
+                {\r
+                    char answer[128];\r
+                    int ret;\r
+\r
+                    printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename);\r
+                    ret = scanf("%1s",answer);\r
+                    if (ret != 1) \r
+                    {\r
+                       exit(EXIT_FAILURE);\r
+                    }\r
+                    rep = answer[0] ;\r
+                    if ((rep>='a') && (rep<='z'))\r
+                        rep -= 0x20;\r
+                }\r
+                while ((rep!='Y') && (rep!='N') && (rep!='A'));\r
+            }\r
+\r
+            if (rep == 'N')\r
+                skip = 1;\r
+\r
+            if (rep == 'A')\r
+                *popt_overwrite=1;\r
+        }\r
+\r
+        if ((skip==0) && (err==UNZ_OK))\r
+        {\r
+            fout=fopen(write_filename,"wb");\r
+\r
+            /* some zipfile don't contain directory alone before file */\r
+            if ((fout==NULL) && ((*popt_extract_without_path)==0) &&\r
+                                (filename_withoutpath!=(char*)filename_inzip))\r
+            {\r
+                char c=*(filename_withoutpath-1);\r
+                *(filename_withoutpath-1)='\0';\r
+                makedir(write_filename);\r
+                *(filename_withoutpath-1)=c;\r
+                fout=fopen(write_filename,"wb");\r
+            }\r
+\r
+            if (fout==NULL)\r
+            {\r
+                printf("error opening %s\n",write_filename);\r
+            }\r
+        }\r
+\r
+        if (fout!=NULL)\r
+        {\r
+            printf(" extracting: %s\n",write_filename);\r
+\r
+            do\r
+            {\r
+                err = unzReadCurrentFile(uf,buf,size_buf);\r
+                if (err<0)\r
+                {\r
+                    printf("error %d with zipfile in unzReadCurrentFile\n",err);\r
+                    break;\r
+                }\r
+                if (err>0)\r
+                    if (fwrite(buf,err,1,fout)!=1)\r
+                    {\r
+                        printf("error in writing extracted file\n");\r
+                        err=UNZ_ERRNO;\r
+                        break;\r
+                    }\r
+            }\r
+            while (err>0);\r
+            if (fout)\r
+                    fclose(fout);\r
+\r
+            if (err==0)\r
+                change_file_date(write_filename,file_info.dosDate,\r
+                                 file_info.tmu_date);\r
+        }\r
+\r
+        if (err==UNZ_OK)\r
+        {\r
+            err = unzCloseCurrentFile (uf);\r
+            if (err!=UNZ_OK)\r
+            {\r
+                printf("error %d with zipfile in unzCloseCurrentFile\n",err);\r
+            }\r
+        }\r
+        else\r
+            unzCloseCurrentFile(uf); /* don't lose the error */\r
+    }\r
+\r
+    free(buf);\r
+    return err;\r
+}\r
+\r
+\r
+int do_extract(uf,opt_extract_without_path,opt_overwrite,password)\r
+    unzFile uf;\r
+    int opt_extract_without_path;\r
+    int opt_overwrite;\r
+    const char* password;\r
+{\r
+    uLong i;\r
+    unz_global_info gi;\r
+    int err;\r
+    FILE* fout=NULL;\r
+\r
+    err = unzGetGlobalInfo (uf,&gi);\r
+    if (err!=UNZ_OK)\r
+        printf("error %d with zipfile in unzGetGlobalInfo \n",err);\r
+\r
+    for (i=0;i<gi.number_entry;i++)\r
+    {\r
+        if (do_extract_currentfile(uf,&opt_extract_without_path,\r
+                                      &opt_overwrite,\r
+                                      password) != UNZ_OK)\r
+            break;\r
+\r
+        if ((i+1)<gi.number_entry)\r
+        {\r
+            err = unzGoToNextFile(uf);\r
+            if (err!=UNZ_OK)\r
+            {\r
+                printf("error %d with zipfile in unzGoToNextFile\n",err);\r
+                break;\r
+            }\r
+        }\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite,password)\r
+    unzFile uf;\r
+    const char* filename;\r
+    int opt_extract_without_path;\r
+    int opt_overwrite;\r
+    const char* password;\r
+{\r
+    int err = UNZ_OK;\r
+    if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)\r
+    {\r
+        printf("file %s not found in the zipfile\n",filename);\r
+        return 2;\r
+    }\r
+\r
+    if (do_extract_currentfile(uf,&opt_extract_without_path,\r
+                                      &opt_overwrite,\r
+                                      password) == UNZ_OK)\r
+        return 0;\r
+    else\r
+        return 1;\r
+}\r
+\r
+\r
+int main(argc,argv)\r
+    int argc;\r
+    char *argv[];\r
+{\r
+    const char *zipfilename=NULL;\r
+    const char *filename_to_extract=NULL;\r
+    const char *password=NULL;\r
+    char filename_try[MAXFILENAME+16] = "";\r
+    int i;\r
+    int opt_do_list=0;\r
+    int opt_do_extract=1;\r
+    int opt_do_extract_withoutpath=0;\r
+    int opt_overwrite=0;\r
+    int opt_extractdir=0;\r
+    const char *dirname=NULL;\r
+    unzFile uf=NULL;\r
+\r
+    do_banner();\r
+    if (argc==1)\r
+    {\r
+        do_help();\r
+        return 0;\r
+    }\r
+    else\r
+    {\r
+        for (i=1;i<argc;i++)\r
+        {\r
+            if ((*argv[i])=='-')\r
+            {\r
+                const char *p=argv[i]+1;\r
+\r
+                while ((*p)!='\0')\r
+                {\r
+                    char c=*(p++);;\r
+                    if ((c=='l') || (c=='L'))\r
+                        opt_do_list = 1;\r
+                    if ((c=='v') || (c=='V'))\r
+                        opt_do_list = 1;\r
+                    if ((c=='x') || (c=='X'))\r
+                        opt_do_extract = 1;\r
+                    if ((c=='e') || (c=='E'))\r
+                        opt_do_extract = opt_do_extract_withoutpath = 1;\r
+                    if ((c=='o') || (c=='O'))\r
+                        opt_overwrite=1;\r
+                    if ((c=='d') || (c=='D'))\r
+                    {\r
+                        opt_extractdir=1;\r
+                        dirname=argv[i+1];\r
+                    }\r
+\r
+                    if (((c=='p') || (c=='P')) && (i+1<argc))\r
+                    {\r
+                        password=argv[i+1];\r
+                        i++;\r
+                    }\r
+                }\r
+            }\r
+            else\r
+            {\r
+                if (zipfilename == NULL)\r
+                    zipfilename = argv[i];\r
+                else if ((filename_to_extract==NULL) && (!opt_extractdir))\r
+                        filename_to_extract = argv[i] ;\r
+            }\r
+        }\r
+    }\r
+\r
+    if (zipfilename!=NULL)\r
+    {\r
+\r
+#        ifdef USEWIN32IOAPI\r
+        zlib_filefunc_def ffunc;\r
+#        endif\r
+\r
+        strncpy(filename_try, zipfilename,MAXFILENAME-1);\r
+        /* strncpy doesnt append the trailing NULL, of the string is too long. */\r
+        filename_try[ MAXFILENAME ] = '\0';\r
+\r
+#        ifdef USEWIN32IOAPI\r
+        fill_win32_filefunc(&ffunc);\r
+        uf = unzOpen2(zipfilename,&ffunc);\r
+#        else\r
+        uf = unzOpen(zipfilename);\r
+#        endif\r
+        if (uf==NULL)\r
+        {\r
+            strcat(filename_try,".zip");\r
+#            ifdef USEWIN32IOAPI\r
+            uf = unzOpen2(filename_try,&ffunc);\r
+#            else\r
+            uf = unzOpen(filename_try);\r
+#            endif\r
+        }\r
+    }\r
+\r
+    if (uf==NULL)\r
+    {\r
+        printf("Cannot open %s or %s.zip\n",zipfilename,zipfilename);\r
+        return 1;\r
+    }\r
+    printf("%s opened\n",filename_try);\r
+\r
+    if (opt_do_list==1)\r
+        return do_list(uf);\r
+    else if (opt_do_extract==1)\r
+    {\r
+        if (opt_extractdir && chdir(dirname)) \r
+        {\r
+          printf("Error changing into %s, aborting\n", dirname);\r
+          exit(-1);\r
+        }\r
+\r
+        if (filename_to_extract == NULL)\r
+            return do_extract(uf,opt_do_extract_withoutpath,opt_overwrite,password);\r
+        else\r
+            return do_extract_onefile(uf,filename_to_extract,\r
+                                      opt_do_extract_withoutpath,opt_overwrite,password);\r
+    }\r
+    unzCloseCurrentFile(uf);\r
+\r
+    return 0;\r
+}\r
index 918c322..70fee02 100644 (file)
-/*
-   minizip.c
-   Version 1.01b, May 30th, 2004
-
-   Copyright (C) 1998-2004 Gilles Vollant
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#ifdef unix
-# include <unistd.h>
-# include <utime.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-#else
-# include <direct.h>
-# include <io.h>
-#endif
-
-#include "zip.h"
-
-#ifdef WIN32
-#define USEWIN32IOAPI
-#include "iowin32.h"
-#endif
-
-
-
-#define WRITEBUFFERSIZE (16384)
-#define MAXFILENAME (256)
-
-#ifdef WIN32
-uLong filetime(f, tmzip, dt)
-    char *f;                /* name of file to get info on */
-    tm_zip *tmzip;             /* return value: access, modific. and creation times */
-    uLong *dt;             /* dostime */
-{
-  int ret = 0;
-  {
-      FILETIME ftLocal;
-      HANDLE hFind;
-      WIN32_FIND_DATA  ff32;
-
-      hFind = FindFirstFile(f,&ff32);
-      if (hFind != INVALID_HANDLE_VALUE)
-      {
-        FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
-        FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
-        FindClose(hFind);
-        ret = 1;
-      }
-  }
-  return ret;
-}
-#else
-#ifdef unix
-uLong filetime(f, tmzip, dt)
-    char *f;               /* name of file to get info on */
-    tm_zip *tmzip;         /* return value: access, modific. and creation times */
-    uLong *dt;             /* dostime */
-{
-  int ret=0;
-  struct stat s;        /* results of stat() */
-  struct tm* filedate;
-  time_t tm_t=0;
-
-  if (strcmp(f,"-")!=0)
-  {
-    char name[MAXFILENAME+1];
-    int len = strlen(f);
-    if (len > MAXFILENAME)
-      len = MAXFILENAME;
-
-    strncpy(name, f,MAXFILENAME-1);
-    /* strncpy doesnt append the trailing NULL, of the string is too long. */
-    name[ MAXFILENAME ] = '\0';
-
-    if (name[len - 1] == '/')
-      name[len - 1] = '\0';
-    /* not all systems allow stat'ing a file with / appended */
-    if (stat(name,&s)==0)
-    {
-      tm_t = s.st_mtime;
-      ret = 1;
-    }
-  }
-  filedate = localtime(&tm_t);
-
-  tmzip->tm_sec  = filedate->tm_sec;
-  tmzip->tm_min  = filedate->tm_min;
-  tmzip->tm_hour = filedate->tm_hour;
-  tmzip->tm_mday = filedate->tm_mday;
-  tmzip->tm_mon  = filedate->tm_mon ;
-  tmzip->tm_year = filedate->tm_year;
-
-  return ret;
-}
-#else
-uLong filetime(f, tmzip, dt)
-    char *f;                /* name of file to get info on */
-    tm_zip *tmzip;             /* return value: access, modific. and creation times */
-    uLong *dt;             /* dostime */
-{
-    return 0;
-}
-#endif
-#endif
-
-
-
-
-int check_exist_file(filename)
-    const char* filename;
-{
-    FILE* ftestexist;
-    int ret = 1;
-    ftestexist = fopen(filename,"rb");
-    if (ftestexist==NULL)
-        ret = 0;
-    else
-        fclose(ftestexist);
-    return ret;
-}
-
-void do_banner()
-{
-    printf("MiniZip 1.01b, demo of zLib + Zip package written by Gilles Vollant\n");
-    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
-}
-
-void do_help()
-{
-    printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] file.zip [files_to_add]\n\n" \
-           "  -o  Overwrite existing file.zip\n" \
-           "  -a  Append to existing file.zip\n" \
-           "  -0  Store only\n" \
-           "  -1  Compress faster\n" \
-           "  -9  Compress better\n\n");
-}
-
-/* calculate the CRC32 of a file,
-   because to encrypt a file, we need known the CRC32 of the file before */
-int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc)
-{
-   unsigned long calculate_crc=0;
-   int err=ZIP_OK;
-   FILE * fin = fopen(filenameinzip,"rb");
-   unsigned long size_read = 0;
-   unsigned long total_read = 0;
-   if (fin==NULL)
-   {
-       err = ZIP_ERRNO;
-   }
-
-    if (err == ZIP_OK)
-        do
-        {
-            err = ZIP_OK;
-            size_read = (int)fread(buf,1,size_buf,fin);
-            if (size_read < size_buf)
-                if (feof(fin)==0)
-            {
-                printf("error in reading %s\n",filenameinzip);
-                err = ZIP_ERRNO;
-            }
-
-            if (size_read>0)
-                calculate_crc = crc32(calculate_crc,buf,size_read);
-            total_read += size_read;
-
-        } while ((err == ZIP_OK) && (size_read>0));
-
-    if (fin)
-        fclose(fin);
-
-    *result_crc=calculate_crc;
-    printf("file %s crc %x\n",filenameinzip,calculate_crc);
-    return err;
-}
-
-int main(argc,argv)
-    int argc;
-    char *argv[];
-{
-    int i;
-    int opt_overwrite=0;
-    int opt_compress_level=Z_DEFAULT_COMPRESSION;
-    int zipfilenamearg = 0;
-    char filename_try[MAXFILENAME+16];
-    int zipok;
-    int err=0;
-    int size_buf=0;
-    void* buf=NULL;
-    const char* password=NULL;
-
-
-    do_banner();
-    if (argc==1)
-    {
-        do_help();
-        return 0;
-    }
-    else
-    {
-        for (i=1;i<argc;i++)
-        {
-            if ((*argv[i])=='-')
-            {
-                const char *p=argv[i]+1;
-
-                while ((*p)!='\0')
-                {
-                    char c=*(p++);;
-                    if ((c=='o') || (c=='O'))
-                        opt_overwrite = 1;
-                    if ((c=='a') || (c=='A'))
-                        opt_overwrite = 2;
-                    if ((c>='0') && (c<='9'))
-                        opt_compress_level = c-'0';
-
-                    if (((c=='p') || (c=='P')) && (i+1<argc))
-                    {
-                        password=argv[i+1];
-                        i++;
-                    }
-                }
-            }
-            else
-                if (zipfilenamearg == 0)
-                    zipfilenamearg = i ;
-        }
-    }
-
-    size_buf = WRITEBUFFERSIZE;
-    buf = (void*)malloc(size_buf);
-    if (buf==NULL)
-    {
-        printf("Error allocating memory\n");
-        return ZIP_INTERNALERROR;
-    }
-
-    if (zipfilenamearg==0)
-        zipok=0;
-    else
-    {
-        int i,len;
-        int dot_found=0;
-
-        zipok = 1 ;
-        strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);
-        /* strncpy doesnt append the trailing NULL, of the string is too long. */
-        filename_try[ MAXFILENAME ] = '\0';
-
-        len=(int)strlen(filename_try);
-        for (i=0;i<len;i++)
-            if (filename_try[i]=='.')
-                dot_found=1;
-
-        if (dot_found==0)
-            strcat(filename_try,".zip");
-
-        if (opt_overwrite==2)
-        {
-            /* if the file don't exist, we not append file */
-            if (check_exist_file(filename_try)==0)
-                opt_overwrite=1;
-        }
-        else
-        if (opt_overwrite==0)
-            if (check_exist_file(filename_try)!=0)
-            {
-                char rep=0;
-                do
-                {
-                    char answer[128];
-                    int ret;
-                    printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try);
-                    ret = scanf("%1s",answer);
-                    if (ret != 1)
-                    {
-                       exit(EXIT_FAILURE);
-                    }
-                    rep = answer[0] ;
-                    if ((rep>='a') && (rep<='z'))
-                        rep -= 0x20;
-                }
-                while ((rep!='Y') && (rep!='N') && (rep!='A'));
-                if (rep=='N')
-                    zipok = 0;
-                if (rep=='A')
-                    opt_overwrite = 2;
-            }
-    }
-
-    if (zipok==1)
-    {
-        zipFile zf;
-        int errclose;
-#        ifdef USEWIN32IOAPI
-        zlib_filefunc_def ffunc;
-        fill_win32_filefunc(&ffunc);
-        zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);
-#        else
-        zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0);
-#        endif
-
-        if (zf == NULL)
-        {
-            printf("error opening %s\n",filename_try);
-            err= ZIP_ERRNO;
-        }
-        else
-            printf("creating %s\n",filename_try);
-
-        for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++)
-        {
-            if (!((((*(argv[i]))=='-') || ((*(argv[i]))=='/')) &&
-                  ((argv[i][1]=='o') || (argv[i][1]=='O') ||
-                   (argv[i][1]=='a') || (argv[i][1]=='A') ||
-                   (argv[i][1]=='p') || (argv[i][1]=='P') ||
-                   ((argv[i][1]>='0') || (argv[i][1]<='9'))) &&
-                  (strlen(argv[i]) == 2)))
-            {
-                FILE * fin;
-                int size_read;
-                const char* filenameinzip = argv[i];
-                zip_fileinfo zi;
-                unsigned long crcFile=0;
-
-                zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
-                zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
-                zi.dosDate = 0;
-                zi.internal_fa = 0;
-                zi.external_fa = 0;
-                filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
-
-/*
-                err = zipOpenNewFileInZip(zf,filenameinzip,&zi,
-                                 NULL,0,NULL,0,NULL / * comment * /,
-                                 (opt_compress_level != 0) ? Z_DEFLATED : 0,
-                                 opt_compress_level);
-*/
-                if ((password != NULL) && (err==ZIP_OK))
-                    err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
-
-                err = zipOpenNewFileInZip3(zf,filenameinzip,&zi,
-                                 NULL,0,NULL,0,NULL /* comment*/,
-                                 (opt_compress_level != 0) ? Z_DEFLATED : 0,
-                                 opt_compress_level,0,
-                                 /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
-                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
-                                 password,crcFile);
-
-                if (err != ZIP_OK)
-                    printf("error in opening %s in zipfile\n",filenameinzip);
-                else
-                {
-                    fin = fopen(filenameinzip,"rb");
-                    if (fin==NULL)
-                    {
-                        err=ZIP_ERRNO;
-                        printf("error in opening %s for reading\n",filenameinzip);
-                    }
-                }
-
-                if (err == ZIP_OK)
-                    do
-                    {
-                        err = ZIP_OK;
-                        size_read = (int)fread(buf,1,size_buf,fin);
-                        if (size_read < size_buf)
-                            if (feof(fin)==0)
-                        {
-                            printf("error in reading %s\n",filenameinzip);
-                            err = ZIP_ERRNO;
-                        }
-
-                        if (size_read>0)
-                        {
-                            err = zipWriteInFileInZip (zf,buf,size_read);
-                            if (err<0)
-                            {
-                                printf("error in writing %s in the zipfile\n",
-                                                 filenameinzip);
-                            }
-
-                        }
-                    } while ((err == ZIP_OK) && (size_read>0));
-
-                if (fin)
-                    fclose(fin);
-
-                if (err<0)
-                    err=ZIP_ERRNO;
-                else
-                {
-                    err = zipCloseFileInZip(zf);
-                    if (err!=ZIP_OK)
-                        printf("error in closing %s in the zipfile\n",
-                                    filenameinzip);
-                }
-            }
-        }
-        errclose = zipClose(zf,NULL);
-        if (errclose != ZIP_OK)
-            printf("error in closing %s\n",filename_try);
-    }
-    else
-    {
-       do_help();
-    }
-
-    free(buf);
-    return 0;
-}
+/*\r
+   minizip.c\r
+   Version 1.01e, February 12th, 2005\r
+\r
+   Copyright (C) 1998-2005 Gilles Vollant\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <time.h>\r
+#include <errno.h>\r
+#include <fcntl.h>\r
+\r
+#ifdef unix\r
+# include <unistd.h>\r
+# include <utime.h>\r
+# include <sys/types.h>\r
+# include <sys/stat.h>\r
+#else\r
+# include <direct.h>\r
+# include <io.h>\r
+#endif\r
+\r
+#include "zip.h"\r
+\r
+#ifdef WIN32\r
+#define USEWIN32IOAPI\r
+#include "iowin32.h"\r
+#endif\r
+\r
+\r
+\r
+#define WRITEBUFFERSIZE (16384)\r
+#define MAXFILENAME (256)\r
+\r
+#ifdef WIN32\r
+uLong filetime(f, tmzip, dt)\r
+    char *f;                /* name of file to get info on */\r
+    tm_zip *tmzip;             /* return value: access, modific. and creation times */\r
+    uLong *dt;             /* dostime */\r
+{\r
+  int ret = 0;\r
+  {\r
+      FILETIME ftLocal;\r
+      HANDLE hFind;\r
+      WIN32_FIND_DATA  ff32;\r
+\r
+      hFind = FindFirstFile(f,&ff32);\r
+      if (hFind != INVALID_HANDLE_VALUE)\r
+      {\r
+        FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);\r
+        FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);\r
+        FindClose(hFind);\r
+        ret = 1;\r
+      }\r
+  }\r
+  return ret;\r
+}\r
+#else\r
+#ifdef unix\r
+uLong filetime(f, tmzip, dt)\r
+    char *f;               /* name of file to get info on */\r
+    tm_zip *tmzip;         /* return value: access, modific. and creation times */\r
+    uLong *dt;             /* dostime */\r
+{\r
+  int ret=0;\r
+  struct stat s;        /* results of stat() */\r
+  struct tm* filedate;\r
+  time_t tm_t=0;\r
+\r
+  if (strcmp(f,"-")!=0)\r
+  {\r
+    char name[MAXFILENAME+1];\r
+    int len = strlen(f);\r
+    if (len > MAXFILENAME)\r
+      len = MAXFILENAME;\r
+\r
+    strncpy(name, f,MAXFILENAME-1);\r
+    /* strncpy doesnt append the trailing NULL, of the string is too long. */\r
+    name[ MAXFILENAME ] = '\0';\r
+\r
+    if (name[len - 1] == '/')\r
+      name[len - 1] = '\0';\r
+    /* not all systems allow stat'ing a file with / appended */\r
+    if (stat(name,&s)==0)\r
+    {\r
+      tm_t = s.st_mtime;\r
+      ret = 1;\r
+    }\r
+  }\r
+  filedate = localtime(&tm_t);\r
+\r
+  tmzip->tm_sec  = filedate->tm_sec;\r
+  tmzip->tm_min  = filedate->tm_min;\r
+  tmzip->tm_hour = filedate->tm_hour;\r
+  tmzip->tm_mday = filedate->tm_mday;\r
+  tmzip->tm_mon  = filedate->tm_mon ;\r
+  tmzip->tm_year = filedate->tm_year;\r
+\r
+  return ret;\r
+}\r
+#else\r
+uLong filetime(f, tmzip, dt)\r
+    char *f;                /* name of file to get info on */\r
+    tm_zip *tmzip;             /* return value: access, modific. and creation times */\r
+    uLong *dt;             /* dostime */\r
+{\r
+    return 0;\r
+}\r
+#endif\r
+#endif\r
+\r
+\r
+\r
+\r
+int check_exist_file(filename)\r
+    const char* filename;\r
+{\r
+    FILE* ftestexist;\r
+    int ret = 1;\r
+    ftestexist = fopen(filename,"rb");\r
+    if (ftestexist==NULL)\r
+        ret = 0;\r
+    else\r
+        fclose(ftestexist);\r
+    return ret;\r
+}\r
+\r
+void do_banner()\r
+{\r
+    printf("MiniZip 1.01b, demo of zLib + Zip package written by Gilles Vollant\n");\r
+    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");\r
+}\r
+\r
+void do_help()\r
+{\r
+    printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] file.zip [files_to_add]\n\n" \\r
+           "  -o  Overwrite existing file.zip\n" \\r
+           "  -a  Append to existing file.zip\n" \\r
+           "  -0  Store only\n" \\r
+           "  -1  Compress faster\n" \\r
+           "  -9  Compress better\n\n");\r
+}\r
+\r
+/* calculate the CRC32 of a file,\r
+   because to encrypt a file, we need known the CRC32 of the file before */\r
+int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc)\r
+{\r
+   unsigned long calculate_crc=0;\r
+   int err=ZIP_OK;\r
+   FILE * fin = fopen(filenameinzip,"rb");\r
+   unsigned long size_read = 0;\r
+   unsigned long total_read = 0;\r
+   if (fin==NULL)\r
+   {\r
+       err = ZIP_ERRNO;\r
+   }\r
+\r
+    if (err == ZIP_OK)\r
+        do\r
+        {\r
+            err = ZIP_OK;\r
+            size_read = (int)fread(buf,1,size_buf,fin);\r
+            if (size_read < size_buf)\r
+                if (feof(fin)==0)\r
+            {\r
+                printf("error in reading %s\n",filenameinzip);\r
+                err = ZIP_ERRNO;\r
+            }\r
+\r
+            if (size_read>0)\r
+                calculate_crc = crc32(calculate_crc,buf,size_read);\r
+            total_read += size_read;\r
+\r
+        } while ((err == ZIP_OK) && (size_read>0));\r
+\r
+    if (fin)\r
+        fclose(fin);\r
+\r
+    *result_crc=calculate_crc;\r
+    printf("file %s crc %x\n",filenameinzip,calculate_crc);\r
+    return err;\r
+}\r
+\r
+int main(argc,argv)\r
+    int argc;\r
+    char *argv[];\r
+{\r
+    int i;\r
+    int opt_overwrite=0;\r
+    int opt_compress_level=Z_DEFAULT_COMPRESSION;\r
+    int zipfilenamearg = 0;\r
+    char filename_try[MAXFILENAME+16];\r
+    int zipok;\r
+    int err=0;\r
+    int size_buf=0;\r
+    void* buf=NULL;\r
+    const char* password=NULL;\r
+\r
+\r
+    do_banner();\r
+    if (argc==1)\r
+    {\r
+        do_help();\r
+        return 0;\r
+    }\r
+    else\r
+    {\r
+        for (i=1;i<argc;i++)\r
+        {\r
+            if ((*argv[i])=='-')\r
+            {\r
+                const char *p=argv[i]+1;\r
+\r
+                while ((*p)!='\0')\r
+                {\r
+                    char c=*(p++);;\r
+                    if ((c=='o') || (c=='O'))\r
+                        opt_overwrite = 1;\r
+                    if ((c=='a') || (c=='A'))\r
+                        opt_overwrite = 2;\r
+                    if ((c>='0') && (c<='9'))\r
+                        opt_compress_level = c-'0';\r
+\r
+                    if (((c=='p') || (c=='P')) && (i+1<argc))\r
+                    {\r
+                        password=argv[i+1];\r
+                        i++;\r
+                    }\r
+                }\r
+            }\r
+            else\r
+                if (zipfilenamearg == 0)\r
+                    zipfilenamearg = i ;\r
+        }\r
+    }\r
+\r
+    size_buf = WRITEBUFFERSIZE;\r
+    buf = (void*)malloc(size_buf);\r
+    if (buf==NULL)\r
+    {\r
+        printf("Error allocating memory\n");\r
+        return ZIP_INTERNALERROR;\r
+    }\r
+\r
+    if (zipfilenamearg==0)\r
+        zipok=0;\r
+    else\r
+    {\r
+        int i,len;\r
+        int dot_found=0;\r
+\r
+        zipok = 1 ;\r
+        strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);\r
+        /* strncpy doesnt append the trailing NULL, of the string is too long. */\r
+        filename_try[ MAXFILENAME ] = '\0';\r
+\r
+        len=(int)strlen(filename_try);\r
+        for (i=0;i<len;i++)\r
+            if (filename_try[i]=='.')\r
+                dot_found=1;\r
+\r
+        if (dot_found==0)\r
+            strcat(filename_try,".zip");\r
+\r
+        if (opt_overwrite==2)\r
+        {\r
+            /* if the file don't exist, we not append file */\r
+            if (check_exist_file(filename_try)==0)\r
+                opt_overwrite=1;\r
+        }\r
+        else\r
+        if (opt_overwrite==0)\r
+            if (check_exist_file(filename_try)!=0)\r
+            {\r
+                char rep=0;\r
+                do\r
+                {\r
+                    char answer[128];\r
+                    int ret;\r
+                    printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try);\r
+                    ret = scanf("%1s",answer);\r
+                    if (ret != 1)\r
+                    {\r
+                       exit(EXIT_FAILURE);\r
+                    }\r
+                    rep = answer[0] ;\r
+                    if ((rep>='a') && (rep<='z'))\r
+                        rep -= 0x20;\r
+                }\r
+                while ((rep!='Y') && (rep!='N') && (rep!='A'));\r
+                if (rep=='N')\r
+                    zipok = 0;\r
+                if (rep=='A')\r
+                    opt_overwrite = 2;\r
+            }\r
+    }\r
+\r
+    if (zipok==1)\r
+    {\r
+        zipFile zf;\r
+        int errclose;\r
+#        ifdef USEWIN32IOAPI\r
+        zlib_filefunc_def ffunc;\r
+        fill_win32_filefunc(&ffunc);\r
+        zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);\r
+#        else\r
+        zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0);\r
+#        endif\r
+\r
+        if (zf == NULL)\r
+        {\r
+            printf("error opening %s\n",filename_try);\r
+            err= ZIP_ERRNO;\r
+        }\r
+        else\r
+            printf("creating %s\n",filename_try);\r
+\r
+        for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++)\r
+        {\r
+            if (!((((*(argv[i]))=='-') || ((*(argv[i]))=='/')) &&\r
+                  ((argv[i][1]=='o') || (argv[i][1]=='O') ||\r
+                   (argv[i][1]=='a') || (argv[i][1]=='A') ||\r
+                   (argv[i][1]=='p') || (argv[i][1]=='P') ||\r
+                   ((argv[i][1]>='0') || (argv[i][1]<='9'))) &&\r
+                  (strlen(argv[i]) == 2)))\r
+            {\r
+                FILE * fin;\r
+                int size_read;\r
+                const char* filenameinzip = argv[i];\r
+                zip_fileinfo zi;\r
+                unsigned long crcFile=0;\r
+\r
+                zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =\r
+                zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;\r
+                zi.dosDate = 0;\r
+                zi.internal_fa = 0;\r
+                zi.external_fa = 0;\r
+                filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);\r
+\r
+/*\r
+                err = zipOpenNewFileInZip(zf,filenameinzip,&zi,\r
+                                 NULL,0,NULL,0,NULL / * comment * /,\r
+                                 (opt_compress_level != 0) ? Z_DEFLATED : 0,\r
+                                 opt_compress_level);\r
+*/\r
+                if ((password != NULL) && (err==ZIP_OK))\r
+                    err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);\r
+\r
+                err = zipOpenNewFileInZip3(zf,filenameinzip,&zi,\r
+                                 NULL,0,NULL,0,NULL /* comment*/,\r
+                                 (opt_compress_level != 0) ? Z_DEFLATED : 0,\r
+                                 opt_compress_level,0,\r
+                                 /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */\r
+                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,\r
+                                 password,crcFile);\r
+\r
+                if (err != ZIP_OK)\r
+                    printf("error in opening %s in zipfile\n",filenameinzip);\r
+                else\r
+                {\r
+                    fin = fopen(filenameinzip,"rb");\r
+                    if (fin==NULL)\r
+                    {\r
+                        err=ZIP_ERRNO;\r
+                        printf("error in opening %s for reading\n",filenameinzip);\r
+                    }\r
+                }\r
+\r
+                if (err == ZIP_OK)\r
+                    do\r
+                    {\r
+                        err = ZIP_OK;\r
+                        size_read = (int)fread(buf,1,size_buf,fin);\r
+                        if (size_read < size_buf)\r
+                            if (feof(fin)==0)\r
+                        {\r
+                            printf("error in reading %s\n",filenameinzip);\r
+                            err = ZIP_ERRNO;\r
+                        }\r
+\r
+                        if (size_read>0)\r
+                        {\r
+                            err = zipWriteInFileInZip (zf,buf,size_read);\r
+                            if (err<0)\r
+                            {\r
+                                printf("error in writing %s in the zipfile\n",\r
+                                                 filenameinzip);\r
+                            }\r
+\r
+                        }\r
+                    } while ((err == ZIP_OK) && (size_read>0));\r
+\r
+                if (fin)\r
+                    fclose(fin);\r
+\r
+                if (err<0)\r
+                    err=ZIP_ERRNO;\r
+                else\r
+                {\r
+                    err = zipCloseFileInZip(zf);\r
+                    if (err!=ZIP_OK)\r
+                        printf("error in closing %s in the zipfile\n",\r
+                                    filenameinzip);\r
+                }\r
+            }\r
+        }\r
+        errclose = zipClose(zf,NULL);\r
+        if (errclose != ZIP_OK)\r
+            printf("error in closing %s\n",filename_try);\r
+    }\r
+    else\r
+    {\r
+       do_help();\r
+    }\r
+\r
+    free(buf);\r
+    return 0;\r
+}\r
diff --git a/zlib/contrib/minizip/mztools.c b/zlib/contrib/minizip/mztools.c
new file mode 100644 (file)
index 0000000..bc5c798
--- /dev/null
@@ -0,0 +1,281 @@
+/*\r
+  Additional tools for Minizip\r
+  Code: Xavier Roche '2004\r
+  License: Same as ZLIB (www.gzip.org)\r
+*/\r
+\r
+/* Code */\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "zlib.h"\r
+#include "unzip.h"\r
+\r
+#define READ_8(adr)  ((unsigned char)*(adr))\r
+#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) )\r
+#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) )\r
+\r
+#define WRITE_8(buff, n) do { \\r
+  *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \\r
+} while(0)\r
+#define WRITE_16(buff, n) do { \\r
+  WRITE_8((unsigned char*)(buff), n); \\r
+  WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \\r
+} while(0)\r
+#define WRITE_32(buff, n) do { \\r
+  WRITE_16((unsigned char*)(buff), (n) & 0xffff); \\r
+  WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \\r
+} while(0)\r
+\r
+extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)\r
+const char* file;\r
+const char* fileOut;\r
+const char* fileOutTmp;\r
+uLong* nRecovered;\r
+uLong* bytesRecovered;\r
+{\r
+  int err = Z_OK;\r
+  FILE* fpZip = fopen(file, "rb");\r
+  FILE* fpOut = fopen(fileOut, "wb");\r
+  FILE* fpOutCD = fopen(fileOutTmp, "wb");\r
+  if (fpZip != NULL &&  fpOut != NULL) {\r
+    int entries = 0;\r
+    uLong totalBytes = 0;\r
+    char header[30];\r
+    char filename[256];\r
+    char extra[1024];\r
+    int offset = 0;\r
+    int offsetCD = 0;\r
+    while ( fread(header, 1, 30, fpZip) == 30 ) {\r
+      int currentOffset = offset;\r
+\r
+      /* File entry */\r
+      if (READ_32(header) == 0x04034b50) {\r
+        unsigned int version = READ_16(header + 4);\r
+        unsigned int gpflag = READ_16(header + 6);\r
+        unsigned int method = READ_16(header + 8);\r
+        unsigned int filetime = READ_16(header + 10);\r
+        unsigned int filedate = READ_16(header + 12);\r
+        unsigned int crc = READ_32(header + 14); /* crc */\r
+        unsigned int cpsize = READ_32(header + 18); /* compressed size */\r
+        unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */\r
+        unsigned int fnsize = READ_16(header + 26); /* file name length */\r
+        unsigned int extsize = READ_16(header + 28); /* extra field length */\r
+        filename[0] = extra[0] = '\0';\r
+        \r
+        /* Header */\r
+        if (fwrite(header, 1, 30, fpOut) == 30) {\r
+          offset += 30;\r
+        } else {\r
+          err = Z_ERRNO;\r
+          break;\r
+        }\r
+        \r
+        /* Filename */\r
+        if (fnsize > 0) {\r
+          if (fread(filename, 1, fnsize, fpZip) == fnsize) {\r
+            if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {\r
+              offset += fnsize;\r
+            } else {\r
+              err = Z_ERRNO;\r
+              break;\r
+            }\r
+          } else {\r
+            err = Z_ERRNO;\r
+            break;\r
+          }\r
+        } else {\r
+          err = Z_STREAM_ERROR;\r
+          break;\r
+        }\r
+\r
+        /* Extra field */\r
+        if (extsize > 0) {\r
+          if (fread(extra, 1, extsize, fpZip) == extsize) {\r
+            if (fwrite(extra, 1, extsize, fpOut) == extsize) {\r
+              offset += extsize;\r
+            } else {\r
+              err = Z_ERRNO;\r
+              break;\r
+            }\r
+          } else {\r
+            err = Z_ERRNO;\r
+            break;\r
+          }\r
+        }\r
+        \r
+        /* Data */\r
+        {\r
+          int dataSize = cpsize;\r
+          if (dataSize == 0) {\r
+            dataSize = uncpsize;\r
+          }\r
+          if (dataSize > 0) {\r
+            char* data = malloc(dataSize);\r
+            if (data != NULL) {\r
+              if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {\r
+                if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {\r
+                  offset += dataSize;\r
+                  totalBytes += dataSize;\r
+                } else {\r
+                  err = Z_ERRNO;\r
+                }\r
+              } else {\r
+                err = Z_ERRNO;\r
+              }\r
+              free(data);\r
+              if (err != Z_OK) {\r
+                break;\r
+              }\r
+            } else {\r
+              err = Z_MEM_ERROR;\r
+              break;\r
+            }\r
+          }\r
+        }\r
+        \r
+        /* Central directory entry */\r
+        {\r
+          char header[46];\r
+          char* comment = "";\r
+          int comsize = (int) strlen(comment);\r
+          WRITE_32(header, 0x02014b50);\r
+          WRITE_16(header + 4, version);\r
+          WRITE_16(header + 6, version);\r
+          WRITE_16(header + 8, gpflag);\r
+          WRITE_16(header + 10, method);\r
+          WRITE_16(header + 12, filetime);\r
+          WRITE_16(header + 14, filedate);\r
+          WRITE_32(header + 16, crc);\r
+          WRITE_32(header + 20, cpsize);\r
+          WRITE_32(header + 24, uncpsize);\r
+          WRITE_16(header + 28, fnsize);\r
+          WRITE_16(header + 30, extsize);\r
+          WRITE_16(header + 32, comsize);\r
+          WRITE_16(header + 34, 0);     /* disk # */\r
+          WRITE_16(header + 36, 0);     /* int attrb */\r
+          WRITE_32(header + 38, 0);     /* ext attrb */\r
+          WRITE_32(header + 42, currentOffset);\r
+          /* Header */\r
+          if (fwrite(header, 1, 46, fpOutCD) == 46) {\r
+            offsetCD += 46;\r
+            \r
+            /* Filename */\r
+            if (fnsize > 0) {\r
+              if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {\r
+                offsetCD += fnsize;\r
+              } else {\r
+                err = Z_ERRNO;\r
+                break;\r
+              }\r
+            } else {\r
+              err = Z_STREAM_ERROR;\r
+              break;\r
+            }\r
+            \r
+            /* Extra field */\r
+            if (extsize > 0) {\r
+              if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {\r
+                offsetCD += extsize;\r
+              } else {\r
+                err = Z_ERRNO;\r
+                break;\r
+              }\r
+            }\r
+            \r
+            /* Comment field */\r
+            if (comsize > 0) {\r
+              if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {\r
+                offsetCD += comsize;\r
+              } else {\r
+                err = Z_ERRNO;\r
+                break;\r
+              }\r
+            }\r
+            \r
+            \r
+          } else {\r
+            err = Z_ERRNO;\r
+            break;\r
+          }\r
+        }\r
+\r
+        /* Success */\r
+        entries++;\r
+\r
+      } else {\r
+        break;\r
+      }\r
+    }\r
+\r
+    /* Final central directory  */\r
+    {\r
+      int entriesZip = entries;\r
+      char header[22];\r
+      char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools";\r
+      int comsize = (int) strlen(comment);\r
+      if (entriesZip > 0xffff) {\r
+        entriesZip = 0xffff;\r
+      }\r
+      WRITE_32(header, 0x06054b50);\r
+      WRITE_16(header + 4, 0);    /* disk # */\r
+      WRITE_16(header + 6, 0);    /* disk # */\r
+      WRITE_16(header + 8, entriesZip);   /* hack */\r
+      WRITE_16(header + 10, entriesZip);  /* hack */\r
+      WRITE_32(header + 12, offsetCD);    /* size of CD */\r
+      WRITE_32(header + 16, offset);      /* offset to CD */\r
+      WRITE_16(header + 20, comsize);     /* comment */\r
+      \r
+      /* Header */\r
+      if (fwrite(header, 1, 22, fpOutCD) == 22) {\r
+        \r
+        /* Comment field */\r
+        if (comsize > 0) {\r
+          if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {\r
+            err = Z_ERRNO;\r
+          }\r
+        }\r
+        \r
+      } else {\r
+        err = Z_ERRNO;\r
+      }\r
+    }\r
+\r
+    /* Final merge (file + central directory) */\r
+    fclose(fpOutCD);\r
+    if (err == Z_OK) {\r
+      fpOutCD = fopen(fileOutTmp, "rb");\r
+      if (fpOutCD != NULL) {\r
+        int nRead;\r
+        char buffer[8192];\r
+        while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {\r
+          if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {\r
+            err = Z_ERRNO;\r
+            break;\r
+          }\r
+        }\r
+        fclose(fpOutCD);\r
+      }\r
+    }\r
+    \r
+    /* Close */\r
+    fclose(fpZip);\r
+    fclose(fpOut);\r
+    \r
+    /* Wipe temporary file */\r
+    (void)remove(fileOutTmp);\r
+    \r
+    /* Number of recovered entries */\r
+    if (err == Z_OK) {\r
+      if (nRecovered != NULL) {\r
+        *nRecovered = entries;\r
+      }\r
+      if (bytesRecovered != NULL) {\r
+        *bytesRecovered = totalBytes;\r
+      }\r
+    }\r
+  } else {\r
+    err = Z_STREAM_ERROR;\r
+  }\r
+  return err;\r
+}\r
diff --git a/zlib/contrib/minizip/mztools.h b/zlib/contrib/minizip/mztools.h
new file mode 100644 (file)
index 0000000..82d1597
--- /dev/null
@@ -0,0 +1,31 @@
+/*\r
+  Additional tools for Minizip\r
+  Code: Xavier Roche '2004\r
+  License: Same as ZLIB (www.gzip.org)\r
+*/\r
+\r
+#ifndef _zip_tools_H\r
+#define _zip_tools_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#ifndef _ZLIB_H\r
+#include "zlib.h"\r
+#endif\r
+\r
+#include "unzip.h"\r
+\r
+/* Repair a ZIP file (missing central directory) \r
+   file: file to recover\r
+   fileOut: output file after recovery\r
+   fileOutTmp: temporary file name used for recovery\r
+*/\r
+extern int ZEXPORT unzRepair(const char* file, \r
+                             const char* fileOut, \r
+                             const char* fileOutTmp, \r
+                             uLong* nRecovered,\r
+                             uLong* bytesRecovered);\r
+\r
+#endif\r
index e14de9e..3a70629 100644 (file)
-/* unzip.c -- IO for uncompress .zip files using zlib
-   Version 1.01d, September 22th, 2004
-
-   Copyright (C) 1998-2004 Gilles Vollant
-
-   Read unzip.h for more info
-*/
-
-/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
-compatibility with older software. The following is from the original crypt.c. Code
-woven in by Terry Thorsen 1/2003.
-*/
-/*
-  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
-
-  See the accompanying file LICENSE, version 2000-Apr-09 or later
-  (the contents of which are also included in zip.h) for terms of use.
-  If, for some reason, all these files are missing, the Info-ZIP license
-  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
-*/
-/*
-  crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
-
-  The encryption/decryption parts of this source code (as opposed to the
-  non-echoing password parts) were originally written in Europe.  The
-  whole source package can be freely distributed, including from the USA.
-  (Prior to January 2000, re-export from the US was a violation of US law.)
- */
-
-/*
-  This encryption code is a direct transcription of the algorithm from
-  Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
-  file (appnote.txt) is distributed with the PKZIP program (even in the
-  version without encryption capabilities).
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "zlib.h"
-#include "unzip.h"
-
-#ifdef STDC
-#  include <stddef.h>
-#  include <string.h>
-#  include <stdlib.h>
-#endif
-#ifdef NO_ERRNO_H
-    extern int errno;
-#else
-#   include <errno.h>
-#endif
-
-
-#ifndef local
-#  define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-
-#ifndef CASESENSITIVITYDEFAULT_NO
-#  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
-#    define CASESENSITIVITYDEFAULT_NO
-#  endif
-#endif
-
-
-#ifndef UNZ_BUFSIZE
-#define UNZ_BUFSIZE (16384)
-#endif
-
-#ifndef UNZ_MAXFILENAMEINZIP
-#define UNZ_MAXFILENAMEINZIP (256)
-#endif
-
-#ifndef ALLOC
-# define ALLOC(size) (malloc(size))
-#endif
-#ifndef TRYFREE
-# define TRYFREE(p) {if (p) free(p);}
-#endif
-
-#define SIZECENTRALDIRITEM (0x2e)
-#define SIZEZIPLOCALHEADER (0x1e)
-
-
-
-
-const char unz_copyright[] =
-   " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
-
-/* unz_file_info_interntal contain internal info about a file in zipfile*/
-typedef struct unz_file_info_internal_s
-{
-    uLong offset_curfile;/* relative offset of local header 4 bytes */
-} unz_file_info_internal;
-
-
-/* file_in_zip_read_info_s contain internal information about a file in zipfile,
-    when reading and decompress it */
-typedef struct
-{
-    char  *read_buffer;         /* internal buffer for compressed data */
-    z_stream stream;            /* zLib stream structure for inflate */
-
-    uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
-    uLong stream_initialised;   /* flag set if stream structure is initialised*/
-
-    uLong offset_local_extrafield;/* offset of the local extra field */
-    uInt  size_local_extrafield;/* size of the local extra field */
-    uLong pos_local_extrafield;   /* position in the local extra field in read*/
-
-    uLong crc32;                /* crc32 of all data uncompressed */
-    uLong crc32_wait;           /* crc32 we must obtain after decompress all */
-    uLong rest_read_compressed; /* number of byte to be decompressed */
-    uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
-    zlib_filefunc_def z_filefunc;
-    voidpf filestream;        /* io structore of the zipfile */
-    uLong compression_method;   /* compression method (0==store) */
-    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
-    int   raw;
-} file_in_zip_read_info_s;
-
-
-/* unz_s contain internal information about the zipfile
-*/
-typedef struct
-{
-    zlib_filefunc_def z_filefunc;
-    voidpf filestream;        /* io structore of the zipfile */
-    unz_global_info gi;       /* public global information */
-    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
-    uLong num_file;             /* number of the current file in the zipfile*/
-    uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
-    uLong current_file_ok;      /* flag about the usability of the current file*/
-    uLong central_pos;          /* position of the beginning of the central dir*/
-
-    uLong size_central_dir;     /* size of the central directory  */
-    uLong offset_central_dir;   /* offset of start of central directory with
-                                   respect to the starting disk number */
-
-    unz_file_info cur_file_info; /* public info about the current file in zip*/
-    unz_file_info_internal cur_file_info_internal; /* private info about it*/
-    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
-                                        file if we are decompressing it */
-    int encrypted;
-#    ifndef NOUNCRYPT
-    unsigned long keys[3];     /* keys defining the pseudo-random sequence */
-    const unsigned long* pcrc_32_tab;
-#    endif
-} unz_s;
-
-
-#ifndef NOUNCRYPT
-#include "crypt.h"
-#endif
-
-/* ===========================================================================
-     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
-   for end of file.
-   IN assertion: the stream s has been sucessfully opened for reading.
-*/
-
-
-local int unzlocal_getByte OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    int *pi));
-
-local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    int *pi;
-{
-    unsigned char c;
-    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
-    if (err==1)
-    {
-        *pi = (int)c;
-        return UNZ_OK;
-    }
-    else
-    {
-        if (ZERROR(*pzlib_filefunc_def,filestream))
-            return UNZ_ERRNO;
-        else
-            return UNZ_EOF;
-    }
-}
-
-
-/* ===========================================================================
-   Reads a long in LSB order from the given gz_stream. Sets
-*/
-local int unzlocal_getShort OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    uLong *pX));
-
-local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    uLong *pX;
-{
-    uLong x ;
-    int i;
-    int err;
-
-    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x = (uLong)i;
-
-    if (err==UNZ_OK)
-        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x += ((uLong)i)<<8;
-
-    if (err==UNZ_OK)
-        *pX = x;
-    else
-        *pX = 0;
-    return err;
-}
-
-local int unzlocal_getLong OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    uLong *pX));
-
-local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    uLong *pX;
-{
-    uLong x ;
-    int i;
-    int err;
-
-    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x = (uLong)i;
-
-    if (err==UNZ_OK)
-        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x += ((uLong)i)<<8;
-
-    if (err==UNZ_OK)
-        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x += ((uLong)i)<<16;
-
-    if (err==UNZ_OK)
-        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x += ((uLong)i)<<24;
-
-    if (err==UNZ_OK)
-        *pX = x;
-    else
-        *pX = 0;
-    return err;
-}
-
-
-/* My own strcmpi / strcasecmp */
-local int strcmpcasenosensitive_internal (fileName1,fileName2)
-    const char* fileName1;
-    const char* fileName2;
-{
-    for (;;)
-    {
-        char c1=*(fileName1++);
-        char c2=*(fileName2++);
-        if ((c1>='a') && (c1<='z'))
-            c1 -= 0x20;
-        if ((c2>='a') && (c2<='z'))
-            c2 -= 0x20;
-        if (c1=='\0')
-            return ((c2=='\0') ? 0 : -1);
-        if (c2=='\0')
-            return 1;
-        if (c1<c2)
-            return -1;
-        if (c1>c2)
-            return 1;
-    }
-}
-
-
-#ifdef  CASESENSITIVITYDEFAULT_NO
-#define CASESENSITIVITYDEFAULTVALUE 2
-#else
-#define CASESENSITIVITYDEFAULTVALUE 1
-#endif
-
-#ifndef STRCMPCASENOSENTIVEFUNCTION
-#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
-#endif
-
-/*
-   Compare two filename (fileName1,fileName2).
-   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
-   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
-                                                                or strcasecmp)
-   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
-        (like 1 on Unix, 2 on Windows)
-
-*/
-extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
-    const char* fileName1;
-    const char* fileName2;
-    int iCaseSensitivity;
-{
-    if (iCaseSensitivity==0)
-        iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
-
-    if (iCaseSensitivity==1)
-        return strcmp(fileName1,fileName2);
-
-    return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
-}
-
-#ifndef BUFREADCOMMENT
-#define BUFREADCOMMENT (0x400)
-#endif
-
-/*
-  Locate the Central directory of a zipfile (at the end, just before
-    the global comment)
-*/
-local uLong unzlocal_SearchCentralDir OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream));
-
-local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-{
-    unsigned char* buf;
-    uLong uSizeFile;
-    uLong uBackRead;
-    uLong uMaxBack=0xffff; /* maximum size of global comment */
-    uLong uPosFound=0;
-
-    if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
-        return 0;
-
-
-    uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
-
-    if (uMaxBack>uSizeFile)
-        uMaxBack = uSizeFile;
-
-    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
-    if (buf==NULL)
-        return 0;
-
-    uBackRead = 4;
-    while (uBackRead<uMaxBack)
-    {
-        uLong uReadSize,uReadPos ;
-        int i;
-        if (uBackRead+BUFREADCOMMENT>uMaxBack)
-            uBackRead = uMaxBack;
-        else
-            uBackRead+=BUFREADCOMMENT;
-        uReadPos = uSizeFile-uBackRead ;
-
-        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
-                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
-        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
-            break;
-
-        if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
-            break;
-
-        for (i=(int)uReadSize-3; (i--)>0;)
-            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
-                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
-            {
-                uPosFound = uReadPos+i;
-                break;
-            }
-
-        if (uPosFound!=0)
-            break;
-    }
-    TRYFREE(buf);
-    return uPosFound;
-}
-
-/*
-  Open a Zip file. path contain the full pathname (by example,
-     on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
-     "zlib/zlib114.zip".
-     If the zipfile cannot be opened (file doesn't exist or in not valid), the
-       return value is NULL.
-     Else, the return value is a unzFile Handle, usable with other function
-       of this unzip package.
-*/
-extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
-    const char *path;
-    zlib_filefunc_def* pzlib_filefunc_def;
-{
-    unz_s us;
-    unz_s *s;
-    uLong central_pos,uL;
-
-    uLong number_disk;          /* number of the current dist, used for
-                                   spaning ZIP, unsupported, always 0*/
-    uLong number_disk_with_CD;  /* number the the disk with central dir, used
-                                   for spaning ZIP, unsupported, always 0*/
-    uLong number_entry_CD;      /* total number of entries in
-                                   the central dir
-                                   (same than number_entry on nospan) */
-
-    int err=UNZ_OK;
-
-    if (unz_copyright[0]!=' ')
-        return NULL;
-
-    if (pzlib_filefunc_def==NULL)
-        fill_fopen_filefunc(&us.z_filefunc);
-    else
-        us.z_filefunc = *pzlib_filefunc_def;
-
-    us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
-                                                 path,
-                                                 ZLIB_FILEFUNC_MODE_READ |
-                                                 ZLIB_FILEFUNC_MODE_EXISTING);
-    if (us.filestream==NULL)
-        return NULL;
-
-    central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
-    if (central_pos==0)
-        err=UNZ_ERRNO;
-
-    if (ZSEEK(us.z_filefunc, us.filestream,
-                                      central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
-        err=UNZ_ERRNO;
-
-    /* the signature, already checked */
-    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
-        err=UNZ_ERRNO;
-
-    /* number of this disk */
-    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
-        err=UNZ_ERRNO;
-
-    /* number of the disk with the start of the central directory */
-    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
-        err=UNZ_ERRNO;
-
-    /* total number of entries in the central dir on this disk */
-    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
-        err=UNZ_ERRNO;
-
-    /* total number of entries in the central dir */
-    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if ((number_entry_CD!=us.gi.number_entry) ||
-        (number_disk_with_CD!=0) ||
-        (number_disk!=0))
-        err=UNZ_BADZIPFILE;
-
-    /* size of the central directory */
-    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
-        err=UNZ_ERRNO;
-
-    /* offset of start of central directory with respect to the
-          starting disk number */
-    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
-        err=UNZ_ERRNO;
-
-    /* zipfile comment length */
-    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
-        (err==UNZ_OK))
-        err=UNZ_BADZIPFILE;
-
-    if (err!=UNZ_OK)
-    {
-        ZCLOSE(us.z_filefunc, us.filestream);
-        return NULL;
-    }
-
-    us.byte_before_the_zipfile = central_pos -
-                            (us.offset_central_dir+us.size_central_dir);
-    us.central_pos = central_pos;
-    us.pfile_in_zip_read = NULL;
-    us.encrypted = 0;
-
-
-    s=(unz_s*)ALLOC(sizeof(unz_s));
-    *s=us;
-    unzGoToFirstFile((unzFile)s);
-    return (unzFile)s;
-}
-
-
-extern unzFile ZEXPORT unzOpen (path)
-    const char *path;
-{
-    return unzOpen2(path, NULL);
-}
-
-/*
-  Close a ZipFile opened with unzipOpen.
-  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
-    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
-  return UNZ_OK if there is no problem. */
-extern int ZEXPORT unzClose (file)
-    unzFile file;
-{
-    unz_s* s;
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-
-    if (s->pfile_in_zip_read!=NULL)
-        unzCloseCurrentFile(file);
-
-    ZCLOSE(s->z_filefunc, s->filestream);
-    TRYFREE(s);
-    return UNZ_OK;
-}
-
-
-/*
-  Write info about the ZipFile in the *pglobal_info structure.
-  No preparation of the structure is needed
-  return UNZ_OK if there is no problem. */
-extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
-    unzFile file;
-    unz_global_info *pglobal_info;
-{
-    unz_s* s;
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    *pglobal_info=s->gi;
-    return UNZ_OK;
-}
-
-
-/*
-   Translate date/time from Dos format to tm_unz (readable more easilty)
-*/
-local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
-    uLong ulDosDate;
-    tm_unz* ptm;
-{
-    uLong uDate;
-    uDate = (uLong)(ulDosDate>>16);
-    ptm->tm_mday = (uInt)(uDate&0x1f) ;
-    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
-    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
-
-    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
-    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
-    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
-}
-
-/*
-  Get Info about the current file in the zipfile, with internal only info
-*/
-local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
-                                                  unz_file_info *pfile_info,
-                                                  unz_file_info_internal
-                                                  *pfile_info_internal,
-                                                  char *szFileName,
-                                                  uLong fileNameBufferSize,
-                                                  void *extraField,
-                                                  uLong extraFieldBufferSize,
-                                                  char *szComment,
-                                                  uLong commentBufferSize));
-
-local int unzlocal_GetCurrentFileInfoInternal (file,
-                                              pfile_info,
-                                              pfile_info_internal,
-                                              szFileName, fileNameBufferSize,
-                                              extraField, extraFieldBufferSize,
-                                              szComment,  commentBufferSize)
-    unzFile file;
-    unz_file_info *pfile_info;
-    unz_file_info_internal *pfile_info_internal;
-    char *szFileName;
-    uLong fileNameBufferSize;
-    void *extraField;
-    uLong extraFieldBufferSize;
-    char *szComment;
-    uLong commentBufferSize;
-{
-    unz_s* s;
-    unz_file_info file_info;
-    unz_file_info_internal file_info_internal;
-    int err=UNZ_OK;
-    uLong uMagic;
-    long lSeek=0;
-
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    if (ZSEEK(s->z_filefunc, s->filestream,
-              s->pos_in_central_dir+s->byte_before_the_zipfile,
-              ZLIB_FILEFUNC_SEEK_SET)!=0)
-        err=UNZ_ERRNO;
-
-
-    /* we check the magic */
-    if (err==UNZ_OK)
-        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
-            err=UNZ_ERRNO;
-        else if (uMagic!=0x02014b50)
-            err=UNZ_BADZIPFILE;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
-
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    lSeek+=file_info.size_filename;
-    if ((err==UNZ_OK) && (szFileName!=NULL))
-    {
-        uLong uSizeRead ;
-        if (file_info.size_filename<fileNameBufferSize)
-        {
-            *(szFileName+file_info.size_filename)='\0';
-            uSizeRead = file_info.size_filename;
-        }
-        else
-            uSizeRead = fileNameBufferSize;
-
-        if ((file_info.size_filename>0) && (fileNameBufferSize>0))
-            if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
-                err=UNZ_ERRNO;
-        lSeek -= uSizeRead;
-    }
-
-
-    if ((err==UNZ_OK) && (extraField!=NULL))
-    {
-        uLong uSizeRead ;
-        if (file_info.size_file_extra<extraFieldBufferSize)
-            uSizeRead = file_info.size_file_extra;
-        else
-            uSizeRead = extraFieldBufferSize;
-
-        if (lSeek!=0)
-            if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
-                lSeek=0;
-            else
-                err=UNZ_ERRNO;
-        if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
-            if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
-                err=UNZ_ERRNO;
-        lSeek += file_info.size_file_extra - uSizeRead;
-    }
-    else
-        lSeek+=file_info.size_file_extra;
-
-
-    if ((err==UNZ_OK) && (szComment!=NULL))
-    {
-        uLong uSizeRead ;
-        if (file_info.size_file_comment<commentBufferSize)
-        {
-            *(szComment+file_info.size_file_comment)='\0';
-            uSizeRead = file_info.size_file_comment;
-        }
-        else
-            uSizeRead = commentBufferSize;
-
-        if (lSeek!=0)
-            if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
-                lSeek=0;
-            else
-                err=UNZ_ERRNO;
-        if ((file_info.size_file_comment>0) && (commentBufferSize>0))
-            if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
-                err=UNZ_ERRNO;
-        lSeek+=file_info.size_file_comment - uSizeRead;
-    }
-    else
-        lSeek+=file_info.size_file_comment;
-
-    if ((err==UNZ_OK) && (pfile_info!=NULL))
-        *pfile_info=file_info;
-
-    if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
-        *pfile_info_internal=file_info_internal;
-
-    return err;
-}
-
-
-
-/*
-  Write info about the ZipFile in the *pglobal_info structure.
-  No preparation of the structure is needed
-  return UNZ_OK if there is no problem.
-*/
-extern int ZEXPORT unzGetCurrentFileInfo (file,
-                                          pfile_info,
-                                          szFileName, fileNameBufferSize,
-                                          extraField, extraFieldBufferSize,
-                                          szComment,  commentBufferSize)
-    unzFile file;
-    unz_file_info *pfile_info;
-    char *szFileName;
-    uLong fileNameBufferSize;
-    void *extraField;
-    uLong extraFieldBufferSize;
-    char *szComment;
-    uLong commentBufferSize;
-{
-    return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
-                                                szFileName,fileNameBufferSize,
-                                                extraField,extraFieldBufferSize,
-                                                szComment,commentBufferSize);
-}
-
-/*
-  Set the current file of the zipfile to the first file.
-  return UNZ_OK if there is no problem
-*/
-extern int ZEXPORT unzGoToFirstFile (file)
-    unzFile file;
-{
-    int err=UNZ_OK;
-    unz_s* s;
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    s->pos_in_central_dir=s->offset_central_dir;
-    s->num_file=0;
-    err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
-                                             &s->cur_file_info_internal,
-                                             NULL,0,NULL,0,NULL,0);
-    s->current_file_ok = (err == UNZ_OK);
-    return err;
-}
-
-/*
-  Set the current file of the zipfile to the next file.
-  return UNZ_OK if there is no problem
-  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
-*/
-extern int ZEXPORT unzGoToNextFile (file)
-    unzFile file;
-{
-    unz_s* s;
-    int err;
-
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    if (!s->current_file_ok)
-        return UNZ_END_OF_LIST_OF_FILE;
-    if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
-      if (s->num_file+1==s->gi.number_entry)
-        return UNZ_END_OF_LIST_OF_FILE;
-
-    s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
-            s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
-    s->num_file++;
-    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
-                                               &s->cur_file_info_internal,
-                                               NULL,0,NULL,0,NULL,0);
-    s->current_file_ok = (err == UNZ_OK);
-    return err;
-}
-
-
-/*
-  Try locate the file szFileName in the zipfile.
-  For the iCaseSensitivity signification, see unzipStringFileNameCompare
-
-  return value :
-  UNZ_OK if the file is found. It becomes the current file.
-  UNZ_END_OF_LIST_OF_FILE if the file is not found
-*/
-extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
-    unzFile file;
-    const char *szFileName;
-    int iCaseSensitivity;
-{
-    unz_s* s;
-    int err;
-
-    /* We remember the 'current' position in the file so that we can jump
-     * back there if we fail.
-     */
-    unz_file_info cur_file_infoSaved;
-    unz_file_info_internal cur_file_info_internalSaved;
-    uLong num_fileSaved;
-    uLong pos_in_central_dirSaved;
-
-
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-
-    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
-        return UNZ_PARAMERROR;
-
-    s=(unz_s*)file;
-    if (!s->current_file_ok)
-        return UNZ_END_OF_LIST_OF_FILE;
-
-    /* Save the current state */
-    num_fileSaved = s->num_file;
-    pos_in_central_dirSaved = s->pos_in_central_dir;
-    cur_file_infoSaved = s->cur_file_info;
-    cur_file_info_internalSaved = s->cur_file_info_internal;
-
-    err = unzGoToFirstFile(file);
-
-    while (err == UNZ_OK)
-    {
-        char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
-        err = unzGetCurrentFileInfo(file,NULL,
-                                    szCurrentFileName,sizeof(szCurrentFileName)-1,
-                                    NULL,0,NULL,0);
-        if (err == UNZ_OK)
-        {
-            if (unzStringFileNameCompare(szCurrentFileName,
-                                            szFileName,iCaseSensitivity)==0)
-                return UNZ_OK;
-            err = unzGoToNextFile(file);
-        }
-    }
-
-    /* We failed, so restore the state of the 'current file' to where we
-     * were.
-     */
-    s->num_file = num_fileSaved ;
-    s->pos_in_central_dir = pos_in_central_dirSaved ;
-    s->cur_file_info = cur_file_infoSaved;
-    s->cur_file_info_internal = cur_file_info_internalSaved;
-    return err;
-}
-
-
-/*
-///////////////////////////////////////////
-// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
-// I need random access
-//
-// Further optimization could be realized by adding an ability
-// to cache the directory in memory. The goal being a single
-// comprehensive file read to put the file I need in a memory.
-*/
-
-/*
-typedef struct unz_file_pos_s
-{
-    uLong pos_in_zip_directory;   // offset in file
-    uLong num_of_file;            // # of file
-} unz_file_pos;
-*/
-
-extern int ZEXPORT unzGetFilePos(file, file_pos)
-    unzFile file;
-    unz_file_pos* file_pos;
-{
-    unz_s* s;
-
-    if (file==NULL || file_pos==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    if (!s->current_file_ok)
-        return UNZ_END_OF_LIST_OF_FILE;
-
-    file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
-    file_pos->num_of_file           = s->num_file;
-
-    return UNZ_OK;
-}
-
-extern int ZEXPORT unzGoToFilePos(file, file_pos)
-    unzFile file;
-    unz_file_pos* file_pos;
-{
-    unz_s* s;
-    int err;
-
-    if (file==NULL || file_pos==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-
-    /* jump to the right spot */
-    s->pos_in_central_dir = file_pos->pos_in_zip_directory;
-    s->num_file           = file_pos->num_of_file;
-
-    /* set the current file */
-    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
-                                               &s->cur_file_info_internal,
-                                               NULL,0,NULL,0,NULL,0);
-    /* return results */
-    s->current_file_ok = (err == UNZ_OK);
-    return err;
-}
-
-/*
-// Unzip Helper Functions - should be here?
-///////////////////////////////////////////
-*/
-
-/*
-  Read the local header of the current zipfile
-  Check the coherency of the local header and info in the end of central
-        directory about this file
-  store in *piSizeVar the size of extra info in local header
-        (filename and size of extra field data)
-*/
-local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
-                                                    poffset_local_extrafield,
-                                                    psize_local_extrafield)
-    unz_s* s;
-    uInt* piSizeVar;
-    uLong *poffset_local_extrafield;
-    uInt  *psize_local_extrafield;
-{
-    uLong uMagic,uData,uFlags;
-    uLong size_filename;
-    uLong size_extra_field;
-    int err=UNZ_OK;
-
-    *piSizeVar = 0;
-    *poffset_local_extrafield = 0;
-    *psize_local_extrafield = 0;
-
-    if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
-                                s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
-        return UNZ_ERRNO;
-
-
-    if (err==UNZ_OK)
-        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
-            err=UNZ_ERRNO;
-        else if (uMagic!=0x04034b50)
-            err=UNZ_BADZIPFILE;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
-        err=UNZ_ERRNO;
-/*
-    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
-        err=UNZ_BADZIPFILE;
-*/
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
-        err=UNZ_ERRNO;
-    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
-        err=UNZ_BADZIPFILE;
-
-    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
-                         (s->cur_file_info.compression_method!=Z_DEFLATED))
-        err=UNZ_BADZIPFILE;
-
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
-        err=UNZ_ERRNO;
-
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
-        err=UNZ_ERRNO;
-    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
-                              ((uFlags & 8)==0))
-        err=UNZ_BADZIPFILE;
-
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
-        err=UNZ_ERRNO;
-    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
-                              ((uFlags & 8)==0))
-        err=UNZ_BADZIPFILE;
-
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
-        err=UNZ_ERRNO;
-    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
-                              ((uFlags & 8)==0))
-        err=UNZ_BADZIPFILE;
-
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
-        err=UNZ_ERRNO;
-    else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
-        err=UNZ_BADZIPFILE;
-
-    *piSizeVar += (uInt)size_filename;
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
-        err=UNZ_ERRNO;
-    *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
-                                    SIZEZIPLOCALHEADER + size_filename;
-    *psize_local_extrafield = (uInt)size_extra_field;
-
-    *piSizeVar += (uInt)size_extra_field;
-
-    return err;
-}
-
-/*
-  Open for reading data the current file in the zipfile.
-  If there is no error and the file is opened, the return value is UNZ_OK.
-*/
-extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
-    unzFile file;
-    int* method;
-    int* level;
-    int raw;
-    const char* password;
-{
-    int err=UNZ_OK;
-    uInt iSizeVar;
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
-    uLong offset_local_extrafield;  /* offset of the local extra field */
-    uInt  size_local_extrafield;    /* size of the local extra field */
-#    ifndef NOUNCRYPT
-    char source[12];
-#    else
-    if (password != NULL)
-        return UNZ_PARAMERROR;
-#    endif
-
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    if (!s->current_file_ok)
-        return UNZ_PARAMERROR;
-
-    if (s->pfile_in_zip_read != NULL)
-        unzCloseCurrentFile(file);
-
-    if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
-                &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
-        return UNZ_BADZIPFILE;
-
-    pfile_in_zip_read_info = (file_in_zip_read_info_s*)
-                                        ALLOC(sizeof(file_in_zip_read_info_s));
-    if (pfile_in_zip_read_info==NULL)
-        return UNZ_INTERNALERROR;
-
-    pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
-    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
-    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
-    pfile_in_zip_read_info->pos_local_extrafield=0;
-    pfile_in_zip_read_info->raw=raw;
-
-    if (pfile_in_zip_read_info->read_buffer==NULL)
-    {
-        TRYFREE(pfile_in_zip_read_info);
-        return UNZ_INTERNALERROR;
-    }
-
-    pfile_in_zip_read_info->stream_initialised=0;
-
-    if (method!=NULL)
-        *method = (int)s->cur_file_info.compression_method;
-
-    if (level!=NULL)
-    {
-        *level = 6;
-        switch (s->cur_file_info.flag & 0x06)
-        {
-          case 6 : *level = 1; break;
-          case 4 : *level = 2; break;
-          case 2 : *level = 9; break;
-        }
-    }
-
-    if ((s->cur_file_info.compression_method!=0) &&
-        (s->cur_file_info.compression_method!=Z_DEFLATED))
-        err=UNZ_BADZIPFILE;
-
-    pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
-    pfile_in_zip_read_info->crc32=0;
-    pfile_in_zip_read_info->compression_method =
-            s->cur_file_info.compression_method;
-    pfile_in_zip_read_info->filestream=s->filestream;
-    pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
-    pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
-
-    pfile_in_zip_read_info->stream.total_out = 0;
-
-    if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
-        (!raw))
-    {
-      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
-      pfile_in_zip_read_info->stream.zfree = (free_func)0;
-      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
-      pfile_in_zip_read_info->stream.next_in = (voidpf)0;
-      pfile_in_zip_read_info->stream.avail_in = 0;
-
-      err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
-      if (err == Z_OK)
-        pfile_in_zip_read_info->stream_initialised=1;
-      else
-        return err;
-        /* windowBits is passed < 0 to tell that there is no zlib header.
-         * Note that in this case inflate *requires* an extra "dummy" byte
-         * after the compressed stream in order to complete decompression and
-         * return Z_STREAM_END.
-         * In unzip, i don't wait absolutely Z_STREAM_END because I known the
-         * size of both compressed and uncompressed data
-         */
-    }
-    pfile_in_zip_read_info->rest_read_compressed =
-            s->cur_file_info.compressed_size ;
-    pfile_in_zip_read_info->rest_read_uncompressed =
-            s->cur_file_info.uncompressed_size ;
-
-
-    pfile_in_zip_read_info->pos_in_zipfile =
-            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
-              iSizeVar;
-
-    pfile_in_zip_read_info->stream.avail_in = (uInt)0;
-
-    s->pfile_in_zip_read = pfile_in_zip_read_info;
-
-#    ifndef NOUNCRYPT
-    if (password != NULL)
-    {
-        int i;
-        s->pcrc_32_tab = get_crc_table();
-        init_keys(password,s->keys,s->pcrc_32_tab);
-        if (ZSEEK(s->z_filefunc, s->filestream,
-                  s->pfile_in_zip_read->pos_in_zipfile +
-                     s->pfile_in_zip_read->byte_before_the_zipfile,
-                  SEEK_SET)!=0)
-            return UNZ_INTERNALERROR;
-        if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
-            return UNZ_INTERNALERROR;
-
-        for (i = 0; i<12; i++)
-            zdecode(s->keys,s->pcrc_32_tab,source[i]);
-
-        s->pfile_in_zip_read->pos_in_zipfile+=12;
-        s->encrypted=1;
-    }
-#    endif
-
-
-    return UNZ_OK;
-}
-
-extern int ZEXPORT unzOpenCurrentFile (file)
-    unzFile file;
-{
-    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
-}
-
-extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
-    unzFile file;
-    const char* password;
-{
-    return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
-}
-
-extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
-    unzFile file;
-    int* method;
-    int* level;
-    int raw;
-{
-    return unzOpenCurrentFile3(file, method, level, raw, NULL);
-}
-
-/*
-  Read bytes from the current file.
-  buf contain buffer where data must be copied
-  len the size of buf.
-
-  return the number of byte copied if somes bytes are copied
-  return 0 if the end of file was reached
-  return <0 with error code if there is an error
-    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
-*/
-extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
-    unzFile file;
-    voidp buf;
-    unsigned len;
-{
-    int err=UNZ_OK;
-    uInt iRead = 0;
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    pfile_in_zip_read_info=s->pfile_in_zip_read;
-
-    if (pfile_in_zip_read_info==NULL)
-        return UNZ_PARAMERROR;
-
-
-    if ((pfile_in_zip_read_info->read_buffer == NULL))
-        return UNZ_END_OF_LIST_OF_FILE;
-    if (len==0)
-        return 0;
-
-    pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
-
-    pfile_in_zip_read_info->stream.avail_out = (uInt)len;
-
-    if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
-        (!(pfile_in_zip_read_info->raw)))
-        pfile_in_zip_read_info->stream.avail_out =
-            (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
-
-    if ((len>pfile_in_zip_read_info->rest_read_compressed+
-           pfile_in_zip_read_info->stream.avail_in) &&
-         (pfile_in_zip_read_info->raw))
-        pfile_in_zip_read_info->stream.avail_out =
-            (uInt)pfile_in_zip_read_info->rest_read_compressed+
-            pfile_in_zip_read_info->stream.avail_in;
-
-    while (pfile_in_zip_read_info->stream.avail_out>0)
-    {
-        if ((pfile_in_zip_read_info->stream.avail_in==0) &&
-            (pfile_in_zip_read_info->rest_read_compressed>0))
-        {
-            uInt uReadThis = UNZ_BUFSIZE;
-            if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
-                uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
-            if (uReadThis == 0)
-                return UNZ_EOF;
-            if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
-                      pfile_in_zip_read_info->filestream,
-                      pfile_in_zip_read_info->pos_in_zipfile +
-                         pfile_in_zip_read_info->byte_before_the_zipfile,
-                         ZLIB_FILEFUNC_SEEK_SET)!=0)
-                return UNZ_ERRNO;
-            if (ZREAD(pfile_in_zip_read_info->z_filefunc,
-                      pfile_in_zip_read_info->filestream,
-                      pfile_in_zip_read_info->read_buffer,
-                      uReadThis)!=uReadThis)
-                return UNZ_ERRNO;
-
-
-#            ifndef NOUNCRYPT
-            if(s->encrypted)
-            {
-                uInt i;
-                for(i=0;i<uReadThis;i++)
-                  pfile_in_zip_read_info->read_buffer[i] =
-                      zdecode(s->keys,s->pcrc_32_tab,
-                              pfile_in_zip_read_info->read_buffer[i]);
-            }
-#            endif
-
-
-            pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
-
-            pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
-
-            pfile_in_zip_read_info->stream.next_in =
-                (Bytef*)pfile_in_zip_read_info->read_buffer;
-            pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
-        }
-
-        if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
-        {
-            uInt uDoCopy,i ;
-
-            if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
-                (pfile_in_zip_read_info->rest_read_compressed == 0))
-                return (iRead==0) ? UNZ_EOF : iRead;
-
-            if (pfile_in_zip_read_info->stream.avail_out <
-                            pfile_in_zip_read_info->stream.avail_in)
-                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
-            else
-                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
-
-            for (i=0;i<uDoCopy;i++)
-                *(pfile_in_zip_read_info->stream.next_out+i) =
-                        *(pfile_in_zip_read_info->stream.next_in+i);
-
-            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
-                                pfile_in_zip_read_info->stream.next_out,
-                                uDoCopy);
-            pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
-            pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
-            pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
-            pfile_in_zip_read_info->stream.next_out += uDoCopy;
-            pfile_in_zip_read_info->stream.next_in += uDoCopy;
-            pfile_in_zip_read_info->stream.total_out += uDoCopy;
-            iRead += uDoCopy;
-        }
-        else
-        {
-            uLong uTotalOutBefore,uTotalOutAfter;
-            const Bytef *bufBefore;
-            uLong uOutThis;
-            int flush=Z_SYNC_FLUSH;
-
-            uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
-            bufBefore = pfile_in_zip_read_info->stream.next_out;
-
-            /*
-            if ((pfile_in_zip_read_info->rest_read_uncompressed ==
-                     pfile_in_zip_read_info->stream.avail_out) &&
-                (pfile_in_zip_read_info->rest_read_compressed == 0))
-                flush = Z_FINISH;
-            */
-            err=inflate(&pfile_in_zip_read_info->stream,flush);
-
-            if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
-              err = Z_DATA_ERROR;
-
-            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
-            uOutThis = uTotalOutAfter-uTotalOutBefore;
-
-            pfile_in_zip_read_info->crc32 =
-                crc32(pfile_in_zip_read_info->crc32,bufBefore,
-                        (uInt)(uOutThis));
-
-            pfile_in_zip_read_info->rest_read_uncompressed -=
-                uOutThis;
-
-            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
-
-            if (err==Z_STREAM_END)
-                return (iRead==0) ? UNZ_EOF : iRead;
-            if (err!=Z_OK)
-                break;
-        }
-    }
-
-    if (err==Z_OK)
-        return iRead;
-    return err;
-}
-
-
-/*
-  Give the current position in uncompressed data
-*/
-extern z_off_t ZEXPORT unztell (file)
-    unzFile file;
-{
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    pfile_in_zip_read_info=s->pfile_in_zip_read;
-
-    if (pfile_in_zip_read_info==NULL)
-        return UNZ_PARAMERROR;
-
-    return (z_off_t)pfile_in_zip_read_info->stream.total_out;
-}
-
-
-/*
-  return 1 if the end of file was reached, 0 elsewhere
-*/
-extern int ZEXPORT unzeof (file)
-    unzFile file;
-{
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    pfile_in_zip_read_info=s->pfile_in_zip_read;
-
-    if (pfile_in_zip_read_info==NULL)
-        return UNZ_PARAMERROR;
-
-    if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
-        return 1;
-    else
-        return 0;
-}
-
-
-
-/*
-  Read extra field from the current file (opened by unzOpenCurrentFile)
-  This is the local-header version of the extra field (sometimes, there is
-    more info in the local-header version than in the central-header)
-
-  if buf==NULL, it return the size of the local extra field that can be read
-
-  if buf!=NULL, len is the size of the buffer, the extra header is copied in
-    buf.
-  the return value is the number of bytes copied in buf, or (if <0)
-    the error code
-*/
-extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
-    unzFile file;
-    voidp buf;
-    unsigned len;
-{
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
-    uInt read_now;
-    uLong size_to_read;
-
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    pfile_in_zip_read_info=s->pfile_in_zip_read;
-
-    if (pfile_in_zip_read_info==NULL)
-        return UNZ_PARAMERROR;
-
-    size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
-                pfile_in_zip_read_info->pos_local_extrafield);
-
-    if (buf==NULL)
-        return (int)size_to_read;
-
-    if (len>size_to_read)
-        read_now = (uInt)size_to_read;
-    else
-        read_now = (uInt)len ;
-
-    if (read_now==0)
-        return 0;
-
-    if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
-              pfile_in_zip_read_info->filestream,
-              pfile_in_zip_read_info->offset_local_extrafield +
-              pfile_in_zip_read_info->pos_local_extrafield,
-              ZLIB_FILEFUNC_SEEK_SET)!=0)
-        return UNZ_ERRNO;
-
-    if (ZREAD(pfile_in_zip_read_info->z_filefunc,
-              pfile_in_zip_read_info->filestream,
-              buf,read_now)!=read_now)
-        return UNZ_ERRNO;
-
-    return (int)read_now;
-}
-
-/*
-  Close the file in zip opened with unzipOpenCurrentFile
-  Return UNZ_CRCERROR if all the file was read but the CRC is not good
-*/
-extern int ZEXPORT unzCloseCurrentFile (file)
-    unzFile file;
-{
-    int err=UNZ_OK;
-
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    pfile_in_zip_read_info=s->pfile_in_zip_read;
-
-    if (pfile_in_zip_read_info==NULL)
-        return UNZ_PARAMERROR;
-
-
-    if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
-        (!pfile_in_zip_read_info->raw))
-    {
-        if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
-            err=UNZ_CRCERROR;
-    }
-
-
-    TRYFREE(pfile_in_zip_read_info->read_buffer);
-    pfile_in_zip_read_info->read_buffer = NULL;
-    if (pfile_in_zip_read_info->stream_initialised)
-        inflateEnd(&pfile_in_zip_read_info->stream);
-
-    pfile_in_zip_read_info->stream_initialised = 0;
-    TRYFREE(pfile_in_zip_read_info);
-
-    s->pfile_in_zip_read=NULL;
-
-    return err;
-}
-
-
-/*
-  Get the global comment string of the ZipFile, in the szComment buffer.
-  uSizeBuf is the size of the szComment buffer.
-  return the number of byte copied or an error code <0
-*/
-extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
-    unzFile file;
-    char *szComment;
-    uLong uSizeBuf;
-{
-    int err=UNZ_OK;
-    unz_s* s;
-    uLong uReadThis ;
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-
-    uReadThis = uSizeBuf;
-    if (uReadThis>s->gi.size_comment)
-        uReadThis = s->gi.size_comment;
-
-    if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
-        return UNZ_ERRNO;
-
-    if (uReadThis>0)
-    {
-      *szComment='\0';
-      if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
-        return UNZ_ERRNO;
-    }
-
-    if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
-        *(szComment+s->gi.size_comment)='\0';
-    return (int)uReadThis;
-}
-
-/* Additions by RX '2004 */
-extern uLong ZEXPORT unzGetOffset (file)
-    unzFile file;
-{
-    unz_s* s;
-
-    if (file==NULL)
-          return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    if (!s->current_file_ok)
-      return 0;
-    if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
-      if (s->num_file==s->gi.number_entry)
-         return 0;
-    return s->pos_in_central_dir;
-}
-
-extern int ZEXPORT unzSetOffset (file, pos)
-        unzFile file;
-        uLong pos;
-{
-    unz_s* s;
-    int err;
-
-    if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-
-    s->pos_in_central_dir = pos;
-    s->num_file = s->gi.number_entry;      /* hack */
-    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
-                                              &s->cur_file_info_internal,
-                                              NULL,0,NULL,0,NULL,0);
-    s->current_file_ok = (err == UNZ_OK);
-    return err;
-}
+/* unzip.c -- IO for uncompress .zip files using zlib\r
+   Version 1.01e, February 12th, 2005\r
+\r
+   Copyright (C) 1998-2005 Gilles Vollant\r
+\r
+   Read unzip.h for more info\r
+*/\r
+\r
+/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of\r
+compatibility with older software. The following is from the original crypt.c. Code\r
+woven in by Terry Thorsen 1/2003.\r
+*/\r
+/*\r
+  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\r
+\r
+  See the accompanying file LICENSE, version 2000-Apr-09 or later\r
+  (the contents of which are also included in zip.h) for terms of use.\r
+  If, for some reason, all these files are missing, the Info-ZIP license\r
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\r
+*/\r
+/*\r
+  crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]\r
+\r
+  The encryption/decryption parts of this source code (as opposed to the\r
+  non-echoing password parts) were originally written in Europe.  The\r
+  whole source package can be freely distributed, including from the USA.\r
+  (Prior to January 2000, re-export from the US was a violation of US law.)\r
+ */\r
+\r
+/*\r
+  This encryption code is a direct transcription of the algorithm from\r
+  Roger Schlafly, described by Phil Katz in the file appnote.txt.  This\r
+  file (appnote.txt) is distributed with the PKZIP program (even in the\r
+  version without encryption capabilities).\r
+ */\r
+\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "zlib.h"\r
+#include "unzip.h"\r
+\r
+#ifdef STDC\r
+#  include <stddef.h>\r
+#  include <string.h>\r
+#  include <stdlib.h>\r
+#endif\r
+#ifdef NO_ERRNO_H\r
+    extern int errno;\r
+#else\r
+#   include <errno.h>\r
+#endif\r
+\r
+\r
+#ifndef local\r
+#  define local static\r
+#endif\r
+/* compile with -Dlocal if your debugger can't find static symbols */\r
+\r
+\r
+#ifndef CASESENSITIVITYDEFAULT_NO\r
+#  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)\r
+#    define CASESENSITIVITYDEFAULT_NO\r
+#  endif\r
+#endif\r
+\r
+\r
+#ifndef UNZ_BUFSIZE\r
+#define UNZ_BUFSIZE (16384)\r
+#endif\r
+\r
+#ifndef UNZ_MAXFILENAMEINZIP\r
+#define UNZ_MAXFILENAMEINZIP (256)\r
+#endif\r
+\r
+#ifndef ALLOC\r
+# define ALLOC(size) (malloc(size))\r
+#endif\r
+#ifndef TRYFREE\r
+# define TRYFREE(p) {if (p) free(p);}\r
+#endif\r
+\r
+#define SIZECENTRALDIRITEM (0x2e)\r
+#define SIZEZIPLOCALHEADER (0x1e)\r
+\r
+\r
+\r
+\r
+const char unz_copyright[] =\r
+   " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";\r
+\r
+/* unz_file_info_interntal contain internal info about a file in zipfile*/\r
+typedef struct unz_file_info_internal_s\r
+{\r
+    uLong offset_curfile;/* relative offset of local header 4 bytes */\r
+} unz_file_info_internal;\r
+\r
+\r
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,\r
+    when reading and decompress it */\r
+typedef struct\r
+{\r
+    char  *read_buffer;         /* internal buffer for compressed data */\r
+    z_stream stream;            /* zLib stream structure for inflate */\r
+\r
+    uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/\r
+    uLong stream_initialised;   /* flag set if stream structure is initialised*/\r
+\r
+    uLong offset_local_extrafield;/* offset of the local extra field */\r
+    uInt  size_local_extrafield;/* size of the local extra field */\r
+    uLong pos_local_extrafield;   /* position in the local extra field in read*/\r
+\r
+    uLong crc32;                /* crc32 of all data uncompressed */\r
+    uLong crc32_wait;           /* crc32 we must obtain after decompress all */\r
+    uLong rest_read_compressed; /* number of byte to be decompressed */\r
+    uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/\r
+    zlib_filefunc_def z_filefunc;\r
+    voidpf filestream;        /* io structore of the zipfile */\r
+    uLong compression_method;   /* compression method (0==store) */\r
+    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/\r
+    int   raw;\r
+} file_in_zip_read_info_s;\r
+\r
+\r
+/* unz_s contain internal information about the zipfile\r
+*/\r
+typedef struct\r
+{\r
+    zlib_filefunc_def z_filefunc;\r
+    voidpf filestream;        /* io structore of the zipfile */\r
+    unz_global_info gi;       /* public global information */\r
+    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/\r
+    uLong num_file;             /* number of the current file in the zipfile*/\r
+    uLong pos_in_central_dir;   /* pos of the current file in the central dir*/\r
+    uLong current_file_ok;      /* flag about the usability of the current file*/\r
+    uLong central_pos;          /* position of the beginning of the central dir*/\r
+\r
+    uLong size_central_dir;     /* size of the central directory  */\r
+    uLong offset_central_dir;   /* offset of start of central directory with\r
+                                   respect to the starting disk number */\r
+\r
+    unz_file_info cur_file_info; /* public info about the current file in zip*/\r
+    unz_file_info_internal cur_file_info_internal; /* private info about it*/\r
+    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current\r
+                                        file if we are decompressing it */\r
+    int encrypted;\r
+#    ifndef NOUNCRYPT\r
+    unsigned long keys[3];     /* keys defining the pseudo-random sequence */\r
+    const unsigned long* pcrc_32_tab;\r
+#    endif\r
+} unz_s;\r
+\r
+\r
+#ifndef NOUNCRYPT\r
+#include "crypt.h"\r
+#endif\r
+\r
+/* ===========================================================================\r
+     Read a byte from a gz_stream; update next_in and avail_in. Return EOF\r
+   for end of file.\r
+   IN assertion: the stream s has been sucessfully opened for reading.\r
+*/\r
+\r
+\r
+local int unzlocal_getByte OF((\r
+    const zlib_filefunc_def* pzlib_filefunc_def,\r
+    voidpf filestream,\r
+    int *pi));\r
+\r
+local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)\r
+    const zlib_filefunc_def* pzlib_filefunc_def;\r
+    voidpf filestream;\r
+    int *pi;\r
+{\r
+    unsigned char c;\r
+    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);\r
+    if (err==1)\r
+    {\r
+        *pi = (int)c;\r
+        return UNZ_OK;\r
+    }\r
+    else\r
+    {\r
+        if (ZERROR(*pzlib_filefunc_def,filestream))\r
+            return UNZ_ERRNO;\r
+        else\r
+            return UNZ_EOF;\r
+    }\r
+}\r
+\r
+\r
+/* ===========================================================================\r
+   Reads a long in LSB order from the given gz_stream. Sets\r
+*/\r
+local int unzlocal_getShort OF((\r
+    const zlib_filefunc_def* pzlib_filefunc_def,\r
+    voidpf filestream,\r
+    uLong *pX));\r
+\r
+local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)\r
+    const zlib_filefunc_def* pzlib_filefunc_def;\r
+    voidpf filestream;\r
+    uLong *pX;\r
+{\r
+    uLong x ;\r
+    int i;\r
+    int err;\r
+\r
+    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x = (uLong)i;\r
+\r
+    if (err==UNZ_OK)\r
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x += ((uLong)i)<<8;\r
+\r
+    if (err==UNZ_OK)\r
+        *pX = x;\r
+    else\r
+        *pX = 0;\r
+    return err;\r
+}\r
+\r
+local int unzlocal_getLong OF((\r
+    const zlib_filefunc_def* pzlib_filefunc_def,\r
+    voidpf filestream,\r
+    uLong *pX));\r
+\r
+local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)\r
+    const zlib_filefunc_def* pzlib_filefunc_def;\r
+    voidpf filestream;\r
+    uLong *pX;\r
+{\r
+    uLong x ;\r
+    int i;\r
+    int err;\r
+\r
+    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x = (uLong)i;\r
+\r
+    if (err==UNZ_OK)\r
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x += ((uLong)i)<<8;\r
+\r
+    if (err==UNZ_OK)\r
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x += ((uLong)i)<<16;\r
+\r
+    if (err==UNZ_OK)\r
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x += ((uLong)i)<<24;\r
+\r
+    if (err==UNZ_OK)\r
+        *pX = x;\r
+    else\r
+        *pX = 0;\r
+    return err;\r
+}\r
+\r
+\r
+/* My own strcmpi / strcasecmp */\r
+local int strcmpcasenosensitive_internal (fileName1,fileName2)\r
+    const char* fileName1;\r
+    const char* fileName2;\r
+{\r
+    for (;;)\r
+    {\r
+        char c1=*(fileName1++);\r
+        char c2=*(fileName2++);\r
+        if ((c1>='a') && (c1<='z'))\r
+            c1 -= 0x20;\r
+        if ((c2>='a') && (c2<='z'))\r
+            c2 -= 0x20;\r
+        if (c1=='\0')\r
+            return ((c2=='\0') ? 0 : -1);\r
+        if (c2=='\0')\r
+            return 1;\r
+        if (c1<c2)\r
+            return -1;\r
+        if (c1>c2)\r
+            return 1;\r
+    }\r
+}\r
+\r
+\r
+#ifdef  CASESENSITIVITYDEFAULT_NO\r
+#define CASESENSITIVITYDEFAULTVALUE 2\r
+#else\r
+#define CASESENSITIVITYDEFAULTVALUE 1\r
+#endif\r
+\r
+#ifndef STRCMPCASENOSENTIVEFUNCTION\r
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal\r
+#endif\r
+\r
+/*\r
+   Compare two filename (fileName1,fileName2).\r
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)\r
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi\r
+                                                                or strcasecmp)\r
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system\r
+        (like 1 on Unix, 2 on Windows)\r
+\r
+*/\r
+extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)\r
+    const char* fileName1;\r
+    const char* fileName2;\r
+    int iCaseSensitivity;\r
+{\r
+    if (iCaseSensitivity==0)\r
+        iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;\r
+\r
+    if (iCaseSensitivity==1)\r
+        return strcmp(fileName1,fileName2);\r
+\r
+    return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);\r
+}\r
+\r
+#ifndef BUFREADCOMMENT\r
+#define BUFREADCOMMENT (0x400)\r
+#endif\r
+\r
+/*\r
+  Locate the Central directory of a zipfile (at the end, just before\r
+    the global comment)\r
+*/\r
+local uLong unzlocal_SearchCentralDir OF((\r
+    const zlib_filefunc_def* pzlib_filefunc_def,\r
+    voidpf filestream));\r
+\r
+local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)\r
+    const zlib_filefunc_def* pzlib_filefunc_def;\r
+    voidpf filestream;\r
+{\r
+    unsigned char* buf;\r
+    uLong uSizeFile;\r
+    uLong uBackRead;\r
+    uLong uMaxBack=0xffff; /* maximum size of global comment */\r
+    uLong uPosFound=0;\r
+\r
+    if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)\r
+        return 0;\r
+\r
+\r
+    uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);\r
+\r
+    if (uMaxBack>uSizeFile)\r
+        uMaxBack = uSizeFile;\r
+\r
+    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);\r
+    if (buf==NULL)\r
+        return 0;\r
+\r
+    uBackRead = 4;\r
+    while (uBackRead<uMaxBack)\r
+    {\r
+        uLong uReadSize,uReadPos ;\r
+        int i;\r
+        if (uBackRead+BUFREADCOMMENT>uMaxBack)\r
+            uBackRead = uMaxBack;\r
+        else\r
+            uBackRead+=BUFREADCOMMENT;\r
+        uReadPos = uSizeFile-uBackRead ;\r
+\r
+        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?\r
+                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);\r
+        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+            break;\r
+\r
+        if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)\r
+            break;\r
+\r
+        for (i=(int)uReadSize-3; (i--)>0;)\r
+            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&\r
+                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))\r
+            {\r
+                uPosFound = uReadPos+i;\r
+                break;\r
+            }\r
+\r
+        if (uPosFound!=0)\r
+            break;\r
+    }\r
+    TRYFREE(buf);\r
+    return uPosFound;\r
+}\r
+\r
+/*\r
+  Open a Zip file. path contain the full pathname (by example,\r
+     on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer\r
+     "zlib/zlib114.zip".\r
+     If the zipfile cannot be opened (file doesn't exist or in not valid), the\r
+       return value is NULL.\r
+     Else, the return value is a unzFile Handle, usable with other function\r
+       of this unzip package.\r
+*/\r
+extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)\r
+    const char *path;\r
+    zlib_filefunc_def* pzlib_filefunc_def;\r
+{\r
+    unz_s us;\r
+    unz_s *s;\r
+    uLong central_pos,uL;\r
+\r
+    uLong number_disk;          /* number of the current dist, used for\r
+                                   spaning ZIP, unsupported, always 0*/\r
+    uLong number_disk_with_CD;  /* number the the disk with central dir, used\r
+                                   for spaning ZIP, unsupported, always 0*/\r
+    uLong number_entry_CD;      /* total number of entries in\r
+                                   the central dir\r
+                                   (same than number_entry on nospan) */\r
+\r
+    int err=UNZ_OK;\r
+\r
+    if (unz_copyright[0]!=' ')\r
+        return NULL;\r
+\r
+    if (pzlib_filefunc_def==NULL)\r
+        fill_fopen_filefunc(&us.z_filefunc);\r
+    else\r
+        us.z_filefunc = *pzlib_filefunc_def;\r
+\r
+    us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,\r
+                                                 path,\r
+                                                 ZLIB_FILEFUNC_MODE_READ |\r
+                                                 ZLIB_FILEFUNC_MODE_EXISTING);\r
+    if (us.filestream==NULL)\r
+        return NULL;\r
+\r
+    central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);\r
+    if (central_pos==0)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (ZSEEK(us.z_filefunc, us.filestream,\r
+                                      central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+        err=UNZ_ERRNO;\r
+\r
+    /* the signature, already checked */\r
+    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    /* number of this disk */\r
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    /* number of the disk with the start of the central directory */\r
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    /* total number of entries in the central dir on this disk */\r
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    /* total number of entries in the central dir */\r
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if ((number_entry_CD!=us.gi.number_entry) ||\r
+        (number_disk_with_CD!=0) ||\r
+        (number_disk!=0))\r
+        err=UNZ_BADZIPFILE;\r
+\r
+    /* size of the central directory */\r
+    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    /* offset of start of central directory with respect to the\r
+          starting disk number */\r
+    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    /* zipfile comment length */\r
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if ((central_pos<us.offset_central_dir+us.size_central_dir) &&\r
+        (err==UNZ_OK))\r
+        err=UNZ_BADZIPFILE;\r
+\r
+    if (err!=UNZ_OK)\r
+    {\r
+        ZCLOSE(us.z_filefunc, us.filestream);\r
+        return NULL;\r
+    }\r
+\r
+    us.byte_before_the_zipfile = central_pos -\r
+                            (us.offset_central_dir+us.size_central_dir);\r
+    us.central_pos = central_pos;\r
+    us.pfile_in_zip_read = NULL;\r
+    us.encrypted = 0;\r
+\r
+\r
+    s=(unz_s*)ALLOC(sizeof(unz_s));\r
+    *s=us;\r
+    unzGoToFirstFile((unzFile)s);\r
+    return (unzFile)s;\r
+}\r
+\r
+\r
+extern unzFile ZEXPORT unzOpen (path)\r
+    const char *path;\r
+{\r
+    return unzOpen2(path, NULL);\r
+}\r
+\r
+/*\r
+  Close a ZipFile opened with unzipOpen.\r
+  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),\r
+    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.\r
+  return UNZ_OK if there is no problem. */\r
+extern int ZEXPORT unzClose (file)\r
+    unzFile file;\r
+{\r
+    unz_s* s;\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+\r
+    if (s->pfile_in_zip_read!=NULL)\r
+        unzCloseCurrentFile(file);\r
+\r
+    ZCLOSE(s->z_filefunc, s->filestream);\r
+    TRYFREE(s);\r
+    return UNZ_OK;\r
+}\r
+\r
+\r
+/*\r
+  Write info about the ZipFile in the *pglobal_info structure.\r
+  No preparation of the structure is needed\r
+  return UNZ_OK if there is no problem. */\r
+extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)\r
+    unzFile file;\r
+    unz_global_info *pglobal_info;\r
+{\r
+    unz_s* s;\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    *pglobal_info=s->gi;\r
+    return UNZ_OK;\r
+}\r
+\r
+\r
+/*\r
+   Translate date/time from Dos format to tm_unz (readable more easilty)\r
+*/\r
+local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)\r
+    uLong ulDosDate;\r
+    tm_unz* ptm;\r
+{\r
+    uLong uDate;\r
+    uDate = (uLong)(ulDosDate>>16);\r
+    ptm->tm_mday = (uInt)(uDate&0x1f) ;\r
+    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;\r
+    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;\r
+\r
+    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);\r
+    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;\r
+    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;\r
+}\r
+\r
+/*\r
+  Get Info about the current file in the zipfile, with internal only info\r
+*/\r
+local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,\r
+                                                  unz_file_info *pfile_info,\r
+                                                  unz_file_info_internal\r
+                                                  *pfile_info_internal,\r
+                                                  char *szFileName,\r
+                                                  uLong fileNameBufferSize,\r
+                                                  void *extraField,\r
+                                                  uLong extraFieldBufferSize,\r
+                                                  char *szComment,\r
+                                                  uLong commentBufferSize));\r
+\r
+local int unzlocal_GetCurrentFileInfoInternal (file,\r
+                                              pfile_info,\r
+                                              pfile_info_internal,\r
+                                              szFileName, fileNameBufferSize,\r
+                                              extraField, extraFieldBufferSize,\r
+                                              szComment,  commentBufferSize)\r
+    unzFile file;\r
+    unz_file_info *pfile_info;\r
+    unz_file_info_internal *pfile_info_internal;\r
+    char *szFileName;\r
+    uLong fileNameBufferSize;\r
+    void *extraField;\r
+    uLong extraFieldBufferSize;\r
+    char *szComment;\r
+    uLong commentBufferSize;\r
+{\r
+    unz_s* s;\r
+    unz_file_info file_info;\r
+    unz_file_info_internal file_info_internal;\r
+    int err=UNZ_OK;\r
+    uLong uMagic;\r
+    long lSeek=0;\r
+\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    if (ZSEEK(s->z_filefunc, s->filestream,\r
+              s->pos_in_central_dir+s->byte_before_the_zipfile,\r
+              ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+        err=UNZ_ERRNO;\r
+\r
+\r
+    /* we check the magic */\r
+    if (err==UNZ_OK)\r
+        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)\r
+            err=UNZ_ERRNO;\r
+        else if (uMagic!=0x02014b50)\r
+            err=UNZ_BADZIPFILE;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);\r
+\r
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    lSeek+=file_info.size_filename;\r
+    if ((err==UNZ_OK) && (szFileName!=NULL))\r
+    {\r
+        uLong uSizeRead ;\r
+        if (file_info.size_filename<fileNameBufferSize)\r
+        {\r
+            *(szFileName+file_info.size_filename)='\0';\r
+            uSizeRead = file_info.size_filename;\r
+        }\r
+        else\r
+            uSizeRead = fileNameBufferSize;\r
+\r
+        if ((file_info.size_filename>0) && (fileNameBufferSize>0))\r
+            if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)\r
+                err=UNZ_ERRNO;\r
+        lSeek -= uSizeRead;\r
+    }\r
+\r
+\r
+    if ((err==UNZ_OK) && (extraField!=NULL))\r
+    {\r
+        uLong uSizeRead ;\r
+        if (file_info.size_file_extra<extraFieldBufferSize)\r
+            uSizeRead = file_info.size_file_extra;\r
+        else\r
+            uSizeRead = extraFieldBufferSize;\r
+\r
+        if (lSeek!=0)\r
+            if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)\r
+                lSeek=0;\r
+            else\r
+                err=UNZ_ERRNO;\r
+        if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))\r
+            if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)\r
+                err=UNZ_ERRNO;\r
+        lSeek += file_info.size_file_extra - uSizeRead;\r
+    }\r
+    else\r
+        lSeek+=file_info.size_file_extra;\r
+\r
+\r
+    if ((err==UNZ_OK) && (szComment!=NULL))\r
+    {\r
+        uLong uSizeRead ;\r
+        if (file_info.size_file_comment<commentBufferSize)\r
+        {\r
+            *(szComment+file_info.size_file_comment)='\0';\r
+            uSizeRead = file_info.size_file_comment;\r
+        }\r
+        else\r
+            uSizeRead = commentBufferSize;\r
+\r
+        if (lSeek!=0)\r
+            if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)\r
+                lSeek=0;\r
+            else\r
+                err=UNZ_ERRNO;\r
+        if ((file_info.size_file_comment>0) && (commentBufferSize>0))\r
+            if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)\r
+                err=UNZ_ERRNO;\r
+        lSeek+=file_info.size_file_comment - uSizeRead;\r
+    }\r
+    else\r
+        lSeek+=file_info.size_file_comment;\r
+\r
+    if ((err==UNZ_OK) && (pfile_info!=NULL))\r
+        *pfile_info=file_info;\r
+\r
+    if ((err==UNZ_OK) && (pfile_info_internal!=NULL))\r
+        *pfile_info_internal=file_info_internal;\r
+\r
+    return err;\r
+}\r
+\r
+\r
+\r
+/*\r
+  Write info about the ZipFile in the *pglobal_info structure.\r
+  No preparation of the structure is needed\r
+  return UNZ_OK if there is no problem.\r
+*/\r
+extern int ZEXPORT unzGetCurrentFileInfo (file,\r
+                                          pfile_info,\r
+                                          szFileName, fileNameBufferSize,\r
+                                          extraField, extraFieldBufferSize,\r
+                                          szComment,  commentBufferSize)\r
+    unzFile file;\r
+    unz_file_info *pfile_info;\r
+    char *szFileName;\r
+    uLong fileNameBufferSize;\r
+    void *extraField;\r
+    uLong extraFieldBufferSize;\r
+    char *szComment;\r
+    uLong commentBufferSize;\r
+{\r
+    return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,\r
+                                                szFileName,fileNameBufferSize,\r
+                                                extraField,extraFieldBufferSize,\r
+                                                szComment,commentBufferSize);\r
+}\r
+\r
+/*\r
+  Set the current file of the zipfile to the first file.\r
+  return UNZ_OK if there is no problem\r
+*/\r
+extern int ZEXPORT unzGoToFirstFile (file)\r
+    unzFile file;\r
+{\r
+    int err=UNZ_OK;\r
+    unz_s* s;\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    s->pos_in_central_dir=s->offset_central_dir;\r
+    s->num_file=0;\r
+    err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r
+                                             &s->cur_file_info_internal,\r
+                                             NULL,0,NULL,0,NULL,0);\r
+    s->current_file_ok = (err == UNZ_OK);\r
+    return err;\r
+}\r
+\r
+/*\r
+  Set the current file of the zipfile to the next file.\r
+  return UNZ_OK if there is no problem\r
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.\r
+*/\r
+extern int ZEXPORT unzGoToNextFile (file)\r
+    unzFile file;\r
+{\r
+    unz_s* s;\r
+    int err;\r
+\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    if (!s->current_file_ok)\r
+        return UNZ_END_OF_LIST_OF_FILE;\r
+    if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */\r
+      if (s->num_file+1==s->gi.number_entry)\r
+        return UNZ_END_OF_LIST_OF_FILE;\r
+\r
+    s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +\r
+            s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;\r
+    s->num_file++;\r
+    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r
+                                               &s->cur_file_info_internal,\r
+                                               NULL,0,NULL,0,NULL,0);\r
+    s->current_file_ok = (err == UNZ_OK);\r
+    return err;\r
+}\r
+\r
+\r
+/*\r
+  Try locate the file szFileName in the zipfile.\r
+  For the iCaseSensitivity signification, see unzipStringFileNameCompare\r
+\r
+  return value :\r
+  UNZ_OK if the file is found. It becomes the current file.\r
+  UNZ_END_OF_LIST_OF_FILE if the file is not found\r
+*/\r
+extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)\r
+    unzFile file;\r
+    const char *szFileName;\r
+    int iCaseSensitivity;\r
+{\r
+    unz_s* s;\r
+    int err;\r
+\r
+    /* We remember the 'current' position in the file so that we can jump\r
+     * back there if we fail.\r
+     */\r
+    unz_file_info cur_file_infoSaved;\r
+    unz_file_info_internal cur_file_info_internalSaved;\r
+    uLong num_fileSaved;\r
+    uLong pos_in_central_dirSaved;\r
+\r
+\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+\r
+    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)\r
+        return UNZ_PARAMERROR;\r
+\r
+    s=(unz_s*)file;\r
+    if (!s->current_file_ok)\r
+        return UNZ_END_OF_LIST_OF_FILE;\r
+\r
+    /* Save the current state */\r
+    num_fileSaved = s->num_file;\r
+    pos_in_central_dirSaved = s->pos_in_central_dir;\r
+    cur_file_infoSaved = s->cur_file_info;\r
+    cur_file_info_internalSaved = s->cur_file_info_internal;\r
+\r
+    err = unzGoToFirstFile(file);\r
+\r
+    while (err == UNZ_OK)\r
+    {\r
+        char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];\r
+        err = unzGetCurrentFileInfo(file,NULL,\r
+                                    szCurrentFileName,sizeof(szCurrentFileName)-1,\r
+                                    NULL,0,NULL,0);\r
+        if (err == UNZ_OK)\r
+        {\r
+            if (unzStringFileNameCompare(szCurrentFileName,\r
+                                            szFileName,iCaseSensitivity)==0)\r
+                return UNZ_OK;\r
+            err = unzGoToNextFile(file);\r
+        }\r
+    }\r
+\r
+    /* We failed, so restore the state of the 'current file' to where we\r
+     * were.\r
+     */\r
+    s->num_file = num_fileSaved ;\r
+    s->pos_in_central_dir = pos_in_central_dirSaved ;\r
+    s->cur_file_info = cur_file_infoSaved;\r
+    s->cur_file_info_internal = cur_file_info_internalSaved;\r
+    return err;\r
+}\r
+\r
+\r
+/*\r
+///////////////////////////////////////////\r
+// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)\r
+// I need random access\r
+//\r
+// Further optimization could be realized by adding an ability\r
+// to cache the directory in memory. The goal being a single\r
+// comprehensive file read to put the file I need in a memory.\r
+*/\r
+\r
+/*\r
+typedef struct unz_file_pos_s\r
+{\r
+    uLong pos_in_zip_directory;   // offset in file\r
+    uLong num_of_file;            // # of file\r
+} unz_file_pos;\r
+*/\r
+\r
+extern int ZEXPORT unzGetFilePos(file, file_pos)\r
+    unzFile file;\r
+    unz_file_pos* file_pos;\r
+{\r
+    unz_s* s;\r
+\r
+    if (file==NULL || file_pos==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    if (!s->current_file_ok)\r
+        return UNZ_END_OF_LIST_OF_FILE;\r
+\r
+    file_pos->pos_in_zip_directory  = s->pos_in_central_dir;\r
+    file_pos->num_of_file           = s->num_file;\r
+\r
+    return UNZ_OK;\r
+}\r
+\r
+extern int ZEXPORT unzGoToFilePos(file, file_pos)\r
+    unzFile file;\r
+    unz_file_pos* file_pos;\r
+{\r
+    unz_s* s;\r
+    int err;\r
+\r
+    if (file==NULL || file_pos==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+\r
+    /* jump to the right spot */\r
+    s->pos_in_central_dir = file_pos->pos_in_zip_directory;\r
+    s->num_file           = file_pos->num_of_file;\r
+\r
+    /* set the current file */\r
+    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r
+                                               &s->cur_file_info_internal,\r
+                                               NULL,0,NULL,0,NULL,0);\r
+    /* return results */\r
+    s->current_file_ok = (err == UNZ_OK);\r
+    return err;\r
+}\r
+\r
+/*\r
+// Unzip Helper Functions - should be here?\r
+///////////////////////////////////////////\r
+*/\r
+\r
+/*\r
+  Read the local header of the current zipfile\r
+  Check the coherency of the local header and info in the end of central\r
+        directory about this file\r
+  store in *piSizeVar the size of extra info in local header\r
+        (filename and size of extra field data)\r
+*/\r
+local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,\r
+                                                    poffset_local_extrafield,\r
+                                                    psize_local_extrafield)\r
+    unz_s* s;\r
+    uInt* piSizeVar;\r
+    uLong *poffset_local_extrafield;\r
+    uInt  *psize_local_extrafield;\r
+{\r
+    uLong uMagic,uData,uFlags;\r
+    uLong size_filename;\r
+    uLong size_extra_field;\r
+    int err=UNZ_OK;\r
+\r
+    *piSizeVar = 0;\r
+    *poffset_local_extrafield = 0;\r
+    *psize_local_extrafield = 0;\r
+\r
+    if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +\r
+                                s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+        return UNZ_ERRNO;\r
+\r
+\r
+    if (err==UNZ_OK)\r
+        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)\r
+            err=UNZ_ERRNO;\r
+        else if (uMagic!=0x04034b50)\r
+            err=UNZ_BADZIPFILE;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+/*\r
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))\r
+        err=UNZ_BADZIPFILE;\r
+*/\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))\r
+        err=UNZ_BADZIPFILE;\r
+\r
+    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&\r
+                         (s->cur_file_info.compression_method!=Z_DEFLATED))\r
+        err=UNZ_BADZIPFILE;\r
+\r
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */\r
+        err=UNZ_ERRNO;\r
+\r
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */\r
+        err=UNZ_ERRNO;\r
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&\r
+                              ((uFlags & 8)==0))\r
+        err=UNZ_BADZIPFILE;\r
+\r
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */\r
+        err=UNZ_ERRNO;\r
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&\r
+                              ((uFlags & 8)==0))\r
+        err=UNZ_BADZIPFILE;\r
+\r
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */\r
+        err=UNZ_ERRNO;\r
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&\r
+                              ((uFlags & 8)==0))\r
+        err=UNZ_BADZIPFILE;\r
+\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+    else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))\r
+        err=UNZ_BADZIPFILE;\r
+\r
+    *piSizeVar += (uInt)size_filename;\r
+\r
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)\r
+        err=UNZ_ERRNO;\r
+    *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +\r
+                                    SIZEZIPLOCALHEADER + size_filename;\r
+    *psize_local_extrafield = (uInt)size_extra_field;\r
+\r
+    *piSizeVar += (uInt)size_extra_field;\r
+\r
+    return err;\r
+}\r
+\r
+/*\r
+  Open for reading data the current file in the zipfile.\r
+  If there is no error and the file is opened, the return value is UNZ_OK.\r
+*/\r
+extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)\r
+    unzFile file;\r
+    int* method;\r
+    int* level;\r
+    int raw;\r
+    const char* password;\r
+{\r
+    int err=UNZ_OK;\r
+    uInt iSizeVar;\r
+    unz_s* s;\r
+    file_in_zip_read_info_s* pfile_in_zip_read_info;\r
+    uLong offset_local_extrafield;  /* offset of the local extra field */\r
+    uInt  size_local_extrafield;    /* size of the local extra field */\r
+#    ifndef NOUNCRYPT\r
+    char source[12];\r
+#    else\r
+    if (password != NULL)\r
+        return UNZ_PARAMERROR;\r
+#    endif\r
+\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    if (!s->current_file_ok)\r
+        return UNZ_PARAMERROR;\r
+\r
+    if (s->pfile_in_zip_read != NULL)\r
+        unzCloseCurrentFile(file);\r
+\r
+    if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,\r
+                &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)\r
+        return UNZ_BADZIPFILE;\r
+\r
+    pfile_in_zip_read_info = (file_in_zip_read_info_s*)\r
+                                        ALLOC(sizeof(file_in_zip_read_info_s));\r
+    if (pfile_in_zip_read_info==NULL)\r
+        return UNZ_INTERNALERROR;\r
+\r
+    pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);\r
+    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;\r
+    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;\r
+    pfile_in_zip_read_info->pos_local_extrafield=0;\r
+    pfile_in_zip_read_info->raw=raw;\r
+\r
+    if (pfile_in_zip_read_info->read_buffer==NULL)\r
+    {\r
+        TRYFREE(pfile_in_zip_read_info);\r
+        return UNZ_INTERNALERROR;\r
+    }\r
+\r
+    pfile_in_zip_read_info->stream_initialised=0;\r
+\r
+    if (method!=NULL)\r
+        *method = (int)s->cur_file_info.compression_method;\r
+\r
+    if (level!=NULL)\r
+    {\r
+        *level = 6;\r
+        switch (s->cur_file_info.flag & 0x06)\r
+        {\r
+          case 6 : *level = 1; break;\r
+          case 4 : *level = 2; break;\r
+          case 2 : *level = 9; break;\r
+        }\r
+    }\r
+\r
+    if ((s->cur_file_info.compression_method!=0) &&\r
+        (s->cur_file_info.compression_method!=Z_DEFLATED))\r
+        err=UNZ_BADZIPFILE;\r
+\r
+    pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;\r
+    pfile_in_zip_read_info->crc32=0;\r
+    pfile_in_zip_read_info->compression_method =\r
+            s->cur_file_info.compression_method;\r
+    pfile_in_zip_read_info->filestream=s->filestream;\r
+    pfile_in_zip_read_info->z_filefunc=s->z_filefunc;\r
+    pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;\r
+\r
+    pfile_in_zip_read_info->stream.total_out = 0;\r
+\r
+    if ((s->cur_file_info.compression_method==Z_DEFLATED) &&\r
+        (!raw))\r
+    {\r
+      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;\r
+      pfile_in_zip_read_info->stream.zfree = (free_func)0;\r
+      pfile_in_zip_read_info->stream.opaque = (voidpf)0;\r
+      pfile_in_zip_read_info->stream.next_in = (voidpf)0;\r
+      pfile_in_zip_read_info->stream.avail_in = 0;\r
+\r
+      err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);\r
+      if (err == Z_OK)\r
+        pfile_in_zip_read_info->stream_initialised=1;\r
+      else\r
+      {\r
+        TRYFREE(pfile_in_zip_read_info);\r
+        return err;\r
+      }\r
+        /* windowBits is passed < 0 to tell that there is no zlib header.\r
+         * Note that in this case inflate *requires* an extra "dummy" byte\r
+         * after the compressed stream in order to complete decompression and\r
+         * return Z_STREAM_END.\r
+         * In unzip, i don't wait absolutely Z_STREAM_END because I known the\r
+         * size of both compressed and uncompressed data\r
+         */\r
+    }\r
+    pfile_in_zip_read_info->rest_read_compressed =\r
+            s->cur_file_info.compressed_size ;\r
+    pfile_in_zip_read_info->rest_read_uncompressed =\r
+            s->cur_file_info.uncompressed_size ;\r
+\r
+\r
+    pfile_in_zip_read_info->pos_in_zipfile =\r
+            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +\r
+              iSizeVar;\r
+\r
+    pfile_in_zip_read_info->stream.avail_in = (uInt)0;\r
+\r
+    s->pfile_in_zip_read = pfile_in_zip_read_info;\r
+\r
+#    ifndef NOUNCRYPT\r
+    if (password != NULL)\r
+    {\r
+        int i;\r
+        s->pcrc_32_tab = get_crc_table();\r
+        init_keys(password,s->keys,s->pcrc_32_tab);\r
+        if (ZSEEK(s->z_filefunc, s->filestream,\r
+                  s->pfile_in_zip_read->pos_in_zipfile +\r
+                     s->pfile_in_zip_read->byte_before_the_zipfile,\r
+                  SEEK_SET)!=0)\r
+            return UNZ_INTERNALERROR;\r
+        if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)\r
+            return UNZ_INTERNALERROR;\r
+\r
+        for (i = 0; i<12; i++)\r
+            zdecode(s->keys,s->pcrc_32_tab,source[i]);\r
+\r
+        s->pfile_in_zip_read->pos_in_zipfile+=12;\r
+        s->encrypted=1;\r
+    }\r
+#    endif\r
+\r
+\r
+    return UNZ_OK;\r
+}\r
+\r
+extern int ZEXPORT unzOpenCurrentFile (file)\r
+    unzFile file;\r
+{\r
+    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);\r
+}\r
+\r
+extern int ZEXPORT unzOpenCurrentFilePassword (file, password)\r
+    unzFile file;\r
+    const char* password;\r
+{\r
+    return unzOpenCurrentFile3(file, NULL, NULL, 0, password);\r
+}\r
+\r
+extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)\r
+    unzFile file;\r
+    int* method;\r
+    int* level;\r
+    int raw;\r
+{\r
+    return unzOpenCurrentFile3(file, method, level, raw, NULL);\r
+}\r
+\r
+/*\r
+  Read bytes from the current file.\r
+  buf contain buffer where data must be copied\r
+  len the size of buf.\r
+\r
+  return the number of byte copied if somes bytes are copied\r
+  return 0 if the end of file was reached\r
+  return <0 with error code if there is an error\r
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)\r
+*/\r
+extern int ZEXPORT unzReadCurrentFile  (file, buf, len)\r
+    unzFile file;\r
+    voidp buf;\r
+    unsigned len;\r
+{\r
+    int err=UNZ_OK;\r
+    uInt iRead = 0;\r
+    unz_s* s;\r
+    file_in_zip_read_info_s* pfile_in_zip_read_info;\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    pfile_in_zip_read_info=s->pfile_in_zip_read;\r
+\r
+    if (pfile_in_zip_read_info==NULL)\r
+        return UNZ_PARAMERROR;\r
+\r
+\r
+    if ((pfile_in_zip_read_info->read_buffer == NULL))\r
+        return UNZ_END_OF_LIST_OF_FILE;\r
+    if (len==0)\r
+        return 0;\r
+\r
+    pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;\r
+\r
+    pfile_in_zip_read_info->stream.avail_out = (uInt)len;\r
+\r
+    if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&\r
+        (!(pfile_in_zip_read_info->raw)))\r
+        pfile_in_zip_read_info->stream.avail_out =\r
+            (uInt)pfile_in_zip_read_info->rest_read_uncompressed;\r
+\r
+    if ((len>pfile_in_zip_read_info->rest_read_compressed+\r
+           pfile_in_zip_read_info->stream.avail_in) &&\r
+         (pfile_in_zip_read_info->raw))\r
+        pfile_in_zip_read_info->stream.avail_out =\r
+            (uInt)pfile_in_zip_read_info->rest_read_compressed+\r
+            pfile_in_zip_read_info->stream.avail_in;\r
+\r
+    while (pfile_in_zip_read_info->stream.avail_out>0)\r
+    {\r
+        if ((pfile_in_zip_read_info->stream.avail_in==0) &&\r
+            (pfile_in_zip_read_info->rest_read_compressed>0))\r
+        {\r
+            uInt uReadThis = UNZ_BUFSIZE;\r
+            if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)\r
+                uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;\r
+            if (uReadThis == 0)\r
+                return UNZ_EOF;\r
+            if (ZSEEK(pfile_in_zip_read_info->z_filefunc,\r
+                      pfile_in_zip_read_info->filestream,\r
+                      pfile_in_zip_read_info->pos_in_zipfile +\r
+                         pfile_in_zip_read_info->byte_before_the_zipfile,\r
+                         ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+                return UNZ_ERRNO;\r
+            if (ZREAD(pfile_in_zip_read_info->z_filefunc,\r
+                      pfile_in_zip_read_info->filestream,\r
+                      pfile_in_zip_read_info->read_buffer,\r
+                      uReadThis)!=uReadThis)\r
+                return UNZ_ERRNO;\r
+\r
+\r
+#            ifndef NOUNCRYPT\r
+            if(s->encrypted)\r
+            {\r
+                uInt i;\r
+                for(i=0;i<uReadThis;i++)\r
+                  pfile_in_zip_read_info->read_buffer[i] =\r
+                      zdecode(s->keys,s->pcrc_32_tab,\r
+                              pfile_in_zip_read_info->read_buffer[i]);\r
+            }\r
+#            endif\r
+\r
+\r
+            pfile_in_zip_read_info->pos_in_zipfile += uReadThis;\r
+\r
+            pfile_in_zip_read_info->rest_read_compressed-=uReadThis;\r
+\r
+            pfile_in_zip_read_info->stream.next_in =\r
+                (Bytef*)pfile_in_zip_read_info->read_buffer;\r
+            pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;\r
+        }\r
+\r
+        if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))\r
+        {\r
+            uInt uDoCopy,i ;\r
+\r
+            if ((pfile_in_zip_read_info->stream.avail_in == 0) &&\r
+                (pfile_in_zip_read_info->rest_read_compressed == 0))\r
+                return (iRead==0) ? UNZ_EOF : iRead;\r
+\r
+            if (pfile_in_zip_read_info->stream.avail_out <\r
+                            pfile_in_zip_read_info->stream.avail_in)\r
+                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;\r
+            else\r
+                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;\r
+\r
+            for (i=0;i<uDoCopy;i++)\r
+                *(pfile_in_zip_read_info->stream.next_out+i) =\r
+                        *(pfile_in_zip_read_info->stream.next_in+i);\r
+\r
+            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,\r
+                                pfile_in_zip_read_info->stream.next_out,\r
+                                uDoCopy);\r
+            pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;\r
+            pfile_in_zip_read_info->stream.avail_in -= uDoCopy;\r
+            pfile_in_zip_read_info->stream.avail_out -= uDoCopy;\r
+            pfile_in_zip_read_info->stream.next_out += uDoCopy;\r
+            pfile_in_zip_read_info->stream.next_in += uDoCopy;\r
+            pfile_in_zip_read_info->stream.total_out += uDoCopy;\r
+            iRead += uDoCopy;\r
+        }\r
+        else\r
+        {\r
+            uLong uTotalOutBefore,uTotalOutAfter;\r
+            const Bytef *bufBefore;\r
+            uLong uOutThis;\r
+            int flush=Z_SYNC_FLUSH;\r
+\r
+            uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;\r
+            bufBefore = pfile_in_zip_read_info->stream.next_out;\r
+\r
+            /*\r
+            if ((pfile_in_zip_read_info->rest_read_uncompressed ==\r
+                     pfile_in_zip_read_info->stream.avail_out) &&\r
+                (pfile_in_zip_read_info->rest_read_compressed == 0))\r
+                flush = Z_FINISH;\r
+            */\r
+            err=inflate(&pfile_in_zip_read_info->stream,flush);\r
+\r
+            if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))\r
+              err = Z_DATA_ERROR;\r
+\r
+            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;\r
+            uOutThis = uTotalOutAfter-uTotalOutBefore;\r
+\r
+            pfile_in_zip_read_info->crc32 =\r
+                crc32(pfile_in_zip_read_info->crc32,bufBefore,\r
+                        (uInt)(uOutThis));\r
+\r
+            pfile_in_zip_read_info->rest_read_uncompressed -=\r
+                uOutThis;\r
+\r
+            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);\r
+\r
+            if (err==Z_STREAM_END)\r
+                return (iRead==0) ? UNZ_EOF : iRead;\r
+            if (err!=Z_OK)\r
+                break;\r
+        }\r
+    }\r
+\r
+    if (err==Z_OK)\r
+        return iRead;\r
+    return err;\r
+}\r
+\r
+\r
+/*\r
+  Give the current position in uncompressed data\r
+*/\r
+extern z_off_t ZEXPORT unztell (file)\r
+    unzFile file;\r
+{\r
+    unz_s* s;\r
+    file_in_zip_read_info_s* pfile_in_zip_read_info;\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    pfile_in_zip_read_info=s->pfile_in_zip_read;\r
+\r
+    if (pfile_in_zip_read_info==NULL)\r
+        return UNZ_PARAMERROR;\r
+\r
+    return (z_off_t)pfile_in_zip_read_info->stream.total_out;\r
+}\r
+\r
+\r
+/*\r
+  return 1 if the end of file was reached, 0 elsewhere\r
+*/\r
+extern int ZEXPORT unzeof (file)\r
+    unzFile file;\r
+{\r
+    unz_s* s;\r
+    file_in_zip_read_info_s* pfile_in_zip_read_info;\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    pfile_in_zip_read_info=s->pfile_in_zip_read;\r
+\r
+    if (pfile_in_zip_read_info==NULL)\r
+        return UNZ_PARAMERROR;\r
+\r
+    if (pfile_in_zip_read_info->rest_read_uncompressed == 0)\r
+        return 1;\r
+    else\r
+        return 0;\r
+}\r
+\r
+\r
+\r
+/*\r
+  Read extra field from the current file (opened by unzOpenCurrentFile)\r
+  This is the local-header version of the extra field (sometimes, there is\r
+    more info in the local-header version than in the central-header)\r
+\r
+  if buf==NULL, it return the size of the local extra field that can be read\r
+\r
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in\r
+    buf.\r
+  the return value is the number of bytes copied in buf, or (if <0)\r
+    the error code\r
+*/\r
+extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)\r
+    unzFile file;\r
+    voidp buf;\r
+    unsigned len;\r
+{\r
+    unz_s* s;\r
+    file_in_zip_read_info_s* pfile_in_zip_read_info;\r
+    uInt read_now;\r
+    uLong size_to_read;\r
+\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    pfile_in_zip_read_info=s->pfile_in_zip_read;\r
+\r
+    if (pfile_in_zip_read_info==NULL)\r
+        return UNZ_PARAMERROR;\r
+\r
+    size_to_read = (pfile_in_zip_read_info->size_local_extrafield -\r
+                pfile_in_zip_read_info->pos_local_extrafield);\r
+\r
+    if (buf==NULL)\r
+        return (int)size_to_read;\r
+\r
+    if (len>size_to_read)\r
+        read_now = (uInt)size_to_read;\r
+    else\r
+        read_now = (uInt)len ;\r
+\r
+    if (read_now==0)\r
+        return 0;\r
+\r
+    if (ZSEEK(pfile_in_zip_read_info->z_filefunc,\r
+              pfile_in_zip_read_info->filestream,\r
+              pfile_in_zip_read_info->offset_local_extrafield +\r
+              pfile_in_zip_read_info->pos_local_extrafield,\r
+              ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+        return UNZ_ERRNO;\r
+\r
+    if (ZREAD(pfile_in_zip_read_info->z_filefunc,\r
+              pfile_in_zip_read_info->filestream,\r
+              buf,read_now)!=read_now)\r
+        return UNZ_ERRNO;\r
+\r
+    return (int)read_now;\r
+}\r
+\r
+/*\r
+  Close the file in zip opened with unzipOpenCurrentFile\r
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good\r
+*/\r
+extern int ZEXPORT unzCloseCurrentFile (file)\r
+    unzFile file;\r
+{\r
+    int err=UNZ_OK;\r
+\r
+    unz_s* s;\r
+    file_in_zip_read_info_s* pfile_in_zip_read_info;\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    pfile_in_zip_read_info=s->pfile_in_zip_read;\r
+\r
+    if (pfile_in_zip_read_info==NULL)\r
+        return UNZ_PARAMERROR;\r
+\r
+\r
+    if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&\r
+        (!pfile_in_zip_read_info->raw))\r
+    {\r
+        if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)\r
+            err=UNZ_CRCERROR;\r
+    }\r
+\r
+\r
+    TRYFREE(pfile_in_zip_read_info->read_buffer);\r
+    pfile_in_zip_read_info->read_buffer = NULL;\r
+    if (pfile_in_zip_read_info->stream_initialised)\r
+        inflateEnd(&pfile_in_zip_read_info->stream);\r
+\r
+    pfile_in_zip_read_info->stream_initialised = 0;\r
+    TRYFREE(pfile_in_zip_read_info);\r
+\r
+    s->pfile_in_zip_read=NULL;\r
+\r
+    return err;\r
+}\r
+\r
+\r
+/*\r
+  Get the global comment string of the ZipFile, in the szComment buffer.\r
+  uSizeBuf is the size of the szComment buffer.\r
+  return the number of byte copied or an error code <0\r
+*/\r
+extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)\r
+    unzFile file;\r
+    char *szComment;\r
+    uLong uSizeBuf;\r
+{\r
+    int err=UNZ_OK;\r
+    unz_s* s;\r
+    uLong uReadThis ;\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+\r
+    uReadThis = uSizeBuf;\r
+    if (uReadThis>s->gi.size_comment)\r
+        uReadThis = s->gi.size_comment;\r
+\r
+    if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+        return UNZ_ERRNO;\r
+\r
+    if (uReadThis>0)\r
+    {\r
+      *szComment='\0';\r
+      if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)\r
+        return UNZ_ERRNO;\r
+    }\r
+\r
+    if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))\r
+        *(szComment+s->gi.size_comment)='\0';\r
+    return (int)uReadThis;\r
+}\r
+\r
+/* Additions by RX '2004 */\r
+extern uLong ZEXPORT unzGetOffset (file)\r
+    unzFile file;\r
+{\r
+    unz_s* s;\r
+\r
+    if (file==NULL)\r
+          return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+    if (!s->current_file_ok)\r
+      return 0;\r
+    if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)\r
+      if (s->num_file==s->gi.number_entry)\r
+         return 0;\r
+    return s->pos_in_central_dir;\r
+}\r
+\r
+extern int ZEXPORT unzSetOffset (file, pos)\r
+        unzFile file;\r
+        uLong pos;\r
+{\r
+    unz_s* s;\r
+    int err;\r
+\r
+    if (file==NULL)\r
+        return UNZ_PARAMERROR;\r
+    s=(unz_s*)file;\r
+\r
+    s->pos_in_central_dir = pos;\r
+    s->num_file = s->gi.number_entry;      /* hack */\r
+    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r
+                                              &s->cur_file_info_internal,\r
+                                              NULL,0,NULL,0,NULL,0);\r
+    s->current_file_ok = (err == UNZ_OK);\r
+    return err;\r
+}\r
index 0c7c6f1..c3206a0 100644 (file)
-/* unzip.h -- IO for uncompress .zip files using zlib
-   Version 1.01, May 8th, 2004
-
-   Copyright (C) 1998-2004 Gilles Vollant
-
-   This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
-     WinZip, InfoZip tools and compatible.
-   Encryption and multi volume ZipFile (span) are not supported.
-   Old compressions used by old PKZip 1.x are not supported
-
-
-   I WAIT FEEDBACK at mail info@winimage.com
-   Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
-
-   Condition of use and distribution are the same than zlib :
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-
-*/
-
-/* for more info about .ZIP format, see
-      http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
-      http://www.info-zip.org/pub/infozip/doc/
-   PkWare has also a specification at :
-      ftp://ftp.pkware.com/probdesc.zip
-*/
-
-#ifndef _unz_H
-#define _unz_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _ZLIB_H
-#include "zlib.h"
-#endif
-
-#ifndef _ZLIBIOAPI_H
-#include "ioapi.h"
-#endif
-
-#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
-/* like the STRICT of WIN32, we define a pointer that cannot be converted
-    from (void*) without cast */
-typedef struct TagunzFile__ { int unused; } unzFile__;
-typedef unzFile__ *unzFile;
-#else
-typedef voidp unzFile;
-#endif
-
-
-#define UNZ_OK                          (0)
-#define UNZ_END_OF_LIST_OF_FILE         (-100)
-#define UNZ_ERRNO                       (Z_ERRNO)
-#define UNZ_EOF                         (0)
-#define UNZ_PARAMERROR                  (-102)
-#define UNZ_BADZIPFILE                  (-103)
-#define UNZ_INTERNALERROR               (-104)
-#define UNZ_CRCERROR                    (-105)
-
-/* tm_unz contain date/time info */
-typedef struct tm_unz_s
-{
-    uInt tm_sec;            /* seconds after the minute - [0,59] */
-    uInt tm_min;            /* minutes after the hour - [0,59] */
-    uInt tm_hour;           /* hours since midnight - [0,23] */
-    uInt tm_mday;           /* day of the month - [1,31] */
-    uInt tm_mon;            /* months since January - [0,11] */
-    uInt tm_year;           /* years - [1980..2044] */
-} tm_unz;
-
-/* unz_global_info structure contain global data about the ZIPfile
-   These data comes from the end of central dir */
-typedef struct unz_global_info_s
-{
-    uLong number_entry;         /* total number of entries in
-                       the central dir on this disk */
-    uLong size_comment;         /* size of the global comment of the zipfile */
-} unz_global_info;
-
-
-/* unz_file_info contain information about a file in the zipfile */
-typedef struct unz_file_info_s
-{
-    uLong version;              /* version made by                 2 bytes */
-    uLong version_needed;       /* version needed to extract       2 bytes */
-    uLong flag;                 /* general purpose bit flag        2 bytes */
-    uLong compression_method;   /* compression method              2 bytes */
-    uLong dosDate;              /* last mod file date in Dos fmt   4 bytes */
-    uLong crc;                  /* crc-32                          4 bytes */
-    uLong compressed_size;      /* compressed size                 4 bytes */
-    uLong uncompressed_size;    /* uncompressed size               4 bytes */
-    uLong size_filename;        /* filename length                 2 bytes */
-    uLong size_file_extra;      /* extra field length              2 bytes */
-    uLong size_file_comment;    /* file comment length             2 bytes */
-
-    uLong disk_num_start;       /* disk number start               2 bytes */
-    uLong internal_fa;          /* internal file attributes        2 bytes */
-    uLong external_fa;          /* external file attributes        4 bytes */
-
-    tm_unz tmu_date;
-} unz_file_info;
-
-extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
-                                                 const char* fileName2,
-                                                 int iCaseSensitivity));
-/*
-   Compare two filename (fileName1,fileName2).
-   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
-   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
-                                or strcasecmp)
-   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
-    (like 1 on Unix, 2 on Windows)
-*/
-
-
-extern unzFile ZEXPORT unzOpen OF((const char *path));
-/*
-  Open a Zip file. path contain the full pathname (by example,
-     on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
-     "zlib/zlib113.zip".
-     If the zipfile cannot be opened (file don't exist or in not valid), the
-       return value is NULL.
-     Else, the return value is a unzFile Handle, usable with other function
-       of this unzip package.
-*/
-
-extern unzFile ZEXPORT unzOpen2 OF((const char *path,
-                                    zlib_filefunc_def* pzlib_filefunc_def));
-/*
-   Open a Zip file, like unzOpen, but provide a set of file low level API
-      for read/write the zip file (see ioapi.h)
-*/
-
-extern int ZEXPORT unzClose OF((unzFile file));
-/*
-  Close a ZipFile opened with unzipOpen.
-  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
-    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
-  return UNZ_OK if there is no problem. */
-
-extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
-                                        unz_global_info *pglobal_info));
-/*
-  Write info about the ZipFile in the *pglobal_info structure.
-  No preparation of the structure is needed
-  return UNZ_OK if there is no problem. */
-
-
-extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
-                                           char *szComment,
-                                           uLong uSizeBuf));
-/*
-  Get the global comment string of the ZipFile, in the szComment buffer.
-  uSizeBuf is the size of the szComment buffer.
-  return the number of byte copied or an error code <0
-*/
-
-
-/***************************************************************************/
-/* Unzip package allow you browse the directory of the zipfile */
-
-extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
-/*
-  Set the current file of the zipfile to the first file.
-  return UNZ_OK if there is no problem
-*/
-
-extern int ZEXPORT unzGoToNextFile OF((unzFile file));
-/*
-  Set the current file of the zipfile to the next file.
-  return UNZ_OK if there is no problem
-  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
-*/
-
-extern int ZEXPORT unzLocateFile OF((unzFile file,
-                     const char *szFileName,
-                     int iCaseSensitivity));
-/*
-  Try locate the file szFileName in the zipfile.
-  For the iCaseSensitivity signification, see unzStringFileNameCompare
-
-  return value :
-  UNZ_OK if the file is found. It becomes the current file.
-  UNZ_END_OF_LIST_OF_FILE if the file is not found
-*/
-
-
-/* ****************************************** */
-/* Ryan supplied functions */
-/* unz_file_info contain information about a file in the zipfile */
-typedef struct unz_file_pos_s
-{
-    uLong pos_in_zip_directory;   /* offset in zip file directory */
-    uLong num_of_file;            /* # of file */
-} unz_file_pos;
-
-extern int ZEXPORT unzGetFilePos(
-    unzFile file,
-    unz_file_pos* file_pos);
-
-extern int ZEXPORT unzGoToFilePos(
-    unzFile file,
-    unz_file_pos* file_pos);
-
-/* ****************************************** */
-
-extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
-                         unz_file_info *pfile_info,
-                         char *szFileName,
-                         uLong fileNameBufferSize,
-                         void *extraField,
-                         uLong extraFieldBufferSize,
-                         char *szComment,
-                         uLong commentBufferSize));
-/*
-  Get Info about the current file
-  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
-        the current file
-  if szFileName!=NULL, the filemane string will be copied in szFileName
-            (fileNameBufferSize is the size of the buffer)
-  if extraField!=NULL, the extra field information will be copied in extraField
-            (extraFieldBufferSize is the size of the buffer).
-            This is the Central-header version of the extra field
-  if szComment!=NULL, the comment string of the file will be copied in szComment
-            (commentBufferSize is the size of the buffer)
-*/
-
-/***************************************************************************/
-/* for reading the content of the current zipfile, you can open it, read data
-   from it, and close it (you can close it before reading all the file)
-   */
-
-extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
-/*
-  Open for reading data the current file in the zipfile.
-  If there is no error, the return value is UNZ_OK.
-*/
-
-extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
-                                                  const char* password));
-/*
-  Open for reading data the current file in the zipfile.
-  password is a crypting password
-  If there is no error, the return value is UNZ_OK.
-*/
-
-extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
-                                           int* method,
-                                           int* level,
-                                           int raw));
-/*
-  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
-    if raw==1
-  *method will receive method of compression, *level will receive level of
-     compression
-  note : you can set level parameter as NULL (if you did not want known level,
-         but you CANNOT set method parameter as NULL
-*/
-
-extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
-                                           int* method,
-                                           int* level,
-                                           int raw,
-                                           const char* password));
-/*
-  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
-    if raw==1
-  *method will receive method of compression, *level will receive level of
-     compression
-  note : you can set level parameter as NULL (if you did not want known level,
-         but you CANNOT set method parameter as NULL
-*/
-
-
-extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
-/*
-  Close the file in zip opened with unzOpenCurrentFile
-  Return UNZ_CRCERROR if all the file was read but the CRC is not good
-*/
-
-extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
-                      voidp buf,
-                      unsigned len));
-/*
-  Read bytes from the current file (opened by unzOpenCurrentFile)
-  buf contain buffer where data must be copied
-  len the size of buf.
-
-  return the number of byte copied if somes bytes are copied
-  return 0 if the end of file was reached
-  return <0 with error code if there is an error
-    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
-*/
-
-extern z_off_t ZEXPORT unztell OF((unzFile file));
-/*
-  Give the current position in uncompressed data
-*/
-
-extern int ZEXPORT unzeof OF((unzFile file));
-/*
-  return 1 if the end of file was reached, 0 elsewhere
-*/
-
-extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
-                                             voidp buf,
-                                             unsigned len));
-/*
-  Read extra field from the current file (opened by unzOpenCurrentFile)
-  This is the local-header version of the extra field (sometimes, there is
-    more info in the local-header version than in the central-header)
-
-  if buf==NULL, it return the size of the local extra field
-
-  if buf!=NULL, len is the size of the buffer, the extra header is copied in
-    buf.
-  the return value is the number of bytes copied in buf, or (if <0)
-    the error code
-*/
-
-/***************************************************************************/
-
-/* Get the current file offset */
-extern uLong ZEXPORT unzGetOffset (unzFile file);
-
-/* Set the current file offset */
-extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _unz_H */
+/* unzip.h -- IO for uncompress .zip files using zlib\r
+   Version 1.01e, February 12th, 2005\r
+\r
+   Copyright (C) 1998-2005 Gilles Vollant\r
+\r
+   This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g\r
+     WinZip, InfoZip tools and compatible.\r
+\r
+   Multi volume ZipFile (span) are not supported.\r
+   Encryption compatible with pkzip 2.04g only supported\r
+   Old compressions used by old PKZip 1.x are not supported\r
+\r
+\r
+   I WAIT FEEDBACK at mail info@winimage.com\r
+   Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution\r
+\r
+   Condition of use and distribution are the same than zlib :\r
+\r
+  This software is provided 'as-is', without any express or implied\r
+  warranty.  In no event will the authors be held liable for any damages\r
+  arising from the use of this software.\r
+\r
+  Permission is granted to anyone to use this software for any purpose,\r
+  including commercial applications, and to alter it and redistribute it\r
+  freely, subject to the following restrictions:\r
+\r
+  1. The origin of this software must not be misrepresented; you must not\r
+     claim that you wrote the original software. If you use this software\r
+     in a product, an acknowledgment in the product documentation would be\r
+     appreciated but is not required.\r
+  2. Altered source versions must be plainly marked as such, and must not be\r
+     misrepresented as being the original software.\r
+  3. This notice may not be removed or altered from any source distribution.\r
+\r
+\r
+*/\r
+\r
+/* for more info about .ZIP format, see\r
+      http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip\r
+      http://www.info-zip.org/pub/infozip/doc/\r
+   PkWare has also a specification at :\r
+      ftp://ftp.pkware.com/probdesc.zip\r
+*/\r
+\r
+#ifndef _unz_H\r
+#define _unz_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#ifndef _ZLIB_H\r
+#include "zlib.h"\r
+#endif\r
+\r
+#ifndef _ZLIBIOAPI_H\r
+#include "ioapi.h"\r
+#endif\r
+\r
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)\r
+/* like the STRICT of WIN32, we define a pointer that cannot be converted\r
+    from (void*) without cast */\r
+typedef struct TagunzFile__ { int unused; } unzFile__;\r
+typedef unzFile__ *unzFile;\r
+#else\r
+typedef voidp unzFile;\r
+#endif\r
+\r
+\r
+#define UNZ_OK                          (0)\r
+#define UNZ_END_OF_LIST_OF_FILE         (-100)\r
+#define UNZ_ERRNO                       (Z_ERRNO)\r
+#define UNZ_EOF                         (0)\r
+#define UNZ_PARAMERROR                  (-102)\r
+#define UNZ_BADZIPFILE                  (-103)\r
+#define UNZ_INTERNALERROR               (-104)\r
+#define UNZ_CRCERROR                    (-105)\r
+\r
+/* tm_unz contain date/time info */\r
+typedef struct tm_unz_s\r
+{\r
+    uInt tm_sec;            /* seconds after the minute - [0,59] */\r
+    uInt tm_min;            /* minutes after the hour - [0,59] */\r
+    uInt tm_hour;           /* hours since midnight - [0,23] */\r
+    uInt tm_mday;           /* day of the month - [1,31] */\r
+    uInt tm_mon;            /* months since January - [0,11] */\r
+    uInt tm_year;           /* years - [1980..2044] */\r
+} tm_unz;\r
+\r
+/* unz_global_info structure contain global data about the ZIPfile\r
+   These data comes from the end of central dir */\r
+typedef struct unz_global_info_s\r
+{\r
+    uLong number_entry;         /* total number of entries in\r
+                       the central dir on this disk */\r
+    uLong size_comment;         /* size of the global comment of the zipfile */\r
+} unz_global_info;\r
+\r
+\r
+/* unz_file_info contain information about a file in the zipfile */\r
+typedef struct unz_file_info_s\r
+{\r
+    uLong version;              /* version made by                 2 bytes */\r
+    uLong version_needed;       /* version needed to extract       2 bytes */\r
+    uLong flag;                 /* general purpose bit flag        2 bytes */\r
+    uLong compression_method;   /* compression method              2 bytes */\r
+    uLong dosDate;              /* last mod file date in Dos fmt   4 bytes */\r
+    uLong crc;                  /* crc-32                          4 bytes */\r
+    uLong compressed_size;      /* compressed size                 4 bytes */\r
+    uLong uncompressed_size;    /* uncompressed size               4 bytes */\r
+    uLong size_filename;        /* filename length                 2 bytes */\r
+    uLong size_file_extra;      /* extra field length              2 bytes */\r
+    uLong size_file_comment;    /* file comment length             2 bytes */\r
+\r
+    uLong disk_num_start;       /* disk number start               2 bytes */\r
+    uLong internal_fa;          /* internal file attributes        2 bytes */\r
+    uLong external_fa;          /* external file attributes        4 bytes */\r
+\r
+    tm_unz tmu_date;\r
+} unz_file_info;\r
+\r
+extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,\r
+                                                 const char* fileName2,\r
+                                                 int iCaseSensitivity));\r
+/*\r
+   Compare two filename (fileName1,fileName2).\r
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)\r
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi\r
+                                or strcasecmp)\r
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system\r
+    (like 1 on Unix, 2 on Windows)\r
+*/\r
+\r
+\r
+extern unzFile ZEXPORT unzOpen OF((const char *path));\r
+/*\r
+  Open a Zip file. path contain the full pathname (by example,\r
+     on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer\r
+     "zlib/zlib113.zip".\r
+     If the zipfile cannot be opened (file don't exist or in not valid), the\r
+       return value is NULL.\r
+     Else, the return value is a unzFile Handle, usable with other function\r
+       of this unzip package.\r
+*/\r
+\r
+extern unzFile ZEXPORT unzOpen2 OF((const char *path,\r
+                                    zlib_filefunc_def* pzlib_filefunc_def));\r
+/*\r
+   Open a Zip file, like unzOpen, but provide a set of file low level API\r
+      for read/write the zip file (see ioapi.h)\r
+*/\r
+\r
+extern int ZEXPORT unzClose OF((unzFile file));\r
+/*\r
+  Close a ZipFile opened with unzipOpen.\r
+  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),\r
+    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.\r
+  return UNZ_OK if there is no problem. */\r
+\r
+extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,\r
+                                        unz_global_info *pglobal_info));\r
+/*\r
+  Write info about the ZipFile in the *pglobal_info structure.\r
+  No preparation of the structure is needed\r
+  return UNZ_OK if there is no problem. */\r
+\r
+\r
+extern int ZEXPORT unzGetGlobalComment OF((unzFile file,\r
+                                           char *szComment,\r
+                                           uLong uSizeBuf));\r
+/*\r
+  Get the global comment string of the ZipFile, in the szComment buffer.\r
+  uSizeBuf is the size of the szComment buffer.\r
+  return the number of byte copied or an error code <0\r
+*/\r
+\r
+\r
+/***************************************************************************/\r
+/* Unzip package allow you browse the directory of the zipfile */\r
+\r
+extern int ZEXPORT unzGoToFirstFile OF((unzFile file));\r
+/*\r
+  Set the current file of the zipfile to the first file.\r
+  return UNZ_OK if there is no problem\r
+*/\r
+\r
+extern int ZEXPORT unzGoToNextFile OF((unzFile file));\r
+/*\r
+  Set the current file of the zipfile to the next file.\r
+  return UNZ_OK if there is no problem\r
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.\r
+*/\r
+\r
+extern int ZEXPORT unzLocateFile OF((unzFile file,\r
+                     const char *szFileName,\r
+                     int iCaseSensitivity));\r
+/*\r
+  Try locate the file szFileName in the zipfile.\r
+  For the iCaseSensitivity signification, see unzStringFileNameCompare\r
+\r
+  return value :\r
+  UNZ_OK if the file is found. It becomes the current file.\r
+  UNZ_END_OF_LIST_OF_FILE if the file is not found\r
+*/\r
+\r
+\r
+/* ****************************************** */\r
+/* Ryan supplied functions */\r
+/* unz_file_info contain information about a file in the zipfile */\r
+typedef struct unz_file_pos_s\r
+{\r
+    uLong pos_in_zip_directory;   /* offset in zip file directory */\r
+    uLong num_of_file;            /* # of file */\r
+} unz_file_pos;\r
+\r
+extern int ZEXPORT unzGetFilePos(\r
+    unzFile file,\r
+    unz_file_pos* file_pos);\r
+\r
+extern int ZEXPORT unzGoToFilePos(\r
+    unzFile file,\r
+    unz_file_pos* file_pos);\r
+\r
+/* ****************************************** */\r
+\r
+extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,\r
+                         unz_file_info *pfile_info,\r
+                         char *szFileName,\r
+                         uLong fileNameBufferSize,\r
+                         void *extraField,\r
+                         uLong extraFieldBufferSize,\r
+                         char *szComment,\r
+                         uLong commentBufferSize));\r
+/*\r
+  Get Info about the current file\r
+  if pfile_info!=NULL, the *pfile_info structure will contain somes info about\r
+        the current file\r
+  if szFileName!=NULL, the filemane string will be copied in szFileName\r
+            (fileNameBufferSize is the size of the buffer)\r
+  if extraField!=NULL, the extra field information will be copied in extraField\r
+            (extraFieldBufferSize is the size of the buffer).\r
+            This is the Central-header version of the extra field\r
+  if szComment!=NULL, the comment string of the file will be copied in szComment\r
+            (commentBufferSize is the size of the buffer)\r
+*/\r
+\r
+/***************************************************************************/\r
+/* for reading the content of the current zipfile, you can open it, read data\r
+   from it, and close it (you can close it before reading all the file)\r
+   */\r
+\r
+extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));\r
+/*\r
+  Open for reading data the current file in the zipfile.\r
+  If there is no error, the return value is UNZ_OK.\r
+*/\r
+\r
+extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,\r
+                                                  const char* password));\r
+/*\r
+  Open for reading data the current file in the zipfile.\r
+  password is a crypting password\r
+  If there is no error, the return value is UNZ_OK.\r
+*/\r
+\r
+extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,\r
+                                           int* method,\r
+                                           int* level,\r
+                                           int raw));\r
+/*\r
+  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)\r
+    if raw==1\r
+  *method will receive method of compression, *level will receive level of\r
+     compression\r
+  note : you can set level parameter as NULL (if you did not want known level,\r
+         but you CANNOT set method parameter as NULL\r
+*/\r
+\r
+extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,\r
+                                           int* method,\r
+                                           int* level,\r
+                                           int raw,\r
+                                           const char* password));\r
+/*\r
+  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)\r
+    if raw==1\r
+  *method will receive method of compression, *level will receive level of\r
+     compression\r
+  note : you can set level parameter as NULL (if you did not want known level,\r
+         but you CANNOT set method parameter as NULL\r
+*/\r
+\r
+\r
+extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));\r
+/*\r
+  Close the file in zip opened with unzOpenCurrentFile\r
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good\r
+*/\r
+\r
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file,\r
+                      voidp buf,\r
+                      unsigned len));\r
+/*\r
+  Read bytes from the current file (opened by unzOpenCurrentFile)\r
+  buf contain buffer where data must be copied\r
+  len the size of buf.\r
+\r
+  return the number of byte copied if somes bytes are copied\r
+  return 0 if the end of file was reached\r
+  return <0 with error code if there is an error\r
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)\r
+*/\r
+\r
+extern z_off_t ZEXPORT unztell OF((unzFile file));\r
+/*\r
+  Give the current position in uncompressed data\r
+*/\r
+\r
+extern int ZEXPORT unzeof OF((unzFile file));\r
+/*\r
+  return 1 if the end of file was reached, 0 elsewhere\r
+*/\r
+\r
+extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,\r
+                                             voidp buf,\r
+                                             unsigned len));\r
+/*\r
+  Read extra field from the current file (opened by unzOpenCurrentFile)\r
+  This is the local-header version of the extra field (sometimes, there is\r
+    more info in the local-header version than in the central-header)\r
+\r
+  if buf==NULL, it return the size of the local extra field\r
+\r
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in\r
+    buf.\r
+  the return value is the number of bytes copied in buf, or (if <0)\r
+    the error code\r
+*/\r
+\r
+/***************************************************************************/\r
+\r
+/* Get the current file offset */\r
+extern uLong ZEXPORT unzGetOffset (unzFile file);\r
+\r
+/* Set the current file offset */\r
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);\r
+\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* _unz_H */\r
index 2ccd7fd..400e2ba 100644 (file)
-/* zip.c -- IO on .zip files using zlib
-   Version 1.01, May 8th, 2004
-
-   Copyright (C) 1998-2004 Gilles Vollant
-
-   Read zip.h for more info
-*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "zlib.h"
-#include "zip.h"
-
-#ifdef STDC
-#  include <stddef.h>
-#  include <string.h>
-#  include <stdlib.h>
-#endif
-#ifdef NO_ERRNO_H
-    extern int errno;
-#else
-#   include <errno.h>
-#endif
-
-
-#ifndef local
-#  define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-#ifndef VERSIONMADEBY
-# define VERSIONMADEBY   (0x0) /* platform depedent */
-#endif
-
-#ifndef Z_BUFSIZE
-#define Z_BUFSIZE (16384)
-#endif
-
-#ifndef Z_MAXFILENAMEINZIP
-#define Z_MAXFILENAMEINZIP (256)
-#endif
-
-#ifndef ALLOC
-# define ALLOC(size) (malloc(size))
-#endif
-#ifndef TRYFREE
-# define TRYFREE(p) {if (p) free(p);}
-#endif
-
-/*
-#define SIZECENTRALDIRITEM (0x2e)
-#define SIZEZIPLOCALHEADER (0x1e)
-*/
-
-/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
-
-#ifndef SEEK_CUR
-#define SEEK_CUR    1
-#endif
-
-#ifndef SEEK_END
-#define SEEK_END    2
-#endif
-
-#ifndef SEEK_SET
-#define SEEK_SET    0
-#endif
-
-#ifndef DEF_MEM_LEVEL
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-#endif
-const char zip_copyright[] =
-   " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
-
-
-#define SIZEDATA_INDATABLOCK (4096-(4*4))
-
-#define LOCALHEADERMAGIC    (0x04034b50)
-#define CENTRALHEADERMAGIC  (0x02014b50)
-#define ENDHEADERMAGIC      (0x06054b50)
-
-#define FLAG_LOCALHEADER_OFFSET (0x06)
-#define CRC_LOCALHEADER_OFFSET  (0x0e)
-
-#define SIZECENTRALHEADER (0x2e) /* 46 */
-
-typedef struct linkedlist_datablock_internal_s
-{
-  struct linkedlist_datablock_internal_s* next_datablock;
-  uLong  avail_in_this_block;
-  uLong  filled_in_this_block;
-  uLong  unused; /* for future use and alignement */
-  unsigned char data[SIZEDATA_INDATABLOCK];
-} linkedlist_datablock_internal;
-
-typedef struct linkedlist_data_s
-{
-    linkedlist_datablock_internal* first_block;
-    linkedlist_datablock_internal* last_block;
-} linkedlist_data;
-
-
-typedef struct
-{
-    z_stream stream;            /* zLib stream structure for inflate */
-    int  stream_initialised;    /* 1 is stream is initialised */
-    uInt pos_in_buffered_data;  /* last written byte in buffered_data */
-
-    uLong pos_local_header;     /* offset of the local header of the file
-                                     currenty writing */
-    char* central_header;       /* central header data for the current file */
-    uLong size_centralheader;   /* size of the central header for cur file */
-    uLong flag;                 /* flag of the file currently writing */
-
-    int  method;                /* compression method of file currenty wr.*/
-    int  raw;                   /* 1 for directly writing raw data */
-    Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
-    uLong dosDate;
-    uLong crc32;
-    int  encrypt;
-#ifndef NOCRYPT
-    unsigned long keys[3];     /* keys defining the pseudo-random sequence */
-    const unsigned long* pcrc_32_tab;
-    int crypt_header_size;
-#endif
-} curfile_info;
-
-typedef struct
-{
-    zlib_filefunc_def z_filefunc;
-    voidpf filestream;        /* io structore of the zipfile */
-    linkedlist_data central_dir;/* datablock with central dir in construction*/
-    int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
-    curfile_info ci;            /* info on the file curretly writing */
-
-    uLong begin_pos;            /* position of the beginning of the zipfile */
-    uLong add_position_when_writting_offset;
-    uLong number_entry;
-} zip_internal;
-
-
-
-#ifndef NOCRYPT
-#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
-#include "crypt.h"
-#endif
-
-local linkedlist_datablock_internal* allocate_new_datablock()
-{
-    linkedlist_datablock_internal* ldi;
-    ldi = (linkedlist_datablock_internal*)
-                 ALLOC(sizeof(linkedlist_datablock_internal));
-    if (ldi!=NULL)
-    {
-        ldi->next_datablock = NULL ;
-        ldi->filled_in_this_block = 0 ;
-        ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
-    }
-    return ldi;
-}
-
-local void free_datablock(ldi)
-    linkedlist_datablock_internal* ldi;
-{
-    while (ldi!=NULL)
-    {
-        linkedlist_datablock_internal* ldinext = ldi->next_datablock;
-        TRYFREE(ldi);
-        ldi = ldinext;
-    }
-}
-
-local void init_linkedlist(ll)
-    linkedlist_data* ll;
-{
-    ll->first_block = ll->last_block = NULL;
-}
-
-local void free_linkedlist(ll)
-    linkedlist_data* ll;
-{
-    free_datablock(ll->first_block);
-    ll->first_block = ll->last_block = NULL;
-}
-
-
-local int add_data_in_datablock(ll,buf,len)
-    linkedlist_data* ll;
-    const void* buf;
-    uLong len;
-{
-    linkedlist_datablock_internal* ldi;
-    const unsigned char* from_copy;
-
-    if (ll==NULL)
-        return ZIP_INTERNALERROR;
-
-    if (ll->last_block == NULL)
-    {
-        ll->first_block = ll->last_block = allocate_new_datablock();
-        if (ll->first_block == NULL)
-            return ZIP_INTERNALERROR;
-    }
-
-    ldi = ll->last_block;
-    from_copy = (unsigned char*)buf;
-
-    while (len>0)
-    {
-        uInt copy_this;
-        uInt i;
-        unsigned char* to_copy;
-
-        if (ldi->avail_in_this_block==0)
-        {
-            ldi->next_datablock = allocate_new_datablock();
-            if (ldi->next_datablock == NULL)
-                return ZIP_INTERNALERROR;
-            ldi = ldi->next_datablock ;
-            ll->last_block = ldi;
-        }
-
-        if (ldi->avail_in_this_block < len)
-            copy_this = (uInt)ldi->avail_in_this_block;
-        else
-            copy_this = (uInt)len;
-
-        to_copy = &(ldi->data[ldi->filled_in_this_block]);
-
-        for (i=0;i<copy_this;i++)
-            *(to_copy+i)=*(from_copy+i);
-
-        ldi->filled_in_this_block += copy_this;
-        ldi->avail_in_this_block -= copy_this;
-        from_copy += copy_this ;
-        len -= copy_this;
-    }
-    return ZIP_OK;
-}
-
-
-
-/****************************************************************************/
-
-#ifndef NO_ADDFILEINEXISTINGZIP
-/* ===========================================================================
-   Inputs a long in LSB order to the given file
-   nbByte == 1, 2 or 4 (byte, short or long)
-*/
-
-local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def,
-                                voidpf filestream, uLong x, int nbByte));
-local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    uLong x;
-    int nbByte;
-{
-    unsigned char buf[4];
-    int n;
-    for (n = 0; n < nbByte; n++)
-    {
-        buf[n] = (unsigned char)(x & 0xff);
-        x >>= 8;
-    }
-    if (x != 0)
-      {     /* data overflow - hack for ZIP64 (X Roche) */
-      for (n = 0; n < nbByte; n++)
-        {
-          buf[n] = 0xff;
-        }
-      }
-
-    if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
-        return ZIP_ERRNO;
-    else
-        return ZIP_OK;
-}
-
-local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
-local void ziplocal_putValue_inmemory (dest, x, nbByte)
-    void* dest;
-    uLong x;
-    int nbByte;
-{
-    unsigned char* buf=(unsigned char*)dest;
-    int n;
-    for (n = 0; n < nbByte; n++) {
-        buf[n] = (unsigned char)(x & 0xff);
-        x >>= 8;
-    }
-
-    if (x != 0)
-    {     /* data overflow - hack for ZIP64 */
-       for (n = 0; n < nbByte; n++)
-       {
-          buf[n] = 0xff;
-       }
-    }
-}
-
-/****************************************************************************/
-
-
-local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
-    const tm_zip* ptm;
-    uLong dosDate;
-{
-    uLong year = (uLong)ptm->tm_year;
-    if (year>1980)
-        year-=1980;
-    else if (year>80)
-        year-=80;
-    return
-      (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
-        ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
-}
-
-
-/****************************************************************************/
-
-local int ziplocal_getByte OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    int *pi));
-
-local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    int *pi;
-{
-    unsigned char c;
-    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
-    if (err==1)
-    {
-        *pi = (int)c;
-        return ZIP_OK;
-    }
-    else
-    {
-        if (ZERROR(*pzlib_filefunc_def,filestream))
-            return ZIP_ERRNO;
-        else
-            return ZIP_EOF;
-    }
-}
-
-
-/* ===========================================================================
-   Reads a long in LSB order from the given gz_stream. Sets
-*/
-local int ziplocal_getShort OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    uLong *pX));
-
-local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    uLong *pX;
-{
-    uLong x ;
-    int i;
-    int err;
-
-    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x = (uLong)i;
-
-    if (err==ZIP_OK)
-        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x += ((uLong)i)<<8;
-
-    if (err==ZIP_OK)
-        *pX = x;
-    else
-        *pX = 0;
-    return err;
-}
-
-local int ziplocal_getLong OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    uLong *pX));
-
-local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    uLong *pX;
-{
-    uLong x ;
-    int i;
-    int err;
-
-    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x = (uLong)i;
-
-    if (err==ZIP_OK)
-        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x += ((uLong)i)<<8;
-
-    if (err==ZIP_OK)
-        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x += ((uLong)i)<<16;
-
-    if (err==ZIP_OK)
-        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x += ((uLong)i)<<24;
-
-    if (err==ZIP_OK)
-        *pX = x;
-    else
-        *pX = 0;
-    return err;
-}
-
-#ifndef BUFREADCOMMENT
-#define BUFREADCOMMENT (0x400)
-#endif
-/*
-  Locate the Central directory of a zipfile (at the end, just before
-    the global comment)
-*/
-local uLong ziplocal_SearchCentralDir OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream));
-
-local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-{
-    unsigned char* buf;
-    uLong uSizeFile;
-    uLong uBackRead;
-    uLong uMaxBack=0xffff; /* maximum size of global comment */
-    uLong uPosFound=0;
-
-    if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
-        return 0;
-
-
-    uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
-
-    if (uMaxBack>uSizeFile)
-        uMaxBack = uSizeFile;
-
-    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
-    if (buf==NULL)
-        return 0;
-
-    uBackRead = 4;
-    while (uBackRead<uMaxBack)
-    {
-        uLong uReadSize,uReadPos ;
-        int i;
-        if (uBackRead+BUFREADCOMMENT>uMaxBack)
-            uBackRead = uMaxBack;
-        else
-            uBackRead+=BUFREADCOMMENT;
-        uReadPos = uSizeFile-uBackRead ;
-
-        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
-                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
-        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
-            break;
-
-        if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
-            break;
-
-        for (i=(int)uReadSize-3; (i--)>0;)
-            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
-                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
-            {
-                uPosFound = uReadPos+i;
-                break;
-            }
-
-        if (uPosFound!=0)
-            break;
-    }
-    TRYFREE(buf);
-    return uPosFound;
-}
-#endif /* !NO_ADDFILEINEXISTINGZIP*/
-
-/************************************************************/
-extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def)
-    const char *pathname;
-    int append;
-    zipcharpc* globalcomment;
-    zlib_filefunc_def* pzlib_filefunc_def;
-{
-    zip_internal ziinit;
-    zip_internal* zi;
-    int err=ZIP_OK;
-
-
-    if (pzlib_filefunc_def==NULL)
-        fill_fopen_filefunc(&ziinit.z_filefunc);
-    else
-        ziinit.z_filefunc = *pzlib_filefunc_def;
-
-    ziinit.filestream = (*(ziinit.z_filefunc.zopen_file))
-                 (ziinit.z_filefunc.opaque,
-                  pathname,
-                  (append == APPEND_STATUS_CREATE) ?
-                  (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
-                    (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
-
-    if (ziinit.filestream == NULL)
-        return NULL;
-    ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream);
-    ziinit.in_opened_file_inzip = 0;
-    ziinit.ci.stream_initialised = 0;
-    ziinit.number_entry = 0;
-    ziinit.add_position_when_writting_offset = 0;
-    init_linkedlist(&(ziinit.central_dir));
-
-
-    zi = (zip_internal*)ALLOC(sizeof(zip_internal));
-    if (zi==NULL)
-    {
-        ZCLOSE(ziinit.z_filefunc,ziinit.filestream);
-        return NULL;
-    }
-
-    /* now we add file in a zipfile */
-#    ifndef NO_ADDFILEINEXISTINGZIP
-    if (append == APPEND_STATUS_ADDINZIP)
-    {
-        uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
-
-        uLong size_central_dir;     /* size of the central directory  */
-        uLong offset_central_dir;   /* offset of start of central directory */
-        uLong central_pos,uL;
-
-        uLong number_disk;          /* number of the current dist, used for
-                                    spaning ZIP, unsupported, always 0*/
-        uLong number_disk_with_CD;  /* number the the disk with central dir, used
-                                    for spaning ZIP, unsupported, always 0*/
-        uLong number_entry;
-        uLong number_entry_CD;      /* total number of entries in
-                                    the central dir
-                                    (same than number_entry on nospan) */
-        uLong size_comment;
-
-        central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);
-        if (central_pos==0)
-            err=ZIP_ERRNO;
-
-        if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
-                                        central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
-            err=ZIP_ERRNO;
-
-        /* the signature, already checked */
-        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* number of this disk */
-        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* number of the disk with the start of the central directory */
-        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* total number of entries in the central dir on this disk */
-        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* total number of entries in the central dir */
-        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        if ((number_entry_CD!=number_entry) ||
-            (number_disk_with_CD!=0) ||
-            (number_disk!=0))
-            err=ZIP_BADZIPFILE;
-
-        /* size of the central directory */
-        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* offset of start of central directory with respect to the
-            starting disk number */
-        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* zipfile comment length */
-        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        if ((central_pos<offset_central_dir+size_central_dir) &&
-            (err==ZIP_OK))
-            err=ZIP_BADZIPFILE;
-
-        if (err!=ZIP_OK)
-        {
-            ZCLOSE(ziinit.z_filefunc, ziinit.filestream);
-            return NULL;
-        }
-
-        byte_before_the_zipfile = central_pos -
-                                (offset_central_dir+size_central_dir);
-        ziinit.add_position_when_writting_offset = byte_before_the_zipfile ;
-
-        {
-            uLong size_central_dir_to_read = size_central_dir;
-            size_t buf_size = SIZEDATA_INDATABLOCK;
-            void* buf_read = (void*)ALLOC(buf_size);
-            if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
-                  offset_central_dir + byte_before_the_zipfile,
-                  ZLIB_FILEFUNC_SEEK_SET) != 0)
-                  err=ZIP_ERRNO;
-
-            while ((size_central_dir_to_read>0) && (err==ZIP_OK))
-            {
-                uLong read_this = SIZEDATA_INDATABLOCK;
-                if (read_this > size_central_dir_to_read)
-                    read_this = size_central_dir_to_read;
-                if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this)
-                    err=ZIP_ERRNO;
-
-                if (err==ZIP_OK)
-                    err = add_data_in_datablock(&ziinit.central_dir,buf_read,
-                                                (uLong)read_this);
-                size_central_dir_to_read-=read_this;
-            }
-            TRYFREE(buf_read);
-        }
-        ziinit.begin_pos = byte_before_the_zipfile;
-        ziinit.number_entry = number_entry_CD;
-
-        if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
-                  offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
-            err=ZIP_ERRNO;
-    }
-#    endif /* !NO_ADDFILEINEXISTINGZIP*/
-
-    if (err != ZIP_OK)
-    {
-        TRYFREE(zi);
-        return NULL;
-    }
-    else
-    {
-        *zi = ziinit;
-        return (zipFile)zi;
-    }
-}
-
-extern zipFile ZEXPORT zipOpen (pathname, append)
-    const char *pathname;
-    int append;
-{
-    return zipOpen2(pathname,append,NULL,NULL);
-}
-
-extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
-                                         extrafield_local, size_extrafield_local,
-                                         extrafield_global, size_extrafield_global,
-                                         comment, method, level, raw,
-                                         windowBits, memLevel, strategy,
-                                         password, crcForCrypting)
-    zipFile file;
-    const char* filename;
-    const zip_fileinfo* zipfi;
-    const void* extrafield_local;
-    uInt size_extrafield_local;
-    const void* extrafield_global;
-    uInt size_extrafield_global;
-    const char* comment;
-    int method;
-    int level;
-    int raw;
-    int windowBits;
-    int memLevel;
-    int strategy;
-    const char* password;
-    uLong crcForCrypting;
-{
-    zip_internal* zi;
-    uInt size_filename;
-    uInt size_comment;
-    uInt i;
-    int err = ZIP_OK;
-
-#    ifdef NOCRYPT
-    if (password != NULL)
-        return ZIP_PARAMERROR;
-#    endif
-
-    if (file == NULL)
-        return ZIP_PARAMERROR;
-    if ((method!=0) && (method!=Z_DEFLATED))
-        return ZIP_PARAMERROR;
-
-    zi = (zip_internal*)file;
-
-    if (zi->in_opened_file_inzip == 1)
-    {
-        err = zipCloseFileInZip (file);
-        if (err != ZIP_OK)
-            return err;
-    }
-
-
-    if (filename==NULL)
-        filename="-";
-
-    if (comment==NULL)
-        size_comment = 0;
-    else
-        size_comment = (uInt)strlen(comment);
-
-    size_filename = (uInt)strlen(filename);
-
-    if (zipfi == NULL)
-        zi->ci.dosDate = 0;
-    else
-    {
-        if (zipfi->dosDate != 0)
-            zi->ci.dosDate = zipfi->dosDate;
-        else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
-    }
-
-    zi->ci.flag = 0;
-    if ((level==8) || (level==9))
-      zi->ci.flag |= 2;
-    if ((level==2))
-      zi->ci.flag |= 4;
-    if ((level==1))
-      zi->ci.flag |= 6;
-    if (password != NULL)
-      zi->ci.flag |= 1;
-
-    zi->ci.crc32 = 0;
-    zi->ci.method = method;
-    zi->ci.encrypt = 0;
-    zi->ci.stream_initialised = 0;
-    zi->ci.pos_in_buffered_data = 0;
-    zi->ci.raw = raw;
-    zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ;
-    zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +
-                                      size_extrafield_global + size_comment;
-    zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
-
-    ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
-    /* version info */
-    ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
-    ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
-    ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
-    ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
-    ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
-
-    if (zipfi==NULL)
-        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
-    else
-        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
-
-    if (zipfi==NULL)
-        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
-    else
-        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
-
-    ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);
-
-    for (i=0;i<size_filename;i++)
-        *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
-
-    for (i=0;i<size_extrafield_global;i++)
-        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
-              *(((const char*)extrafield_global)+i);
-
-    for (i=0;i<size_comment;i++)
-        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
-              size_extrafield_global+i) = *(comment+i);
-    if (zi->ci.central_header == NULL)
-        return ZIP_INTERNALERROR;
-
-    /* write the local header */
-    err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4);
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2);
-
-    if ((err==ZIP_OK) && (size_filename>0))
-        if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
-                err = ZIP_ERRNO;
-
-    if ((err==ZIP_OK) && (size_extrafield_local>0))
-        if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local)
-                                                                           !=size_extrafield_local)
-                err = ZIP_ERRNO;
-
-    zi->ci.stream.avail_in = (uInt)0;
-    zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
-    zi->ci.stream.next_out = zi->ci.buffered_data;
-    zi->ci.stream.total_in = 0;
-    zi->ci.stream.total_out = 0;
-
-    if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
-    {
-        zi->ci.stream.zalloc = (alloc_func)0;
-        zi->ci.stream.zfree = (free_func)0;
-        zi->ci.stream.opaque = (voidpf)0;
-
-        if (windowBits>0)
-            windowBits = -windowBits;
-
-        err = deflateInit2(&zi->ci.stream, level,
-               Z_DEFLATED, windowBits, memLevel, strategy);
-
-        if (err==Z_OK)
-            zi->ci.stream_initialised = 1;
-    }
-#    ifndef NOCRYPT
-    zi->ci.crypt_header_size = 0;
-    if ((err==Z_OK) && (password != NULL))
-    {
-        unsigned char bufHead[RAND_HEAD_LEN];
-        unsigned int sizeHead;
-        zi->ci.encrypt = 1;
-        zi->ci.pcrc_32_tab = get_crc_table();
-        /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
-
-        sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
-        zi->ci.crypt_header_size = sizeHead;
-
-        if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
-                err = ZIP_ERRNO;
-    }
-#    endif
-
-    if (err==Z_OK)
-        zi->in_opened_file_inzip = 1;
-    return err;
-}
-
-extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi,
-                                        extrafield_local, size_extrafield_local,
-                                        extrafield_global, size_extrafield_global,
-                                        comment, method, level, raw)
-    zipFile file;
-    const char* filename;
-    const zip_fileinfo* zipfi;
-    const void* extrafield_local;
-    uInt size_extrafield_local;
-    const void* extrafield_global;
-    uInt size_extrafield_global;
-    const char* comment;
-    int method;
-    int level;
-    int raw;
-{
-    return zipOpenNewFileInZip3 (file, filename, zipfi,
-                                 extrafield_local, size_extrafield_local,
-                                 extrafield_global, size_extrafield_global,
-                                 comment, method, level, raw,
-                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
-                                 NULL, 0);
-}
-
-extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi,
-                                        extrafield_local, size_extrafield_local,
-                                        extrafield_global, size_extrafield_global,
-                                        comment, method, level)
-    zipFile file;
-    const char* filename;
-    const zip_fileinfo* zipfi;
-    const void* extrafield_local;
-    uInt size_extrafield_local;
-    const void* extrafield_global;
-    uInt size_extrafield_global;
-    const char* comment;
-    int method;
-    int level;
-{
-    return zipOpenNewFileInZip2 (file, filename, zipfi,
-                                 extrafield_local, size_extrafield_local,
-                                 extrafield_global, size_extrafield_global,
-                                 comment, method, level, 0);
-}
-
-local int zipFlushWriteBuffer(zi)
-  zip_internal* zi;
-{
-    int err=ZIP_OK;
-
-    if (zi->ci.encrypt != 0)
-    {
-#ifndef NOCRYPT
-        uInt i;
-        int t;
-        for (i=0;i<zi->ci.pos_in_buffered_data;i++)
-            zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab,
-                                       zi->ci.buffered_data[i],t);
-#endif
-    }
-    if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data)
-                                                                    !=zi->ci.pos_in_buffered_data)
-      err = ZIP_ERRNO;
-    zi->ci.pos_in_buffered_data = 0;
-    return err;
-}
-
-extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
-    zipFile file;
-    const void* buf;
-    unsigned len;
-{
-    zip_internal* zi;
-    int err=ZIP_OK;
-
-    if (file == NULL)
-        return ZIP_PARAMERROR;
-    zi = (zip_internal*)file;
-
-    if (zi->in_opened_file_inzip == 0)
-        return ZIP_PARAMERROR;
-
-    zi->ci.stream.next_in = (void*)buf;
-    zi->ci.stream.avail_in = len;
-    zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
-
-    while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
-    {
-        if (zi->ci.stream.avail_out == 0)
-        {
-            if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
-                err = ZIP_ERRNO;
-            zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
-            zi->ci.stream.next_out = zi->ci.buffered_data;
-        }
-
-
-        if(err != ZIP_OK)
-            break;
-
-        if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
-        {
-            uLong uTotalOutBefore = zi->ci.stream.total_out;
-            err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
-            zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
-
-        }
-        else
-        {
-            uInt copy_this,i;
-            if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
-                copy_this = zi->ci.stream.avail_in;
-            else
-                copy_this = zi->ci.stream.avail_out;
-            for (i=0;i<copy_this;i++)
-                *(((char*)zi->ci.stream.next_out)+i) =
-                    *(((const char*)zi->ci.stream.next_in)+i);
-            {
-                zi->ci.stream.avail_in -= copy_this;
-                zi->ci.stream.avail_out-= copy_this;
-                zi->ci.stream.next_in+= copy_this;
-                zi->ci.stream.next_out+= copy_this;
-                zi->ci.stream.total_in+= copy_this;
-                zi->ci.stream.total_out+= copy_this;
-                zi->ci.pos_in_buffered_data += copy_this;
-            }
-        }
-    }
-
-    return err;
-}
-
-extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32)
-    zipFile file;
-    uLong uncompressed_size;
-    uLong crc32;
-{
-    zip_internal* zi;
-    uLong compressed_size;
-    int err=ZIP_OK;
-
-    if (file == NULL)
-        return ZIP_PARAMERROR;
-    zi = (zip_internal*)file;
-
-    if (zi->in_opened_file_inzip == 0)
-        return ZIP_PARAMERROR;
-    zi->ci.stream.avail_in = 0;
-
-    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
-        while (err==ZIP_OK)
-    {
-        uLong uTotalOutBefore;
-        if (zi->ci.stream.avail_out == 0)
-        {
-            if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
-                err = ZIP_ERRNO;
-            zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
-            zi->ci.stream.next_out = zi->ci.buffered_data;
-        }
-        uTotalOutBefore = zi->ci.stream.total_out;
-        err=deflate(&zi->ci.stream,  Z_FINISH);
-        zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
-    }
-
-    if (err==Z_STREAM_END)
-        err=ZIP_OK; /* this is normal */
-
-    if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
-        if (zipFlushWriteBuffer(zi)==ZIP_ERRNO)
-            err = ZIP_ERRNO;
-
-    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
-    {
-        err=deflateEnd(&zi->ci.stream);
-        zi->ci.stream_initialised = 0;
-    }
-
-    if (!zi->ci.raw)
-    {
-        crc32 = (uLong)zi->ci.crc32;
-        uncompressed_size = (uLong)zi->ci.stream.total_in;
-    }
-    compressed_size = (uLong)zi->ci.stream.total_out;
-#    ifndef NOCRYPT
-    compressed_size += zi->ci.crypt_header_size;
-#    endif
-
-    ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
-    ziplocal_putValue_inmemory(zi->ci.central_header+20,
-                                compressed_size,4); /*compr size*/
-    if (zi->ci.stream.data_type == Z_ASCII)
-        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+24,
-                                uncompressed_size,4); /*uncompr size*/
-
-    if (err==ZIP_OK)
-        err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
-                                       (uLong)zi->ci.size_centralheader);
-    free(zi->ci.central_header);
-
-    if (err==ZIP_OK)
-    {
-        long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
-        if (ZSEEK(zi->z_filefunc,zi->filestream,
-                  zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
-            err = ZIP_ERRNO;
-
-        if (err==ZIP_OK)
-            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
-
-        if (err==ZIP_OK) /* compressed size, unknown */
-            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
-
-        if (err==ZIP_OK) /* uncompressed size, unknown */
-            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
-
-        if (ZSEEK(zi->z_filefunc,zi->filestream,
-                  cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
-            err = ZIP_ERRNO;
-    }
-
-    zi->number_entry ++;
-    zi->in_opened_file_inzip = 0;
-
-    return err;
-}
-
-extern int ZEXPORT zipCloseFileInZip (file)
-    zipFile file;
-{
-    return zipCloseFileInZipRaw (file,0,0);
-}
-
-extern int ZEXPORT zipClose (file, global_comment)
-    zipFile file;
-    const char* global_comment;
-{
-    zip_internal* zi;
-    int err = 0;
-    uLong size_centraldir = 0;
-    uLong centraldir_pos_inzip ;
-    uInt size_global_comment;
-    if (file == NULL)
-        return ZIP_PARAMERROR;
-    zi = (zip_internal*)file;
-
-    if (zi->in_opened_file_inzip == 1)
-    {
-        err = zipCloseFileInZip (file);
-    }
-
-    if (global_comment==NULL)
-        size_global_comment = 0;
-    else
-        size_global_comment = (uInt)strlen(global_comment);
-
-
-    centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
-    if (err==ZIP_OK)
-    {
-        linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
-        while (ldi!=NULL)
-        {
-            if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
-                if (ZWRITE(zi->z_filefunc,zi->filestream,
-                           ldi->data,ldi->filled_in_this_block)
-                              !=ldi->filled_in_this_block )
-                    err = ZIP_ERRNO;
-
-            size_centraldir += ldi->filled_in_this_block;
-            ldi = ldi->next_datablock;
-        }
-    }
-    free_datablock(zi->central_dir.first_block);
-
-    if (err==ZIP_OK) /* Magic End */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
-
-    if (err==ZIP_OK) /* number of this disk */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
-
-    if (err==ZIP_OK) /* number of the disk with the start of the central directory */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
-
-    if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
-
-    if (err==ZIP_OK) /* total number of entries in the central dir */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
-
-    if (err==ZIP_OK) /* size of the central directory */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
-
-    if (err==ZIP_OK) /* offset of start of central directory with respect to the
-                            starting disk number */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,
-                                (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
-
-    if (err==ZIP_OK) /* zipfile comment length */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
-
-    if ((err==ZIP_OK) && (size_global_comment>0))
-        if (ZWRITE(zi->z_filefunc,zi->filestream,
-                   global_comment,size_global_comment) != size_global_comment)
-                err = ZIP_ERRNO;
-
-    if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0)
-        if (err == ZIP_OK)
-            err = ZIP_ERRNO;
-
-    TRYFREE(zi);
-
-    return err;
-}
+/* zip.c -- IO on .zip files using zlib\r
+   Version 1.01e, February 12th, 2005\r
+\r
+   27 Dec 2004 Rolf Kalbermatter\r
+   Modification to zipOpen2 to support globalComment retrieval.\r
+\r
+   Copyright (C) 1998-2005 Gilles Vollant\r
+\r
+   Read zip.h for more info\r
+*/\r
+\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <time.h>\r
+#include "zlib.h"\r
+#include "zip.h"\r
+\r
+#ifdef STDC\r
+#  include <stddef.h>\r
+#  include <string.h>\r
+#  include <stdlib.h>\r
+#endif\r
+#ifdef NO_ERRNO_H\r
+    extern int errno;\r
+#else\r
+#   include <errno.h>\r
+#endif\r
+\r
+\r
+#ifndef local\r
+#  define local static\r
+#endif\r
+/* compile with -Dlocal if your debugger can't find static symbols */\r
+\r
+#ifndef VERSIONMADEBY\r
+# define VERSIONMADEBY   (0x0) /* platform depedent */\r
+#endif\r
+\r
+#ifndef Z_BUFSIZE\r
+#define Z_BUFSIZE (16384)\r
+#endif\r
+\r
+#ifndef Z_MAXFILENAMEINZIP\r
+#define Z_MAXFILENAMEINZIP (256)\r
+#endif\r
+\r
+#ifndef ALLOC\r
+# define ALLOC(size) (malloc(size))\r
+#endif\r
+#ifndef TRYFREE\r
+# define TRYFREE(p) {if (p) free(p);}\r
+#endif\r
+\r
+/*\r
+#define SIZECENTRALDIRITEM (0x2e)\r
+#define SIZEZIPLOCALHEADER (0x1e)\r
+*/\r
+\r
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */\r
+\r
+#ifndef SEEK_CUR\r
+#define SEEK_CUR    1\r
+#endif\r
+\r
+#ifndef SEEK_END\r
+#define SEEK_END    2\r
+#endif\r
+\r
+#ifndef SEEK_SET\r
+#define SEEK_SET    0\r
+#endif\r
+\r
+#ifndef DEF_MEM_LEVEL\r
+#if MAX_MEM_LEVEL >= 8\r
+#  define DEF_MEM_LEVEL 8\r
+#else\r
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL\r
+#endif\r
+#endif\r
+const char zip_copyright[] =\r
+   " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";\r
+\r
+\r
+#define SIZEDATA_INDATABLOCK (4096-(4*4))\r
+\r
+#define LOCALHEADERMAGIC    (0x04034b50)\r
+#define CENTRALHEADERMAGIC  (0x02014b50)\r
+#define ENDHEADERMAGIC      (0x06054b50)\r
+\r
+#define FLAG_LOCALHEADER_OFFSET (0x06)\r
+#define CRC_LOCALHEADER_OFFSET  (0x0e)\r
+\r
+#define SIZECENTRALHEADER (0x2e) /* 46 */\r
+\r
+typedef struct linkedlist_datablock_internal_s\r
+{\r
+  struct linkedlist_datablock_internal_s* next_datablock;\r
+  uLong  avail_in_this_block;\r
+  uLong  filled_in_this_block;\r
+  uLong  unused; /* for future use and alignement */\r
+  unsigned char data[SIZEDATA_INDATABLOCK];\r
+} linkedlist_datablock_internal;\r
+\r
+typedef struct linkedlist_data_s\r
+{\r
+    linkedlist_datablock_internal* first_block;\r
+    linkedlist_datablock_internal* last_block;\r
+} linkedlist_data;\r
+\r
+\r
+typedef struct\r
+{\r
+    z_stream stream;            /* zLib stream structure for inflate */\r
+    int  stream_initialised;    /* 1 is stream is initialised */\r
+    uInt pos_in_buffered_data;  /* last written byte in buffered_data */\r
+\r
+    uLong pos_local_header;     /* offset of the local header of the file\r
+                                     currenty writing */\r
+    char* central_header;       /* central header data for the current file */\r
+    uLong size_centralheader;   /* size of the central header for cur file */\r
+    uLong flag;                 /* flag of the file currently writing */\r
+\r
+    int  method;                /* compression method of file currenty wr.*/\r
+    int  raw;                   /* 1 for directly writing raw data */\r
+    Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/\r
+    uLong dosDate;\r
+    uLong crc32;\r
+    int  encrypt;\r
+#ifndef NOCRYPT\r
+    unsigned long keys[3];     /* keys defining the pseudo-random sequence */\r
+    const unsigned long* pcrc_32_tab;\r
+    int crypt_header_size;\r
+#endif\r
+} curfile_info;\r
+\r
+typedef struct\r
+{\r
+    zlib_filefunc_def z_filefunc;\r
+    voidpf filestream;        /* io structore of the zipfile */\r
+    linkedlist_data central_dir;/* datablock with central dir in construction*/\r
+    int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/\r
+    curfile_info ci;            /* info on the file curretly writing */\r
+\r
+    uLong begin_pos;            /* position of the beginning of the zipfile */\r
+    uLong add_position_when_writting_offset;\r
+    uLong number_entry;\r
+#ifndef NO_ADDFILEINEXISTINGZIP\r
+    char *globalcomment;\r
+#endif\r
+} zip_internal;\r
+\r
+\r
+\r
+#ifndef NOCRYPT\r
+#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED\r
+#include "crypt.h"\r
+#endif\r
+\r
+local linkedlist_datablock_internal* allocate_new_datablock()\r
+{\r
+    linkedlist_datablock_internal* ldi;\r
+    ldi = (linkedlist_datablock_internal*)\r
+                 ALLOC(sizeof(linkedlist_datablock_internal));\r
+    if (ldi!=NULL)\r
+    {\r
+        ldi->next_datablock = NULL ;\r
+        ldi->filled_in_this_block = 0 ;\r
+        ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;\r
+    }\r
+    return ldi;\r
+}\r
+\r
+local void free_datablock(ldi)\r
+    linkedlist_datablock_internal* ldi;\r
+{\r
+    while (ldi!=NULL)\r
+    {\r
+        linkedlist_datablock_internal* ldinext = ldi->next_datablock;\r
+        TRYFREE(ldi);\r
+        ldi = ldinext;\r
+    }\r
+}\r
+\r
+local void init_linkedlist(ll)\r
+    linkedlist_data* ll;\r
+{\r
+    ll->first_block = ll->last_block = NULL;\r
+}\r
+\r
+local void free_linkedlist(ll)\r
+    linkedlist_data* ll;\r
+{\r
+    free_datablock(ll->first_block);\r
+    ll->first_block = ll->last_block = NULL;\r
+}\r
+\r
+\r
+local int add_data_in_datablock(ll,buf,len)\r
+    linkedlist_data* ll;\r
+    const void* buf;\r
+    uLong len;\r
+{\r
+    linkedlist_datablock_internal* ldi;\r
+    const unsigned char* from_copy;\r
+\r
+    if (ll==NULL)\r
+        return ZIP_INTERNALERROR;\r
+\r
+    if (ll->last_block == NULL)\r
+    {\r
+        ll->first_block = ll->last_block = allocate_new_datablock();\r
+        if (ll->first_block == NULL)\r
+            return ZIP_INTERNALERROR;\r
+    }\r
+\r
+    ldi = ll->last_block;\r
+    from_copy = (unsigned char*)buf;\r
+\r
+    while (len>0)\r
+    {\r
+        uInt copy_this;\r
+        uInt i;\r
+        unsigned char* to_copy;\r
+\r
+        if (ldi->avail_in_this_block==0)\r
+        {\r
+            ldi->next_datablock = allocate_new_datablock();\r
+            if (ldi->next_datablock == NULL)\r
+                return ZIP_INTERNALERROR;\r
+            ldi = ldi->next_datablock ;\r
+            ll->last_block = ldi;\r
+        }\r
+\r
+        if (ldi->avail_in_this_block < len)\r
+            copy_this = (uInt)ldi->avail_in_this_block;\r
+        else\r
+            copy_this = (uInt)len;\r
+\r
+        to_copy = &(ldi->data[ldi->filled_in_this_block]);\r
+\r
+        for (i=0;i<copy_this;i++)\r
+            *(to_copy+i)=*(from_copy+i);\r
+\r
+        ldi->filled_in_this_block += copy_this;\r
+        ldi->avail_in_this_block -= copy_this;\r
+        from_copy += copy_this ;\r
+        len -= copy_this;\r
+    }\r
+    return ZIP_OK;\r
+}\r
+\r
+\r
+\r
+/****************************************************************************/\r
+\r
+#ifndef NO_ADDFILEINEXISTINGZIP\r
+/* ===========================================================================\r
+   Inputs a long in LSB order to the given file\r
+   nbByte == 1, 2 or 4 (byte, short or long)\r
+*/\r
+\r
+local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def,\r
+                                voidpf filestream, uLong x, int nbByte));\r
+local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte)\r
+    const zlib_filefunc_def* pzlib_filefunc_def;\r
+    voidpf filestream;\r
+    uLong x;\r
+    int nbByte;\r
+{\r
+    unsigned char buf[4];\r
+    int n;\r
+    for (n = 0; n < nbByte; n++)\r
+    {\r
+        buf[n] = (unsigned char)(x & 0xff);\r
+        x >>= 8;\r
+    }\r
+    if (x != 0)\r
+      {     /* data overflow - hack for ZIP64 (X Roche) */\r
+      for (n = 0; n < nbByte; n++)\r
+        {\r
+          buf[n] = 0xff;\r
+        }\r
+      }\r
+\r
+    if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)\r
+        return ZIP_ERRNO;\r
+    else\r
+        return ZIP_OK;\r
+}\r
+\r
+local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));\r
+local void ziplocal_putValue_inmemory (dest, x, nbByte)\r
+    void* dest;\r
+    uLong x;\r
+    int nbByte;\r
+{\r
+    unsigned char* buf=(unsigned char*)dest;\r
+    int n;\r
+    for (n = 0; n < nbByte; n++) {\r
+        buf[n] = (unsigned char)(x & 0xff);\r
+        x >>= 8;\r
+    }\r
+\r
+    if (x != 0)\r
+    {     /* data overflow - hack for ZIP64 */\r
+       for (n = 0; n < nbByte; n++)\r
+       {\r
+          buf[n] = 0xff;\r
+       }\r
+    }\r
+}\r
+\r
+/****************************************************************************/\r
+\r
+\r
+local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)\r
+    const tm_zip* ptm;\r
+    uLong dosDate;\r
+{\r
+    uLong year = (uLong)ptm->tm_year;\r
+    if (year>1980)\r
+        year-=1980;\r
+    else if (year>80)\r
+        year-=80;\r
+    return\r
+      (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |\r
+        ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));\r
+}\r
+\r
+\r
+/****************************************************************************/\r
+\r
+local int ziplocal_getByte OF((\r
+    const zlib_filefunc_def* pzlib_filefunc_def,\r
+    voidpf filestream,\r
+    int *pi));\r
+\r
+local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)\r
+    const zlib_filefunc_def* pzlib_filefunc_def;\r
+    voidpf filestream;\r
+    int *pi;\r
+{\r
+    unsigned char c;\r
+    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);\r
+    if (err==1)\r
+    {\r
+        *pi = (int)c;\r
+        return ZIP_OK;\r
+    }\r
+    else\r
+    {\r
+        if (ZERROR(*pzlib_filefunc_def,filestream))\r
+            return ZIP_ERRNO;\r
+        else\r
+            return ZIP_EOF;\r
+    }\r
+}\r
+\r
+\r
+/* ===========================================================================\r
+   Reads a long in LSB order from the given gz_stream. Sets\r
+*/\r
+local int ziplocal_getShort OF((\r
+    const zlib_filefunc_def* pzlib_filefunc_def,\r
+    voidpf filestream,\r
+    uLong *pX));\r
+\r
+local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX)\r
+    const zlib_filefunc_def* pzlib_filefunc_def;\r
+    voidpf filestream;\r
+    uLong *pX;\r
+{\r
+    uLong x ;\r
+    int i;\r
+    int err;\r
+\r
+    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x = (uLong)i;\r
+\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x += ((uLong)i)<<8;\r
+\r
+    if (err==ZIP_OK)\r
+        *pX = x;\r
+    else\r
+        *pX = 0;\r
+    return err;\r
+}\r
+\r
+local int ziplocal_getLong OF((\r
+    const zlib_filefunc_def* pzlib_filefunc_def,\r
+    voidpf filestream,\r
+    uLong *pX));\r
+\r
+local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)\r
+    const zlib_filefunc_def* pzlib_filefunc_def;\r
+    voidpf filestream;\r
+    uLong *pX;\r
+{\r
+    uLong x ;\r
+    int i;\r
+    int err;\r
+\r
+    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x = (uLong)i;\r
+\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x += ((uLong)i)<<8;\r
+\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x += ((uLong)i)<<16;\r
+\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);\r
+    x += ((uLong)i)<<24;\r
+\r
+    if (err==ZIP_OK)\r
+        *pX = x;\r
+    else\r
+        *pX = 0;\r
+    return err;\r
+}\r
+\r
+#ifndef BUFREADCOMMENT\r
+#define BUFREADCOMMENT (0x400)\r
+#endif\r
+/*\r
+  Locate the Central directory of a zipfile (at the end, just before\r
+    the global comment)\r
+*/\r
+local uLong ziplocal_SearchCentralDir OF((\r
+    const zlib_filefunc_def* pzlib_filefunc_def,\r
+    voidpf filestream));\r
+\r
+local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream)\r
+    const zlib_filefunc_def* pzlib_filefunc_def;\r
+    voidpf filestream;\r
+{\r
+    unsigned char* buf;\r
+    uLong uSizeFile;\r
+    uLong uBackRead;\r
+    uLong uMaxBack=0xffff; /* maximum size of global comment */\r
+    uLong uPosFound=0;\r
+\r
+    if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)\r
+        return 0;\r
+\r
+\r
+    uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);\r
+\r
+    if (uMaxBack>uSizeFile)\r
+        uMaxBack = uSizeFile;\r
+\r
+    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);\r
+    if (buf==NULL)\r
+        return 0;\r
+\r
+    uBackRead = 4;\r
+    while (uBackRead<uMaxBack)\r
+    {\r
+        uLong uReadSize,uReadPos ;\r
+        int i;\r
+        if (uBackRead+BUFREADCOMMENT>uMaxBack)\r
+            uBackRead = uMaxBack;\r
+        else\r
+            uBackRead+=BUFREADCOMMENT;\r
+        uReadPos = uSizeFile-uBackRead ;\r
+\r
+        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?\r
+                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);\r
+        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+            break;\r
+\r
+        if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)\r
+            break;\r
+\r
+        for (i=(int)uReadSize-3; (i--)>0;)\r
+            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&\r
+                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))\r
+            {\r
+                uPosFound = uReadPos+i;\r
+                break;\r
+            }\r
+\r
+        if (uPosFound!=0)\r
+            break;\r
+    }\r
+    TRYFREE(buf);\r
+    return uPosFound;\r
+}\r
+#endif /* !NO_ADDFILEINEXISTINGZIP*/\r
+\r
+/************************************************************/\r
+extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def)\r
+    const char *pathname;\r
+    int append;\r
+    zipcharpc* globalcomment;\r
+    zlib_filefunc_def* pzlib_filefunc_def;\r
+{\r
+    zip_internal ziinit;\r
+    zip_internal* zi;\r
+    int err=ZIP_OK;\r
+\r
+\r
+    if (pzlib_filefunc_def==NULL)\r
+        fill_fopen_filefunc(&ziinit.z_filefunc);\r
+    else\r
+        ziinit.z_filefunc = *pzlib_filefunc_def;\r
+\r
+    ziinit.filestream = (*(ziinit.z_filefunc.zopen_file))\r
+                 (ziinit.z_filefunc.opaque,\r
+                  pathname,\r
+                  (append == APPEND_STATUS_CREATE) ?\r
+                  (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :\r
+                    (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));\r
+\r
+    if (ziinit.filestream == NULL)\r
+        return NULL;\r
+    ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream);\r
+    ziinit.in_opened_file_inzip = 0;\r
+    ziinit.ci.stream_initialised = 0;\r
+    ziinit.number_entry = 0;\r
+    ziinit.add_position_when_writting_offset = 0;\r
+    init_linkedlist(&(ziinit.central_dir));\r
+\r
+\r
+    zi = (zip_internal*)ALLOC(sizeof(zip_internal));\r
+    if (zi==NULL)\r
+    {\r
+        ZCLOSE(ziinit.z_filefunc,ziinit.filestream);\r
+        return NULL;\r
+    }\r
+\r
+    /* now we add file in a zipfile */\r
+#    ifndef NO_ADDFILEINEXISTINGZIP\r
+    ziinit.globalcomment = NULL;\r
+    if (append == APPEND_STATUS_ADDINZIP)\r
+    {\r
+        uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/\r
+\r
+        uLong size_central_dir;     /* size of the central directory  */\r
+        uLong offset_central_dir;   /* offset of start of central directory */\r
+        uLong central_pos,uL;\r
+\r
+        uLong number_disk;          /* number of the current dist, used for\r
+                                    spaning ZIP, unsupported, always 0*/\r
+        uLong number_disk_with_CD;  /* number the the disk with central dir, used\r
+                                    for spaning ZIP, unsupported, always 0*/\r
+        uLong number_entry;\r
+        uLong number_entry_CD;      /* total number of entries in\r
+                                    the central dir\r
+                                    (same than number_entry on nospan) */\r
+        uLong size_comment;\r
+\r
+        central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);\r
+        if (central_pos==0)\r
+            err=ZIP_ERRNO;\r
+\r
+        if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,\r
+                                        central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+            err=ZIP_ERRNO;\r
+\r
+        /* the signature, already checked */\r
+        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK)\r
+            err=ZIP_ERRNO;\r
+\r
+        /* number of this disk */\r
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK)\r
+            err=ZIP_ERRNO;\r
+\r
+        /* number of the disk with the start of the central directory */\r
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK)\r
+            err=ZIP_ERRNO;\r
+\r
+        /* total number of entries in the central dir on this disk */\r
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK)\r
+            err=ZIP_ERRNO;\r
+\r
+        /* total number of entries in the central dir */\r
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK)\r
+            err=ZIP_ERRNO;\r
+\r
+        if ((number_entry_CD!=number_entry) ||\r
+            (number_disk_with_CD!=0) ||\r
+            (number_disk!=0))\r
+            err=ZIP_BADZIPFILE;\r
+\r
+        /* size of the central directory */\r
+        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK)\r
+            err=ZIP_ERRNO;\r
+\r
+        /* offset of start of central directory with respect to the\r
+            starting disk number */\r
+        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK)\r
+            err=ZIP_ERRNO;\r
+\r
+        /* zipfile global comment length */\r
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)\r
+            err=ZIP_ERRNO;\r
+\r
+        if ((central_pos<offset_central_dir+size_central_dir) &&\r
+            (err==ZIP_OK))\r
+            err=ZIP_BADZIPFILE;\r
+\r
+        if (err!=ZIP_OK)\r
+        {\r
+            ZCLOSE(ziinit.z_filefunc, ziinit.filestream);\r
+            return NULL;\r
+        }\r
+\r
+        if (size_comment>0)\r
+        {\r
+            ziinit.globalcomment = ALLOC(size_comment+1);\r
+            if (ziinit.globalcomment)\r
+            {\r
+               size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment);\r
+               ziinit.globalcomment[size_comment]=0;\r
+            }\r
+        }\r
+\r
+        byte_before_the_zipfile = central_pos -\r
+                                (offset_central_dir+size_central_dir);\r
+        ziinit.add_position_when_writting_offset = byte_before_the_zipfile;\r
+\r
+        {\r
+            uLong size_central_dir_to_read = size_central_dir;\r
+            size_t buf_size = SIZEDATA_INDATABLOCK;\r
+            void* buf_read = (void*)ALLOC(buf_size);\r
+            if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,\r
+                  offset_central_dir + byte_before_the_zipfile,\r
+                  ZLIB_FILEFUNC_SEEK_SET) != 0)\r
+                  err=ZIP_ERRNO;\r
+\r
+            while ((size_central_dir_to_read>0) && (err==ZIP_OK))\r
+            {\r
+                uLong read_this = SIZEDATA_INDATABLOCK;\r
+                if (read_this > size_central_dir_to_read)\r
+                    read_this = size_central_dir_to_read;\r
+                if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this)\r
+                    err=ZIP_ERRNO;\r
+\r
+                if (err==ZIP_OK)\r
+                    err = add_data_in_datablock(&ziinit.central_dir,buf_read,\r
+                                                (uLong)read_this);\r
+                size_central_dir_to_read-=read_this;\r
+            }\r
+            TRYFREE(buf_read);\r
+        }\r
+        ziinit.begin_pos = byte_before_the_zipfile;\r
+        ziinit.number_entry = number_entry_CD;\r
+\r
+        if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,\r
+                  offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+            err=ZIP_ERRNO;\r
+    }\r
+\r
+    if (globalcomment)\r
+    {\r
+      *globalcomment = ziinit.globalcomment;\r
+    }\r
+#    endif /* !NO_ADDFILEINEXISTINGZIP*/\r
+\r
+    if (err != ZIP_OK)\r
+    {\r
+#    ifndef NO_ADDFILEINEXISTINGZIP\r
+        TRYFREE(ziinit.globalcomment);\r
+#    endif /* !NO_ADDFILEINEXISTINGZIP*/\r
+        TRYFREE(zi);\r
+        return NULL;\r
+    }\r
+    else\r
+    {\r
+        *zi = ziinit;\r
+        return (zipFile)zi;\r
+    }\r
+}\r
+\r
+extern zipFile ZEXPORT zipOpen (pathname, append)\r
+    const char *pathname;\r
+    int append;\r
+{\r
+    return zipOpen2(pathname,append,NULL,NULL);\r
+}\r
+\r
+extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,\r
+                                         extrafield_local, size_extrafield_local,\r
+                                         extrafield_global, size_extrafield_global,\r
+                                         comment, method, level, raw,\r
+                                         windowBits, memLevel, strategy,\r
+                                         password, crcForCrypting)\r
+    zipFile file;\r
+    const char* filename;\r
+    const zip_fileinfo* zipfi;\r
+    const void* extrafield_local;\r
+    uInt size_extrafield_local;\r
+    const void* extrafield_global;\r
+    uInt size_extrafield_global;\r
+    const char* comment;\r
+    int method;\r
+    int level;\r
+    int raw;\r
+    int windowBits;\r
+    int memLevel;\r
+    int strategy;\r
+    const char* password;\r
+    uLong crcForCrypting;\r
+{\r
+    zip_internal* zi;\r
+    uInt size_filename;\r
+    uInt size_comment;\r
+    uInt i;\r
+    int err = ZIP_OK;\r
+\r
+#    ifdef NOCRYPT\r
+    if (password != NULL)\r
+        return ZIP_PARAMERROR;\r
+#    endif\r
+\r
+    if (file == NULL)\r
+        return ZIP_PARAMERROR;\r
+    if ((method!=0) && (method!=Z_DEFLATED))\r
+        return ZIP_PARAMERROR;\r
+\r
+    zi = (zip_internal*)file;\r
+\r
+    if (zi->in_opened_file_inzip == 1)\r
+    {\r
+        err = zipCloseFileInZip (file);\r
+        if (err != ZIP_OK)\r
+            return err;\r
+    }\r
+\r
+\r
+    if (filename==NULL)\r
+        filename="-";\r
+\r
+    if (comment==NULL)\r
+        size_comment = 0;\r
+    else\r
+        size_comment = (uInt)strlen(comment);\r
+\r
+    size_filename = (uInt)strlen(filename);\r
+\r
+    if (zipfi == NULL)\r
+        zi->ci.dosDate = 0;\r
+    else\r
+    {\r
+        if (zipfi->dosDate != 0)\r
+            zi->ci.dosDate = zipfi->dosDate;\r
+        else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);\r
+    }\r
+\r
+    zi->ci.flag = 0;\r
+    if ((level==8) || (level==9))\r
+      zi->ci.flag |= 2;\r
+    if ((level==2))\r
+      zi->ci.flag |= 4;\r
+    if ((level==1))\r
+      zi->ci.flag |= 6;\r
+    if (password != NULL)\r
+      zi->ci.flag |= 1;\r
+\r
+    zi->ci.crc32 = 0;\r
+    zi->ci.method = method;\r
+    zi->ci.encrypt = 0;\r
+    zi->ci.stream_initialised = 0;\r
+    zi->ci.pos_in_buffered_data = 0;\r
+    zi->ci.raw = raw;\r
+    zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ;\r
+    zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +\r
+                                      size_extrafield_global + size_comment;\r
+    zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);\r
+\r
+    ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);\r
+    /* version info */\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/\r
+\r
+    if (zipfi==NULL)\r
+        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);\r
+    else\r
+        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);\r
+\r
+    if (zipfi==NULL)\r
+        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);\r
+    else\r
+        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);\r
+\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);\r
+\r
+    for (i=0;i<size_filename;i++)\r
+        *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);\r
+\r
+    for (i=0;i<size_extrafield_global;i++)\r
+        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =\r
+              *(((const char*)extrafield_global)+i);\r
+\r
+    for (i=0;i<size_comment;i++)\r
+        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+\r
+              size_extrafield_global+i) = *(comment+i);\r
+    if (zi->ci.central_header == NULL)\r
+        return ZIP_INTERNALERROR;\r
+\r
+    /* write the local header */\r
+    err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4);\r
+\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);\r
+\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);\r
+\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);\r
+\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */\r
+\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);\r
+\r
+    if (err==ZIP_OK)\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2);\r
+\r
+    if ((err==ZIP_OK) && (size_filename>0))\r
+        if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)\r
+                err = ZIP_ERRNO;\r
+\r
+    if ((err==ZIP_OK) && (size_extrafield_local>0))\r
+        if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local)\r
+                                                                           !=size_extrafield_local)\r
+                err = ZIP_ERRNO;\r
+\r
+    zi->ci.stream.avail_in = (uInt)0;\r
+    zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;\r
+    zi->ci.stream.next_out = zi->ci.buffered_data;\r
+    zi->ci.stream.total_in = 0;\r
+    zi->ci.stream.total_out = 0;\r
+\r
+    if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))\r
+    {\r
+        zi->ci.stream.zalloc = (alloc_func)0;\r
+        zi->ci.stream.zfree = (free_func)0;\r
+        zi->ci.stream.opaque = (voidpf)0;\r
+\r
+        if (windowBits>0)\r
+            windowBits = -windowBits;\r
+\r
+        err = deflateInit2(&zi->ci.stream, level,\r
+               Z_DEFLATED, windowBits, memLevel, strategy);\r
+\r
+        if (err==Z_OK)\r
+            zi->ci.stream_initialised = 1;\r
+    }\r
+#    ifndef NOCRYPT\r
+    zi->ci.crypt_header_size = 0;\r
+    if ((err==Z_OK) && (password != NULL))\r
+    {\r
+        unsigned char bufHead[RAND_HEAD_LEN];\r
+        unsigned int sizeHead;\r
+        zi->ci.encrypt = 1;\r
+        zi->ci.pcrc_32_tab = get_crc_table();\r
+        /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/\r
+\r
+        sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);\r
+        zi->ci.crypt_header_size = sizeHead;\r
+\r
+        if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)\r
+                err = ZIP_ERRNO;\r
+    }\r
+#    endif\r
+\r
+    if (err==Z_OK)\r
+        zi->in_opened_file_inzip = 1;\r
+    return err;\r
+}\r
+\r
+extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi,\r
+                                        extrafield_local, size_extrafield_local,\r
+                                        extrafield_global, size_extrafield_global,\r
+                                        comment, method, level, raw)\r
+    zipFile file;\r
+    const char* filename;\r
+    const zip_fileinfo* zipfi;\r
+    const void* extrafield_local;\r
+    uInt size_extrafield_local;\r
+    const void* extrafield_global;\r
+    uInt size_extrafield_global;\r
+    const char* comment;\r
+    int method;\r
+    int level;\r
+    int raw;\r
+{\r
+    return zipOpenNewFileInZip3 (file, filename, zipfi,\r
+                                 extrafield_local, size_extrafield_local,\r
+                                 extrafield_global, size_extrafield_global,\r
+                                 comment, method, level, raw,\r
+                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,\r
+                                 NULL, 0);\r
+}\r
+\r
+extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi,\r
+                                        extrafield_local, size_extrafield_local,\r
+                                        extrafield_global, size_extrafield_global,\r
+                                        comment, method, level)\r
+    zipFile file;\r
+    const char* filename;\r
+    const zip_fileinfo* zipfi;\r
+    const void* extrafield_local;\r
+    uInt size_extrafield_local;\r
+    const void* extrafield_global;\r
+    uInt size_extrafield_global;\r
+    const char* comment;\r
+    int method;\r
+    int level;\r
+{\r
+    return zipOpenNewFileInZip2 (file, filename, zipfi,\r
+                                 extrafield_local, size_extrafield_local,\r
+                                 extrafield_global, size_extrafield_global,\r
+                                 comment, method, level, 0);\r
+}\r
+\r
+local int zipFlushWriteBuffer(zi)\r
+  zip_internal* zi;\r
+{\r
+    int err=ZIP_OK;\r
+\r
+    if (zi->ci.encrypt != 0)\r
+    {\r
+#ifndef NOCRYPT\r
+        uInt i;\r
+        int t;\r
+        for (i=0;i<zi->ci.pos_in_buffered_data;i++)\r
+            zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab,\r
+                                       zi->ci.buffered_data[i],t);\r
+#endif\r
+    }\r
+    if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data)\r
+                                                                    !=zi->ci.pos_in_buffered_data)\r
+      err = ZIP_ERRNO;\r
+    zi->ci.pos_in_buffered_data = 0;\r
+    return err;\r
+}\r
+\r
+extern int ZEXPORT zipWriteInFileInZip (file, buf, len)\r
+    zipFile file;\r
+    const void* buf;\r
+    unsigned len;\r
+{\r
+    zip_internal* zi;\r
+    int err=ZIP_OK;\r
+\r
+    if (file == NULL)\r
+        return ZIP_PARAMERROR;\r
+    zi = (zip_internal*)file;\r
+\r
+    if (zi->in_opened_file_inzip == 0)\r
+        return ZIP_PARAMERROR;\r
+\r
+    zi->ci.stream.next_in = (void*)buf;\r
+    zi->ci.stream.avail_in = len;\r
+    zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);\r
+\r
+    while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))\r
+    {\r
+        if (zi->ci.stream.avail_out == 0)\r
+        {\r
+            if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)\r
+                err = ZIP_ERRNO;\r
+            zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;\r
+            zi->ci.stream.next_out = zi->ci.buffered_data;\r
+        }\r
+\r
+\r
+        if(err != ZIP_OK)\r
+            break;\r
+\r
+        if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))\r
+        {\r
+            uLong uTotalOutBefore = zi->ci.stream.total_out;\r
+            err=deflate(&zi->ci.stream,  Z_NO_FLUSH);\r
+            zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;\r
+\r
+        }\r
+        else\r
+        {\r
+            uInt copy_this,i;\r
+            if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)\r
+                copy_this = zi->ci.stream.avail_in;\r
+            else\r
+                copy_this = zi->ci.stream.avail_out;\r
+            for (i=0;i<copy_this;i++)\r
+                *(((char*)zi->ci.stream.next_out)+i) =\r
+                    *(((const char*)zi->ci.stream.next_in)+i);\r
+            {\r
+                zi->ci.stream.avail_in -= copy_this;\r
+                zi->ci.stream.avail_out-= copy_this;\r
+                zi->ci.stream.next_in+= copy_this;\r
+                zi->ci.stream.next_out+= copy_this;\r
+                zi->ci.stream.total_in+= copy_this;\r
+                zi->ci.stream.total_out+= copy_this;\r
+                zi->ci.pos_in_buffered_data += copy_this;\r
+            }\r
+        }\r
+    }\r
+\r
+    return err;\r
+}\r
+\r
+extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32)\r
+    zipFile file;\r
+    uLong uncompressed_size;\r
+    uLong crc32;\r
+{\r
+    zip_internal* zi;\r
+    uLong compressed_size;\r
+    int err=ZIP_OK;\r
+\r
+    if (file == NULL)\r
+        return ZIP_PARAMERROR;\r
+    zi = (zip_internal*)file;\r
+\r
+    if (zi->in_opened_file_inzip == 0)\r
+        return ZIP_PARAMERROR;\r
+    zi->ci.stream.avail_in = 0;\r
+\r
+    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))\r
+        while (err==ZIP_OK)\r
+    {\r
+        uLong uTotalOutBefore;\r
+        if (zi->ci.stream.avail_out == 0)\r
+        {\r
+            if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)\r
+                err = ZIP_ERRNO;\r
+            zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;\r
+            zi->ci.stream.next_out = zi->ci.buffered_data;\r
+        }\r
+        uTotalOutBefore = zi->ci.stream.total_out;\r
+        err=deflate(&zi->ci.stream,  Z_FINISH);\r
+        zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;\r
+    }\r
+\r
+    if (err==Z_STREAM_END)\r
+        err=ZIP_OK; /* this is normal */\r
+\r
+    if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))\r
+        if (zipFlushWriteBuffer(zi)==ZIP_ERRNO)\r
+            err = ZIP_ERRNO;\r
+\r
+    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))\r
+    {\r
+        err=deflateEnd(&zi->ci.stream);\r
+        zi->ci.stream_initialised = 0;\r
+    }\r
+\r
+    if (!zi->ci.raw)\r
+    {\r
+        crc32 = (uLong)zi->ci.crc32;\r
+        uncompressed_size = (uLong)zi->ci.stream.total_in;\r
+    }\r
+    compressed_size = (uLong)zi->ci.stream.total_out;\r
+#    ifndef NOCRYPT\r
+    compressed_size += zi->ci.crypt_header_size;\r
+#    endif\r
+\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+20,\r
+                                compressed_size,4); /*compr size*/\r
+    if (zi->ci.stream.data_type == Z_ASCII)\r
+        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);\r
+    ziplocal_putValue_inmemory(zi->ci.central_header+24,\r
+                                uncompressed_size,4); /*uncompr size*/\r
+\r
+    if (err==ZIP_OK)\r
+        err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,\r
+                                       (uLong)zi->ci.size_centralheader);\r
+    free(zi->ci.central_header);\r
+\r
+    if (err==ZIP_OK)\r
+    {\r
+        long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);\r
+        if (ZSEEK(zi->z_filefunc,zi->filestream,\r
+                  zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+            err = ZIP_ERRNO;\r
+\r
+        if (err==ZIP_OK)\r
+            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */\r
+\r
+        if (err==ZIP_OK) /* compressed size, unknown */\r
+            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);\r
+\r
+        if (err==ZIP_OK) /* uncompressed size, unknown */\r
+            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);\r
+\r
+        if (ZSEEK(zi->z_filefunc,zi->filestream,\r
+                  cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
+            err = ZIP_ERRNO;\r
+    }\r
+\r
+    zi->number_entry ++;\r
+    zi->in_opened_file_inzip = 0;\r
+\r
+    return err;\r
+}\r
+\r
+extern int ZEXPORT zipCloseFileInZip (file)\r
+    zipFile file;\r
+{\r
+    return zipCloseFileInZipRaw (file,0,0);\r
+}\r
+\r
+extern int ZEXPORT zipClose (file, global_comment)\r
+    zipFile file;\r
+    const char* global_comment;\r
+{\r
+    zip_internal* zi;\r
+    int err = 0;\r
+    uLong size_centraldir = 0;\r
+    uLong centraldir_pos_inzip;\r
+    uInt size_global_comment;\r
+    if (file == NULL)\r
+        return ZIP_PARAMERROR;\r
+    zi = (zip_internal*)file;\r
+\r
+    if (zi->in_opened_file_inzip == 1)\r
+    {\r
+        err = zipCloseFileInZip (file);\r
+    }\r
+\r
+#ifndef NO_ADDFILEINEXISTINGZIP\r
+    if (global_comment==NULL)\r
+        global_comment = zi->globalcomment;\r
+#endif\r
+    if (global_comment==NULL)\r
+        size_global_comment = 0;\r
+    else\r
+        size_global_comment = (uInt)strlen(global_comment);\r
+\r
+    centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);\r
+    if (err==ZIP_OK)\r
+    {\r
+        linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;\r
+        while (ldi!=NULL)\r
+        {\r
+            if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))\r
+                if (ZWRITE(zi->z_filefunc,zi->filestream,\r
+                           ldi->data,ldi->filled_in_this_block)\r
+                              !=ldi->filled_in_this_block )\r
+                    err = ZIP_ERRNO;\r
+\r
+            size_centraldir += ldi->filled_in_this_block;\r
+            ldi = ldi->next_datablock;\r
+        }\r
+    }\r
+    free_datablock(zi->central_dir.first_block);\r
+\r
+    if (err==ZIP_OK) /* Magic End */\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);\r
+\r
+    if (err==ZIP_OK) /* number of this disk */\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);\r
+\r
+    if (err==ZIP_OK) /* number of the disk with the start of the central directory */\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);\r
+\r
+    if (err==ZIP_OK) /* total number of entries in the central dir on this disk */\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);\r
+\r
+    if (err==ZIP_OK) /* total number of entries in the central dir */\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);\r
+\r
+    if (err==ZIP_OK) /* size of the central directory */\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);\r
+\r
+    if (err==ZIP_OK) /* offset of start of central directory with respect to the\r
+                            starting disk number */\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,\r
+                                (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);\r
+\r
+    if (err==ZIP_OK) /* zipfile comment length */\r
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);\r
+\r
+    if ((err==ZIP_OK) && (size_global_comment>0))\r
+        if (ZWRITE(zi->z_filefunc,zi->filestream,\r
+                   global_comment,size_global_comment) != size_global_comment)\r
+                err = ZIP_ERRNO;\r
+\r
+    if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0)\r
+        if (err == ZIP_OK)\r
+            err = ZIP_ERRNO;\r
+\r
+#ifndef NO_ADDFILEINEXISTINGZIP\r
+    TRYFREE(zi->globalcomment);\r
+#endif\r
+    TRYFREE(zi);\r
+\r
+    return err;\r
+}\r
index d5112c4..cd38b67 100644 (file)
-/* zip.h -- IO for compress .zip files using zlib
-   Version 1.01, May 8th, 2004
-
-   Copyright (C) 1998-2004 Gilles Vollant
-
-   This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
-     WinZip, InfoZip tools and compatible.
-   Encryption and multi volume ZipFile (span) are not supported.
-   Old compressions used by old PKZip 1.x are not supported
-
-  For uncompress .zip file, look at unzip.h
-
-
-   I WAIT FEEDBACK at mail info@winimage.com
-   Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
-
-   Condition of use and distribution are the same than zlib :
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-
-*/
-
-/* for more info about .ZIP format, see
-      http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
-      http://www.info-zip.org/pub/infozip/doc/
-   PkWare has also a specification at :
-      ftp://ftp.pkware.com/probdesc.zip
-*/
-
-#ifndef _zip_H
-#define _zip_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _ZLIB_H
-#include "zlib.h"
-#endif
-
-#ifndef _ZLIBIOAPI_H
-#include "ioapi.h"
-#endif
-
-#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
-/* like the STRICT of WIN32, we define a pointer that cannot be converted
-    from (void*) without cast */
-typedef struct TagzipFile__ { int unused; } zipFile__;
-typedef zipFile__ *zipFile;
-#else
-typedef voidp zipFile;
-#endif
-
-#define ZIP_OK                          (0)
-#define ZIP_EOF                         (0)
-#define ZIP_ERRNO                       (Z_ERRNO)
-#define ZIP_PARAMERROR                  (-102)
-#define ZIP_BADZIPFILE                  (-103)
-#define ZIP_INTERNALERROR               (-104)
-
-#ifndef DEF_MEM_LEVEL
-#  if MAX_MEM_LEVEL >= 8
-#    define DEF_MEM_LEVEL 8
-#  else
-#    define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#  endif
-#endif
-/* default memLevel */
-
-/* tm_zip contain date/time info */
-typedef struct tm_zip_s
-{
-    uInt tm_sec;            /* seconds after the minute - [0,59] */
-    uInt tm_min;            /* minutes after the hour - [0,59] */
-    uInt tm_hour;           /* hours since midnight - [0,23] */
-    uInt tm_mday;           /* day of the month - [1,31] */
-    uInt tm_mon;            /* months since January - [0,11] */
-    uInt tm_year;           /* years - [1980..2044] */
-} tm_zip;
-
-typedef struct
-{
-    tm_zip      tmz_date;       /* date in understandable format           */
-    uLong       dosDate;       /* if dos_date == 0, tmu_date is used      */
-/*    uLong       flag;        */   /* general purpose bit flag        2 bytes */
-
-    uLong       internal_fa;    /* internal file attributes        2 bytes */
-    uLong       external_fa;    /* external file attributes        4 bytes */
-} zip_fileinfo;
-
-typedef const char* zipcharpc;
-
-
-#define APPEND_STATUS_CREATE        (0)
-#define APPEND_STATUS_CREATEAFTER   (1)
-#define APPEND_STATUS_ADDINZIP      (2)
-
-extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
-/*
-  Create a zipfile.
-     pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
-       an Unix computer "zlib/zlib113.zip".
-     if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
-       will be created at the end of the file.
-         (useful if the file contain a self extractor code)
-     if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
-       add files in existing zip (be sure you don't add file that doesn't exist)
-     If the zipfile cannot be opened, the return value is NULL.
-     Else, the return value is a zipFile Handle, usable with other function
-       of this zip package.
-*/
-
-/* Note : there is no delete function into a zipfile.
-   If you want delete file into a zipfile, you must open a zipfile, and create another
-   Of couse, you can use RAW reading and writing to copy the file you did not want delte
-*/
-
-extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
-                                   int append,
-                                   zipcharpc* globalcomment,
-                                   zlib_filefunc_def* pzlib_filefunc_def));
-
-extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
-                       const char* filename,
-                       const zip_fileinfo* zipfi,
-                       const void* extrafield_local,
-                       uInt size_extrafield_local,
-                       const void* extrafield_global,
-                       uInt size_extrafield_global,
-                       const char* comment,
-                       int method,
-                       int level));
-/*
-  Open a file in the ZIP for writing.
-  filename : the filename in zip (if NULL, '-' without quote will be used
-  *zipfi contain supplemental information
-  if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
-    contains the extrafield data the the local header
-  if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
-    contains the extrafield data the the local header
-  if comment != NULL, comment contain the comment string
-  method contain the compression method (0 for store, Z_DEFLATED for deflate)
-  level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
-*/
-
-
-extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
-                                            const char* filename,
-                                            const zip_fileinfo* zipfi,
-                                            const void* extrafield_local,
-                                            uInt size_extrafield_local,
-                                            const void* extrafield_global,
-                                            uInt size_extrafield_global,
-                                            const char* comment,
-                                            int method,
-                                            int level,
-                                            int raw));
-
-/*
-  Same than zipOpenNewFileInZip, except if raw=1, we write raw file
- */
-
-extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
-                                            const char* filename,
-                                            const zip_fileinfo* zipfi,
-                                            const void* extrafield_local,
-                                            uInt size_extrafield_local,
-                                            const void* extrafield_global,
-                                            uInt size_extrafield_global,
-                                            const char* comment,
-                                            int method,
-                                            int level,
-                                            int raw,
-                                            int windowBits,
-                                            int memLevel,
-                                            int strategy,
-                                            const char* password,
-                                            uLong crcForCtypting));
-
-/*
-  Same than zipOpenNewFileInZip2, except
-    windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
-    password : crypting password (NULL for no crypting)
-    crcForCtypting : crc of file to compress (needed for crypting)
- */
-
-
-extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
-                       const void* buf,
-                       unsigned len));
-/*
-  Write data in the zipfile
-*/
-
-extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
-/*
-  Close the current file in the zipfile
-*/
-
-extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
-                                            uLong uncompressed_size,
-                                            uLong crc32));
-/*
-  Close the current file in the zipfile, for fiel opened with
-    parameter raw=1 in zipOpenNewFileInZip2
-  uncompressed_size and crc32 are value for the uncompressed size
-*/
-
-extern int ZEXPORT zipClose OF((zipFile file,
-                const char* global_comment));
-/*
-  Close the zipfile
-*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _zip_H */
+/* zip.h -- IO for compress .zip files using zlib\r
+   Version 1.01e, February 12th, 2005\r
+\r
+   Copyright (C) 1998-2005 Gilles Vollant\r
+\r
+   This unzip package allow creates .ZIP file, compatible with PKZip 2.04g\r
+     WinZip, InfoZip tools and compatible.\r
+   Multi volume ZipFile (span) are not supported.\r
+   Encryption compatible with pkzip 2.04g only supported\r
+   Old compressions used by old PKZip 1.x are not supported\r
+\r
+  For uncompress .zip file, look at unzip.h\r
+\r
+\r
+   I WAIT FEEDBACK at mail info@winimage.com\r
+   Visit also http://www.winimage.com/zLibDll/unzip.html for evolution\r
+\r
+   Condition of use and distribution are the same than zlib :\r
+\r
+  This software is provided 'as-is', without any express or implied\r
+  warranty.  In no event will the authors be held liable for any damages\r
+  arising from the use of this software.\r
+\r
+  Permission is granted to anyone to use this software for any purpose,\r
+  including commercial applications, and to alter it and redistribute it\r
+  freely, subject to the following restrictions:\r
+\r
+  1. The origin of this software must not be misrepresented; you must not\r
+     claim that you wrote the original software. If you use this software\r
+     in a product, an acknowledgment in the product documentation would be\r
+     appreciated but is not required.\r
+  2. Altered source versions must be plainly marked as such, and must not be\r
+     misrepresented as being the original software.\r
+  3. This notice may not be removed or altered from any source distribution.\r
+\r
+\r
+*/\r
+\r
+/* for more info about .ZIP format, see\r
+      http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip\r
+      http://www.info-zip.org/pub/infozip/doc/\r
+   PkWare has also a specification at :\r
+      ftp://ftp.pkware.com/probdesc.zip\r
+*/\r
+\r
+#ifndef _zip_H\r
+#define _zip_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#ifndef _ZLIB_H\r
+#include "zlib.h"\r
+#endif\r
+\r
+#ifndef _ZLIBIOAPI_H\r
+#include "ioapi.h"\r
+#endif\r
+\r
+#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)\r
+/* like the STRICT of WIN32, we define a pointer that cannot be converted\r
+    from (void*) without cast */\r
+typedef struct TagzipFile__ { int unused; } zipFile__;\r
+typedef zipFile__ *zipFile;\r
+#else\r
+typedef voidp zipFile;\r
+#endif\r
+\r
+#define ZIP_OK                          (0)\r
+#define ZIP_EOF                         (0)\r
+#define ZIP_ERRNO                       (Z_ERRNO)\r
+#define ZIP_PARAMERROR                  (-102)\r
+#define ZIP_BADZIPFILE                  (-103)\r
+#define ZIP_INTERNALERROR               (-104)\r
+\r
+#ifndef DEF_MEM_LEVEL\r
+#  if MAX_MEM_LEVEL >= 8\r
+#    define DEF_MEM_LEVEL 8\r
+#  else\r
+#    define DEF_MEM_LEVEL  MAX_MEM_LEVEL\r
+#  endif\r
+#endif\r
+/* default memLevel */\r
+\r
+/* tm_zip contain date/time info */\r
+typedef struct tm_zip_s\r
+{\r
+    uInt tm_sec;            /* seconds after the minute - [0,59] */\r
+    uInt tm_min;            /* minutes after the hour - [0,59] */\r
+    uInt tm_hour;           /* hours since midnight - [0,23] */\r
+    uInt tm_mday;           /* day of the month - [1,31] */\r
+    uInt tm_mon;            /* months since January - [0,11] */\r
+    uInt tm_year;           /* years - [1980..2044] */\r
+} tm_zip;\r
+\r
+typedef struct\r
+{\r
+    tm_zip      tmz_date;       /* date in understandable format           */\r
+    uLong       dosDate;       /* if dos_date == 0, tmu_date is used      */\r
+/*    uLong       flag;        */   /* general purpose bit flag        2 bytes */\r
+\r
+    uLong       internal_fa;    /* internal file attributes        2 bytes */\r
+    uLong       external_fa;    /* external file attributes        4 bytes */\r
+} zip_fileinfo;\r
+\r
+typedef const char* zipcharpc;\r
+\r
+\r
+#define APPEND_STATUS_CREATE        (0)\r
+#define APPEND_STATUS_CREATEAFTER   (1)\r
+#define APPEND_STATUS_ADDINZIP      (2)\r
+\r
+extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));\r
+/*\r
+  Create a zipfile.\r
+     pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on\r
+       an Unix computer "zlib/zlib113.zip".\r
+     if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip\r
+       will be created at the end of the file.\r
+         (useful if the file contain a self extractor code)\r
+     if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will\r
+       add files in existing zip (be sure you don't add file that doesn't exist)\r
+     If the zipfile cannot be opened, the return value is NULL.\r
+     Else, the return value is a zipFile Handle, usable with other function\r
+       of this zip package.\r
+*/\r
+\r
+/* Note : there is no delete function into a zipfile.\r
+   If you want delete file into a zipfile, you must open a zipfile, and create another\r
+   Of couse, you can use RAW reading and writing to copy the file you did not want delte\r
+*/\r
+\r
+extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,\r
+                                   int append,\r
+                                   zipcharpc* globalcomment,\r
+                                   zlib_filefunc_def* pzlib_filefunc_def));\r
+\r
+extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,\r
+                       const char* filename,\r
+                       const zip_fileinfo* zipfi,\r
+                       const void* extrafield_local,\r
+                       uInt size_extrafield_local,\r
+                       const void* extrafield_global,\r
+                       uInt size_extrafield_global,\r
+                       const char* comment,\r
+                       int method,\r
+                       int level));\r
+/*\r
+  Open a file in the ZIP for writing.\r
+  filename : the filename in zip (if NULL, '-' without quote will be used\r
+  *zipfi contain supplemental information\r
+  if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local\r
+    contains the extrafield data the the local header\r
+  if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global\r
+    contains the extrafield data the the local header\r
+  if comment != NULL, comment contain the comment string\r
+  method contain the compression method (0 for store, Z_DEFLATED for deflate)\r
+  level contain the level of compression (can be Z_DEFAULT_COMPRESSION)\r
+*/\r
+\r
+\r
+extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,\r
+                                            const char* filename,\r
+                                            const zip_fileinfo* zipfi,\r
+                                            const void* extrafield_local,\r
+                                            uInt size_extrafield_local,\r
+                                            const void* extrafield_global,\r
+                                            uInt size_extrafield_global,\r
+                                            const char* comment,\r
+                                            int method,\r
+                                            int level,\r
+                                            int raw));\r
+\r
+/*\r
+  Same than zipOpenNewFileInZip, except if raw=1, we write raw file\r
+ */\r
+\r
+extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,\r
+                                            const char* filename,\r
+                                            const zip_fileinfo* zipfi,\r
+                                            const void* extrafield_local,\r
+                                            uInt size_extrafield_local,\r
+                                            const void* extrafield_global,\r
+                                            uInt size_extrafield_global,\r
+                                            const char* comment,\r
+                                            int method,\r
+                                            int level,\r
+                                            int raw,\r
+                                            int windowBits,\r
+                                            int memLevel,\r
+                                            int strategy,\r
+                                            const char* password,\r
+                                            uLong crcForCtypting));\r
+\r
+/*\r
+  Same than zipOpenNewFileInZip2, except\r
+    windowBits,memLevel,,strategy : see parameter strategy in deflateInit2\r
+    password : crypting password (NULL for no crypting)\r
+    crcForCtypting : crc of file to compress (needed for crypting)\r
+ */\r
+\r
+\r
+extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,\r
+                       const void* buf,\r
+                       unsigned len));\r
+/*\r
+  Write data in the zipfile\r
+*/\r
+\r
+extern int ZEXPORT zipCloseFileInZip OF((zipFile file));\r
+/*\r
+  Close the current file in the zipfile\r
+*/\r
+\r
+extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,\r
+                                            uLong uncompressed_size,\r
+                                            uLong crc32));\r
+/*\r
+  Close the current file in the zipfile, for fiel opened with\r
+    parameter raw=1 in zipOpenNewFileInZip2\r
+  uncompressed_size and crc32 are value for the uncompressed size\r
+*/\r
+\r
+extern int ZEXPORT zipClose OF((zipFile file,\r
+                const char* global_comment));\r
+/*\r
+  Close the zipfile\r
+*/\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* _zip_H */\r
diff --git a/zlib/contrib/testzlib/rdtsc64.asm b/zlib/contrib/testzlib/rdtsc64.asm
new file mode 100644 (file)
index 0000000..6b78a8b
--- /dev/null
@@ -0,0 +1,18 @@
+; rdtsc64.asm\r
+;\r
+; unsigned _int64 myrdtsc();\r
+;\r
+; return the performance rdtsc value, on AMD64/Intel EM64T\r
+;\r
+; compile with :\r
+;    ml64.exe" /Flrdtsc64   /c /Zi rdtsc64.asm\r
+;\r
+.code\r
+myrdtsc PROC\r
+          rdtsc\r
+          shl rdx,32\r
+          or rax,rdx\r
+          ret\r
+myrdtsc ENDP\r
+\r
+END\r
index fdabc5c..6c3ff9f 100644 (file)
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <windows.h>
-#include "zlib.h"
-
-int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)
-{
-    FILE* stream;
-    void* ptr;
-    int retVal=1;
-    stream=fopen(filename, "rb");
-    if (stream==NULL)
-        return 0;
-
-    fseek(stream,0,SEEK_END);
-
-    *plFileSize=ftell(stream);
-    fseek(stream,0,SEEK_SET);
-    ptr=malloc((*plFileSize)+1);
-    if (ptr==NULL)
-        retVal=0;
-    else
-    {
-        if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize))
-            retVal=0;
-    }
-    fclose(stream);
-    *pFilePtr=ptr;
-    return retVal;
-}
-
-int main(int argc, char *argv[])
-{
-    int BlockSizeCompress=0x8000;
-    int BlockSizeUncompress=0x8000;
-    int cprLevel=Z_DEFAULT_COMPRESSION ;
-    long lFileSize;
-    unsigned char* FilePtr;
-    long lBufferSizeCpr;
-    long lBufferSizeUncpr;
-    long lCompressedSize=0;
-    unsigned char* CprPtr;
-    unsigned char* UncprPtr;
-    long lSizeCpr,lSizeUncpr;
-    DWORD dwGetTick;
-
-    if (argc<=1)
-    {
-        printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n");
-        return 0;
-    }
-
-    if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0)
-    {
-        printf("error reading %s\n",argv[1]);
-        return 1;
-    }
-    else printf("file %s read, %u bytes\n",argv[1],lFileSize);
-
-    if (argc>=3)
-        BlockSizeCompress=atol(argv[2]);
-
-    if (argc>=4)
-        BlockSizeUncompress=atol(argv[3]);
-
-    if (argc>=5)
-        cprLevel=(int)atol(argv[4]);
-
-    lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200;
-    lBufferSizeUncpr = lBufferSizeCpr;
-
-    CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress);
-    UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress);
-
-    dwGetTick=GetTickCount();
-    {
-        z_stream zcpr;
-        int ret=Z_OK;
-        long lOrigToDo = lFileSize;
-        long lOrigDone = 0;
-        int step=0;
-        memset(&zcpr,0,sizeof(z_stream));
-        deflateInit(&zcpr,cprLevel);
-
-        zcpr.next_in = FilePtr;
-        zcpr.next_out = CprPtr;
-
-
-        do
-        {
-            long all_read_before = zcpr.total_in;
-            zcpr.avail_in = min(lOrigToDo,BlockSizeCompress);
-            zcpr.avail_out = BlockSizeCompress;
-            ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH);
-            lOrigDone += (zcpr.total_in-all_read_before);
-            lOrigToDo -= (zcpr.total_in-all_read_before);
-            step++;
-        } while (ret==Z_OK);
-
-        lSizeCpr=zcpr.total_out;
-        deflateEnd(&zcpr);
-        dwGetTick=GetTickCount()-dwGetTick;
-        printf("total compress size = %u, in %u step\n",lSizeCpr,step);
-        printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.);
-    }
-
-    dwGetTick=GetTickCount();
-    {
-        z_stream zcpr;
-        int ret=Z_OK;
-        long lOrigToDo = lSizeCpr;
-        long lOrigDone = 0;
-        int step=0;
-        memset(&zcpr,0,sizeof(z_stream));
-        inflateInit(&zcpr);
-
-        zcpr.next_in = CprPtr;
-        zcpr.next_out = UncprPtr;
-
-
-        do
-        {
-            long all_read_before = zcpr.total_in;
-            zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress);
-            zcpr.avail_out = BlockSizeUncompress;
-            ret=inflate(&zcpr,Z_SYNC_FLUSH);
-            lOrigDone += (zcpr.total_in-all_read_before);
-            lOrigToDo -= (zcpr.total_in-all_read_before);
-            step++;
-        } while (ret==Z_OK);
-
-        lSizeUncpr=zcpr.total_out;
-        inflateEnd(&zcpr);
-        dwGetTick=GetTickCount()-dwGetTick;
-        printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step);
-        printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.);
-    }
-
-    if (lSizeUncpr==lFileSize)
-    {
-        if (memcmp(FilePtr,UncprPtr,lFileSize)==0)
-            printf("compare ok\n");
-
-    }
-
-    return 0;
-
-}
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <windows.h>\r
+#include "zlib.h"\r
+\r
+\r
+void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B)\r
+{\r
+    R->HighPart = A.HighPart - B.HighPart;\r
+    if (A.LowPart >= B.LowPart)\r
+        R->LowPart = A.LowPart - B.LowPart;\r
+    else\r
+    {\r
+        R->LowPart = A.LowPart - B.LowPart;\r
+        R->HighPart --;\r
+    }\r
+}\r
+\r
+#ifdef _AMD64_\r
+unsigned _int64 myrdtsc();\r
+void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)\r
+{\r
+ //   printf("rdtsc = %I64x\n",myrdtsc());\r
+   pbeginTime64->QuadPart=myrdtsc();\r
+}\r
+\r
+LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)\r
+{\r
+    LARGE_INTEGER LIres;\r
+    unsigned _int64 res=myrdtsc()-((unsigned _int64)(beginTime64.QuadPart));\r
+    LIres.QuadPart=res;\r
+   // printf("rdtsc = %I64x\n",myrdtsc());\r
+    return LIres;\r
+}\r
+#else\r
+void myGetRDTSC32(LARGE_INTEGER * pbeginTime64)\r
+{\r
+    DWORD dwEdx,dwEax;\r
+    _asm\r
+    {\r
+        rdtsc\r
+        mov dwEax,eax\r
+        mov dwEdx,edx\r
+    }\r
+    pbeginTime64->LowPart=dwEax;\r
+    pbeginTime64->HighPart=dwEdx;\r
+}\r
+\r
+void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)\r
+{\r
+    myGetRDTSC32(pbeginTime64);\r
+}\r
+\r
+LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)\r
+{\r
+    LARGE_INTEGER LIres,endTime64;\r
+    myGetRDTSC32(&endTime64);\r
+\r
+    LIres.LowPart=LIres.HighPart=0;\r
+    MyDoMinus64(&LIres,endTime64,beginTime64);\r
+    return LIres;\r
+}\r
+#endif\r
+\r
+\r
+void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf)\r
+{\r
+    if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64)))\r
+    {\r
+        pbeginTime64->LowPart = GetTickCount();\r
+        pbeginTime64->HighPart = 0;\r
+    }\r
+}\r
+\r
+DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)\r
+{\r
+    LARGE_INTEGER endTime64,ticksPerSecond,ticks;\r
+    DWORDLONG ticksShifted,tickSecShifted;\r
+    DWORD dwLog=16+0;\r
+    DWORD dwRet;\r
+    if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64)))\r
+        dwRet = (GetTickCount() - beginTime64.LowPart)*1;\r
+    else\r
+    {\r
+        MyDoMinus64(&ticks,endTime64,beginTime64);\r
+        QueryPerformanceFrequency(&ticksPerSecond);\r
+\r
+    \r
+        {\r
+            ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog);\r
+            tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog);\r
+        \r
+        } \r
+\r
+        dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted));\r
+        dwRet *=1;\r
+    }\r
+    return dwRet;\r
+}\r
+\r
+int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)\r
+{\r
+    FILE* stream;\r
+    void* ptr;\r
+    int retVal=1;\r
+    stream=fopen(filename, "rb");\r
+    if (stream==NULL)\r
+        return 0;\r
+\r
+    fseek(stream,0,SEEK_END);\r
+\r
+    *plFileSize=ftell(stream);\r
+    fseek(stream,0,SEEK_SET);\r
+    ptr=malloc((*plFileSize)+1);\r
+    if (ptr==NULL)\r
+        retVal=0;\r
+    else\r
+    {\r
+        if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize))\r
+            retVal=0;\r
+    }\r
+    fclose(stream);\r
+    *pFilePtr=ptr;\r
+    return retVal;\r
+}\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+    int BlockSizeCompress=0x8000;\r
+    int BlockSizeUncompress=0x8000;\r
+    int cprLevel=Z_DEFAULT_COMPRESSION ;\r
+    long lFileSize;\r
+    unsigned char* FilePtr;\r
+    long lBufferSizeCpr;\r
+    long lBufferSizeUncpr;\r
+    long lCompressedSize=0;\r
+    unsigned char* CprPtr;\r
+    unsigned char* UncprPtr;\r
+    long lSizeCpr,lSizeUncpr;\r
+    DWORD dwGetTick,dwMsecQP;\r
+    LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc;\r
+\r
+    if (argc<=1)\r
+    {\r
+        printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n");\r
+        return 0;\r
+    }\r
+\r
+    if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0)\r
+    {\r
+        printf("error reading %s\n",argv[1]);\r
+        return 1;\r
+    }\r
+    else printf("file %s read, %u bytes\n",argv[1],lFileSize);\r
+\r
+    if (argc>=3)\r
+        BlockSizeCompress=atol(argv[2]);\r
+\r
+    if (argc>=4)\r
+        BlockSizeUncompress=atol(argv[3]);\r
+\r
+    if (argc>=5)\r
+        cprLevel=(int)atol(argv[4]);\r
+\r
+    lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200;\r
+    lBufferSizeUncpr = lBufferSizeCpr;\r
+\r
+    CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress);\r
+\r
+    BeginCountPerfCounter(&li_qp,TRUE);\r
+    dwGetTick=GetTickCount();\r
+    BeginCountRdtsc(&li_rdtsc);\r
+    {\r
+        z_stream zcpr;\r
+        int ret=Z_OK;\r
+        long lOrigToDo = lFileSize;\r
+        long lOrigDone = 0;\r
+        int step=0;\r
+        memset(&zcpr,0,sizeof(z_stream));\r
+        deflateInit(&zcpr,cprLevel);\r
+\r
+        zcpr.next_in = FilePtr;\r
+        zcpr.next_out = CprPtr;\r
+\r
+\r
+        do\r
+        {\r
+            long all_read_before = zcpr.total_in;\r
+            zcpr.avail_in = min(lOrigToDo,BlockSizeCompress);\r
+            zcpr.avail_out = BlockSizeCompress;\r
+            ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH);\r
+            lOrigDone += (zcpr.total_in-all_read_before);\r
+            lOrigToDo -= (zcpr.total_in-all_read_before);\r
+            step++;\r
+        } while (ret==Z_OK);\r
+\r
+        lSizeCpr=zcpr.total_out;\r
+        deflateEnd(&zcpr);\r
+        dwGetTick=GetTickCount()-dwGetTick;\r
+        dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE);\r
+        dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE);\r
+        printf("total compress size = %u, in %u step\n",lSizeCpr,step);\r
+        printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.);\r
+        printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.);\r
+        printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart);\r
+    }\r
+\r
+    CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr);\r
+    UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress);\r
+\r
+    BeginCountPerfCounter(&li_qp,TRUE);\r
+    dwGetTick=GetTickCount();\r
+    BeginCountRdtsc(&li_rdtsc);\r
+    {\r
+        z_stream zcpr;\r
+        int ret=Z_OK;\r
+        long lOrigToDo = lSizeCpr;\r
+        long lOrigDone = 0;\r
+        int step=0;\r
+        memset(&zcpr,0,sizeof(z_stream));\r
+        inflateInit(&zcpr);\r
+\r
+        zcpr.next_in = CprPtr;\r
+        zcpr.next_out = UncprPtr;\r
+\r
+\r
+        do\r
+        {\r
+            long all_read_before = zcpr.total_in;\r
+            zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress);\r
+            zcpr.avail_out = BlockSizeUncompress;\r
+            ret=inflate(&zcpr,Z_SYNC_FLUSH);\r
+            lOrigDone += (zcpr.total_in-all_read_before);\r
+            lOrigToDo -= (zcpr.total_in-all_read_before);\r
+            step++;\r
+        } while (ret==Z_OK);\r
+\r
+        lSizeUncpr=zcpr.total_out;\r
+        inflateEnd(&zcpr);\r
+        dwGetTick=GetTickCount()-dwGetTick;\r
+        dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE);\r
+        dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE);\r
+        printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step);\r
+        printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.);\r
+        printf("uncpr  time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.);\r
+        printf("uncpr  result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart);\r
+    }\r
+\r
+    if (lSizeUncpr==lFileSize)\r
+    {\r
+        if (memcmp(FilePtr,UncprPtr,lFileSize)==0)\r
+            printf("compare ok\n");\r
+\r
+    }\r
+\r
+    return 0;\r
+}\r
diff --git a/zlib/contrib/testzlib/testzlib.txt b/zlib/contrib/testzlib/testzlib.txt
new file mode 100644 (file)
index 0000000..62258f1
--- /dev/null
@@ -0,0 +1,10 @@
+To build testzLib with Visual Studio 2005:\r
+\r
+copy to a directory file from :\r
+- root of zLib tree\r
+- contrib/testzlib\r
+- contrib/masmx86\r
+- contrib/masmx64\r
+- contrib/vstudio/vc7\r
+\r
+and open testzlib8.sln
\ No newline at end of file
diff --git a/zlib/contrib/testzlib/testzlib8.sln b/zlib/contrib/testzlib/testzlib8.sln
new file mode 100644 (file)
index 0000000..794f72d
--- /dev/null
@@ -0,0 +1,32 @@
+\r
+Microsoft Visual Studio Solution File, Format Version 9.00\r
+# Visual Studio 2005\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib8", "testzlib8.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"\r
+EndProject\r
+Global\r
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+               Debug|Win32 = Debug|Win32\r
+               Debug|Win64 (AMD64) = Debug|Win64 (AMD64)\r
+               Release|Win32 = Release|Win32\r
+               Release|Win64 (AMD64) = Release|Win64 (AMD64)\r
+               ReleaseAsm|Win32 = ReleaseAsm|Win32\r
+               ReleaseAsm|Win64 (AMD64) = ReleaseAsm|Win64 (AMD64)\r
+       EndGlobalSection\r
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win64 (AMD64).ActiveCfg = Debug|Win64 (AMD64)\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win64 (AMD64).Build.0 = Debug|Win64 (AMD64)\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64)\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64)\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win32.ActiveCfg = ReleaseAsm|Win32\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win32.Build.0 = ReleaseAsm|Win32\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win64 (AMD64).ActiveCfg = ReleaseAsm|Win64 (AMD64)\r
+               {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win64 (AMD64).Build.0 = ReleaseAsm|Win64 (AMD64)\r
+       EndGlobalSection\r
+       GlobalSection(SolutionProperties) = preSolution\r
+               HideSolutionNode = FALSE\r
+       EndGlobalSection\r
+EndGlobal\r
diff --git a/zlib/contrib/testzlib/testzlib8.vcproj b/zlib/contrib/testzlib/testzlib8.vcproj
new file mode 100644 (file)
index 0000000..3cab776
--- /dev/null
@@ -0,0 +1,638 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="8,00"\r
+       Name="testzlib8"\r
+       ProjectGUID="{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"\r
+       Keyword="Win32Proj"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="Win64 (AMD64)"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+               <DefaultToolFile\r
+                       FileName="masm.tool"\r
+               />\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="x86\$(ConfigurationName)"\r
+                       IntermediateDirectory="x86\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="MASM"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               MinimalRebuild="TRUE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerOutput="4"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="TRUE"\r
+                               DebugInformationFormat="4"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="gvmat32.obj inffas32.obj"\r
+                               OutputFile="$(OutDir)/testzlib.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(OutDir)/testzlib.pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|Win64 (AMD64)"\r
+                       OutputDirectory="amd64\$(ConfigurationName)"\r
+                       IntermediateDirectory="amd64\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="MASM"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               MinimalRebuild="TRUE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="1"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerOutput="4"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="TRUE"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               CommandLine=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="gvmat64.obj inffasx64.obj rdtsc64.obj"\r
+                               OutputFile="$(OutDir)/testzlib.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(OutDir)/testzlib.pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="x86\$(ConfigurationName)"\r
+                       IntermediateDirectory="x86\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="MASM"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               OmitFramePointers="TRUE"\r
+                               PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="TRUE"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/testzlib.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="TRUE"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               OptimizeForWindows98="1"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win64 (AMD64)"\r
+                       OutputDirectory="amd64\$(ConfigurationName)"\r
+                       IntermediateDirectory="amd64\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="MASM"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               OmitFramePointers="TRUE"\r
+                               PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="TRUE"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="rdtsc64.obj"\r
+                               OutputFile="$(OutDir)/testzlib.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="TRUE"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               OptimizeForWindows98="1"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="ReleaseAsm|Win32"\r
+                       OutputDirectory="x86\$(ConfigurationName)"\r
+                       IntermediateDirectory="x86\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="MASM"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               OmitFramePointers="TRUE"\r
+                               PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="TRUE"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="gvmat32.obj inffas32.obj"\r
+                               OutputFile="$(OutDir)/testzlib.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="TRUE"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               OptimizeForWindows98="1"\r
+                               TargetMachine="1"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="ReleaseAsm|Win64 (AMD64)"\r
+                       OutputDirectory="amd64\$(ConfigurationName)"\r
+                       IntermediateDirectory="amd64\$(ConfigurationName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                               CommandLine=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="MASM"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               OmitFramePointers="TRUE"\r
+                               PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="0"\r
+                               AssemblerOutput="4"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="TRUE"\r
+                               DebugInformationFormat="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                               CommandLine=""\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="gvmat64.obj inffasx64.obj rdtsc64.obj"\r
+                               OutputFile="$(OutDir)/testzlib.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="TRUE"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               OptimizeForWindows98="1"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"\r
+                       >\r
+                       <File\r
+                               RelativePath=".\adler32.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\compress.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\crc32.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\deflate.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\gvmat32c.c"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win64 (AMD64)"\r
+                                       ExcludedFromBuild="TRUE"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win64 (AMD64)"\r
+                                       ExcludedFromBuild="TRUE"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="ReleaseAsm|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="ReleaseAsm|Win64 (AMD64)"\r
+                                       ExcludedFromBuild="TRUE"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\infback.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\inffas8664.c"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       ExcludedFromBuild="TRUE"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="ReleaseAsm|Win32"\r
+                                       ExcludedFromBuild="TRUE"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\inffast.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\inflate.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\inftrees.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="testzlib.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\trees.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\uncompr.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath=".\zutil.c"\r
+                               >\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc"\r
+                       >\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+                       >\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
index 5b2f856..ebb3262 100644 (file)
Binary files a/zlib/contrib/vstudio/vc7/gvmat32.obj and b/zlib/contrib/vstudio/vc7/gvmat32.obj differ
index a541a5a..bd6664d 100644 (file)
Binary files a/zlib/contrib/vstudio/vc7/inffas32.obj and b/zlib/contrib/vstudio/vc7/inffas32.obj differ
index 3ebe25b..e9d748f 100644 (file)
@@ -2,8 +2,8 @@
 \r
 #define IDR_VERSION1  1\r
 IDR_VERSION1   VERSIONINFO     MOVEABLE IMPURE LOADONCALL DISCARDABLE\r
-  FILEVERSION   1,2,2\r
-  PRODUCTVERSION 1,2,2\r
+  FILEVERSION   1,2,2,4\r
+  PRODUCTVERSION 1,2,2,4\r
   FILEFLAGSMASK        VS_FFI_FILEFLAGSMASK\r
   FILEFLAGS    0\r
   FILEOS       VOS_DOS_WINDOWS32\r
@@ -17,7 +17,7 @@ BEGIN
 \r
     BEGIN\r
       VALUE "FileDescription", "zlib data compression library\0"\r
-      VALUE "FileVersion",     "1.2.2\0"\r
+      VALUE "FileVersion",     "1.2.2.4\0"\r
       VALUE "InternalName",    "zlib\0"\r
       VALUE "OriginalFilename",        "zlib.dll\0"\r
       VALUE "ProductName",     "ZLib.DLL\0"\r
index d8be051..06724e0 100644 (file)
@@ -1,12 +1,12 @@
 /* crc32.c -- compute the CRC-32 of a data stream
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2005 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  *
  * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
  * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
  * tables for updating the shift register in one step with three exclusive-ors
- * instead of four steps with four exclusive-ors.  This results about a factor
- * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ * instead of four steps with four exclusive-ors.  This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
  */
 
 /* @(#) $Id$ */
 #  define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
                 (((w)&0xff00)<<8)+(((w)&0xff)<<24))
    local unsigned long crc32_little OF((unsigned long,
-                        const unsigned char FAR *, unsigned));
+                        const unsigned char FAR *, unsigned))
+       /*@*/;
    local unsigned long crc32_big OF((unsigned long,
-                        const unsigned char FAR *, unsigned));
+                        const unsigned char FAR *, unsigned))
+       /*@*/;
 #  define TBLS 8
 #else
 #  define TBLS 1
 #endif /* BYFOUR */
 
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+                                         unsigned long vec))
+       /*@*/;
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat))
+       /*@modifies *square @*/;
+
 #ifdef DYNAMIC_CRC_TABLE
 
 local volatile int crc_table_empty = 1;
 local unsigned long FAR crc_table[TBLS][256];
-local void make_crc_table OF((void));
+local void make_crc_table OF((void))
+       /*@*/;
 #ifdef MAKECRCH
-   local void write_table OF((FILE *, const unsigned long FAR *));
+   local void write_table OF((FILE *, const unsigned long FAR *))
+       /*@*/;
 #endif /* MAKECRCH */
-
 /*
   Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
   x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
@@ -99,7 +109,7 @@ local void make_crc_table OF((void));
   allow for word-at-a-time CRC calculation for both big-endian and little-
   endian machines, where a word is four bytes.
 */
-local void make_crc_table()
+local void make_crc_table(void)
 {
     unsigned long c;
     int n, k;
@@ -176,9 +186,7 @@ local void make_crc_table()
 }
 
 #ifdef MAKECRCH
-local void write_table(out, table)
-    FILE *out;
-    const unsigned long FAR *table;
+local void write_table(FILE *out, const unsigned long FAR *table)
 {
     int n;
 
@@ -252,10 +260,7 @@ unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uns
 #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
 
 /* ========================================================================= */
-local unsigned long crc32_little(crc, buf, len)
-    unsigned long crc;
-    const unsigned char FAR *buf;
-    unsigned len;
+local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf, unsigned len)
 {
     register u4 c;
     register const u4 FAR *buf4;
@@ -267,7 +272,7 @@ local unsigned long crc32_little(crc, buf, len)
         len--;
     }
 
-    buf4 = (const u4 FAR *)buf;
+    buf4 = (const u4 FAR *)(const void FAR *)buf;
     while (len >= 32) {
         DOLIT32;
         len -= 32;
@@ -292,10 +297,7 @@ local unsigned long crc32_little(crc, buf, len)
 #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
 
 /* ========================================================================= */
-local unsigned long crc32_big(crc, buf, len)
-    unsigned long crc;
-    const unsigned char FAR *buf;
-    unsigned len;
+local unsigned long crc32_big(unsigned long crc, const unsigned char FAR *buf, unsigned len)
 {
     register u4 c;
     register const u4 FAR *buf4;
@@ -307,7 +309,7 @@ local unsigned long crc32_big(crc, buf, len)
         len--;
     }
 
-    buf4 = (const u4 FAR *)buf;
+    buf4 = (const u4 FAR *)(const void FAR *)buf;
     buf4--;
     while (len >= 32) {
         DOBIG32;
@@ -328,3 +330,82 @@ local unsigned long crc32_big(crc, buf, len)
 }
 
 #endif /* BYFOUR */
+
+#define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times(unsigned long *mat, unsigned long vec)
+{
+    unsigned long sum;
+
+    sum = 0;
+    while (vec) {
+        if (vec & 1)
+            sum ^= *mat;
+        vec >>= 1;
+        mat++;
+    }
+    return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square(unsigned long *square, unsigned long *mat)
+{
+    int n;
+
+    for (n = 0; n < GF2_DIM; n++)
+        square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2)
+{
+    int n;
+    unsigned long row;
+    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
+    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
+
+    /* degenerate case */
+    if (len2 == 0)
+        return crc1;
+
+    /* put operator for one zero bit in odd */
+    odd[0] = 0xedb88320L;           /* CRC-32 polynomial */
+    row = 1;
+    for (n = 1; n < GF2_DIM; n++) {
+        odd[n] = row;
+        row <<= 1;
+    }
+
+    /* put operator for two zero bits in even */
+    gf2_matrix_square(even, odd);
+
+    /* put operator for four zero bits in odd */
+    gf2_matrix_square(odd, even);
+
+    /* apply len2 zeros to crc1 (first square will put the operator for one
+       zero byte, eight zero bits, in even) */
+    do {
+        /* apply zeros operator for this bit of len2 */
+        gf2_matrix_square(even, odd);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(even, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+        if (len2 == 0)
+            break;
+
+        /* another iteration of the loop with odd and even swapped */
+        gf2_matrix_square(odd, even);
+        if (len2 & 1)
+            crc1 = gf2_matrix_times(odd, crc1);
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+    } while (len2 != 0);
+
+    /* return combined crc */
+    crc1 ^= crc2;
+    return crc1;
+}
index 50aa0ab..60f0c8f 100644 (file)
@@ -1,5 +1,5 @@
 /* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2004 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -53,7 +53,7 @@
 #include "deflate.h"
 
 const char deflate_copyright[] =
-   " deflate 1.2.2.f-rpm-rsync Copyright 1995-2004 Jean-loup Gailly ";
+   " deflate 1.2.2.f-rpm-rsync Copyright 1995-2005 Jean-loup Gailly ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -139,6 +139,7 @@ local  void check_match OF((deflate_state *s, IPos start, IPos match,
 /* Whether window sum matches magic value */
 
 /* Global rsync mode control variable */
+/*@unchecked@*/
 int zlib_rsync = 1;
 
 /* Values for max_lazy_match, good_match and max_chain_length, depending on
@@ -346,9 +347,7 @@ int ZEXPORT deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt
     if (length < MIN_MATCH) return Z_OK;
     if (length > MAX_DIST(s)) {
         length = MAX_DIST(s);
-#ifndef USE_DICT_HEAD
         dictionary += dictLength - length; /* use the tail of the dictionary */
-#endif
     }
     zmemcpy(s->window, dictionary, length);
     s->strstart = length;
@@ -455,6 +454,20 @@ int ZEXPORT deflateParams(z_streamp strm, int level, int strategy)
     return err;
 }
 
+/* ========================================================================= */
+int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain)
+{
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+    s->good_match = good_length;
+    s->max_lazy_match = max_lazy;
+    s->nice_match = nice_length;
+    s->max_chain_length = max_chain;
+    return Z_OK;
+}
+
 /* =========================================================================
  * For the default windowBits of 15 and memLevel of 8, this function returns
  * a close to exact, as well as small, upper bound on the compressed size.
@@ -579,10 +592,10 @@ int ZEXPORT deflate (z_streamp strm, int flush)
                             (s->gzhead->name == Z_NULL ? 0 : 8) +
                             (s->gzhead->comment == Z_NULL ? 0 : 16)
                         );
-                put_byte(s, s->gzhead->time & 0xff);
-                put_byte(s, (s->gzhead->time >> 8) & 0xff);
-                put_byte(s, (s->gzhead->time >> 16) & 0xff);
-                put_byte(s, (s->gzhead->time >> 24) & 0xff);
+                put_byte(s, (Byte)(s->gzhead->time & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
                 put_byte(s, s->level == 9 ? 2 :
                             (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
                              4 : 0));
@@ -630,7 +643,7 @@ int ZEXPORT deflate (z_streamp strm, int flush)
 #ifdef GZIP
     if (s->status == EXTRA_STATE) {
         if (s->gzhead->extra != NULL) {
-            int beg = s->pending;   /* start of bytes to update crc */
+            uInt beg = s->pending;  /* start of bytes to update crc */
 
             while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
                 if (s->pending == s->pending_buf_size) {
@@ -658,7 +671,7 @@ int ZEXPORT deflate (z_streamp strm, int flush)
     }
     if (s->status == NAME_STATE) {
         if (s->gzhead->name != NULL) {
-            int beg = s->pending;   /* start of bytes to update crc */
+            uInt beg = s->pending;  /* start of bytes to update crc */
             int val;
 
             do {
@@ -689,7 +702,7 @@ int ZEXPORT deflate (z_streamp strm, int flush)
     }
     if (s->status == COMMENT_STATE) {
         if (s->gzhead->comment != NULL) {
-            int beg = s->pending;   /* start of bytes to update crc */
+            uInt beg = s->pending;  /* start of bytes to update crc */
             int val;
 
             do {
@@ -721,8 +734,8 @@ int ZEXPORT deflate (z_streamp strm, int flush)
             if (s->pending + 2 > s->pending_buf_size)
                 flush_pending(strm);
             if (s->pending + 2 <= s->pending_buf_size) {
-                put_byte(s, strm->adler & 0xff);
-                put_byte(s, (strm->adler >> 8) & 0xff);
+                put_byte(s, (Byte)(strm->adler & 0xff));
+                put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
                 strm->adler = crc32(0L, Z_NULL, 0);
                 s->status = BUSY_STATE;
             }
@@ -975,9 +988,11 @@ local void lm_init (deflate_state *s)
     s->match_length = s->prev_length = MIN_MATCH-1;
     s->match_available = 0;
     s->ins_h = 0;
+#ifndef FASTEST
 #ifdef ASMV
     match_init(); /* initialize the asm code */
 #endif
+#endif
 
     /* rsync params */
     s->rsync_chunk_end = 0xFFFFFFFFUL;
@@ -1271,6 +1286,7 @@ local void fill_window(deflate_state *s)
                later. (Using level 0 permanently is not an optimal usage of
                zlib, so we don't care about this pathological case.)
              */
+            /* %%% avoid this when Z_RLE */
             n = s->hash_size;
             p = &s->head[n];
             do {
@@ -1325,6 +1341,7 @@ local void fill_window(deflate_state *s)
 }
 
 local void rsync_roll(deflate_state *s, unsigned start, unsigned num)
+       /*@modifies *s @*/
 {
     unsigned i;
 
@@ -1690,3 +1707,64 @@ local block_state deflate_slow(deflate_state *s, int flush)
     return flush == Z_FINISH ? finish_done : block_done;
 }
 #endif /* FASTEST */
+
+#if 0
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one.  Do not maintain a hash table.  (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    int bflush;         /* set if current block must be flushed */
+    uInt run;           /* length of run */
+    uInt max;           /* maximum length of run */
+    uInt prev;          /* byte at distance one to match */
+    Bytef *scan;        /* scan for end of run */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the longest encodable run.
+         */
+        if (s->lookahead < MAX_MATCH) {
+            fill_window(s);
+            if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* See how many times the previous byte repeats */
+        run = 0;
+        if (s->strstart > 0) {      /* if there is a previous byte, that is */
+            max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
+            scan = s->window + s->strstart - 1;
+            prev = *scan++;
+            do {
+                if (*scan++ != prev)
+                    break;
+            } while (++run < max);
+        }
+
+        /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+        if (run >= MIN_MATCH) {
+            check_match(s, s->strstart, s->strstart - 1, run);
+            _tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
+            s->lookahead -= run;
+            s->strstart += run;
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif
index 3f47378..cb93e59 100644 (file)
@@ -1,5 +1,5 @@
 /* deflate.h -- internal compression state
- * Copyright (C) 1995-2002 Jean-loup Gailly
+ * Copyright (C) 1995-2004 Jean-loup Gailly
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /* All codes must not exceed MAX_BITS bits */
 
 #define INIT_STATE    42
+#define EXTRA_STATE   69
+#define NAME_STATE    73
+#define COMMENT_STATE 91
+#define HCRC_STATE   103
 #define BUSY_STATE   113
 #define FINISH_STATE 666
 /* Stream status */
@@ -97,8 +101,10 @@ typedef struct internal_state {
     ulg   pending_buf_size; /* size of pending_buf */
 /*@dependent@*/
     Bytef *pending_out;  /* next pending byte to output to the stream */
-    int   pending;       /* nb of bytes in the pending buffer */
+    uInt   pending;      /* nb of bytes in the pending buffer */
     int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
+    gz_headerp  gzhead;  /* gzip header information to write */
+    uInt   gzindex;      /* where in extra, name, or comment */
     Byte  method;        /* STORED (for zip only) or DEFLATED */
     int   last_flush;    /* value of flush param for previous deflate call */
 
@@ -259,6 +265,9 @@ typedef struct internal_state {
      * are always zero.
      */
 
+    ulg rsync_sum;      /* rolling sum of rsync window */
+    ulg rsync_chunk_end; /* next rsync sequence point */
+
 } FAR deflate_state;
 
 /* Output a byte on the stream.
@@ -283,7 +292,7 @@ void _tr_init         OF((deflate_state *s))
 int  _tr_tally        OF((deflate_state *s, unsigned dist, unsigned lc))
        /*@modifies s @*/;
 void _tr_flush_block  OF((deflate_state *s, charf *buf, ulg stored_len,
-                          int eof))
+                          int pad, int eof))
        /*@modifies s @*/;
 void _tr_align        OF((deflate_state *s))
        /*@modifies s @*/;
diff --git a/zlib/examples/README.examples b/zlib/examples/README.examples
new file mode 100644 (file)
index 0000000..5632d7a
--- /dev/null
@@ -0,0 +1,42 @@
+This directory contains examples of the use of zlib.
+
+fitblk.c
+    compress just enough input to nearly fill a requested output size
+    - zlib isn't designed to do this, but fitblk does it anyway
+
+gun.c
+    uncompress a gzip file
+    - illustrates the use of inflateBack() for high speed file-to-file
+      decompression using call-back functions
+    - is approximately twice as fast as gzip -d
+    - also provides Unix uncompress functionality, again twice as fast
+
+gzappend.c
+    append to a gzip file
+    - illustrates the use of the Z_BLOCK flush parameter for inflate()
+    - illustrates the use of deflatePrime() to start at any bit
+
+gzjoin.c
+    join gzip files without recalculating the crc or recompressing
+    - illustrates the use of the Z_BLOCK flush parameter for inflate()
+    - illustrates the use of crc32_combine()
+
+gzlog.c
+gzlog.h
+    efficiently maintain a message log file in gzip format
+    - illustrates use of raw deflate and Z_SYNC_FLUSH
+    - illustrates use of gzip header extra field
+
+zlib_how.html
+    painfully comprehensive description of zpipe.c (see below)
+    - describes in excruciating detail the use of deflate() and inflate()
+
+zpipe.c
+    reads and writes zlib streams from stdin to stdout
+    - illustrates the proper use of deflate() and inflate()
+    - deeply commented in zlib_how.html (see above)
+
+zran.c
+    index a zlib or gzip stream and randomly access it
+    - illustrates the use of Z_BLOCK, inflatePrime(), and
+      inflateSetDictionary() to provide random access
diff --git a/zlib/examples/fitblk.c b/zlib/examples/fitblk.c
new file mode 100644 (file)
index 0000000..c61de5c
--- /dev/null
@@ -0,0 +1,233 @@
+/* fitblk.c: example of fitting compressed output to a specified size
+   Not copyrighted -- provided to the public domain
+   Version 1.1  25 November 2004  Mark Adler */
+
+/* Version history:
+   1.0  24 Nov 2004  First version
+   1.1  25 Nov 2004  Change deflateInit2() to deflateInit()
+                     Use fixed-size, stack-allocated raw buffers
+                     Simplify code moving compression to subroutines
+                     Use assert() for internal errors
+                     Add detailed description of approach
+ */
+
+/* Approach to just fitting a requested compressed size:
+
+   fitblk performs three compression passes on a portion of the input
+   data in order to determine how much of that input will compress to
+   nearly the requested output block size.  The first pass generates
+   enough deflate blocks to produce output to fill the requested
+   output size plus a specfied excess amount (see the EXCESS define
+   below).  The last deflate block may go quite a bit past that, but
+   is discarded.  The second pass decompresses and recompresses just
+   the compressed data that fit in the requested plus excess sized
+   buffer.  The deflate process is terminated after that amount of
+   input, which is less than the amount consumed on the first pass.
+   The last deflate block of the result will be of a comparable size
+   to the final product, so that the header for that deflate block and
+   the compression ratio for that block will be about the same as in
+   the final product.  The third compression pass decompresses the
+   result of the second step, but only the compressed data up to the
+   requested size minus an amount to allow the compressed stream to
+   complete (see the MARGIN define below).  That will result in a
+   final compressed stream whose length is less than or equal to the
+   requested size.  Assuming sufficient input and a requested size
+   greater than a few hundred bytes, the shortfall will typically be
+   less than ten bytes.
+
+   If the input is short enough that the first compression completes
+   before filling the requested output size, then that compressed
+   stream is return with no recompression.
+
+   EXCESS is chosen to be just greater than the shortfall seen in a
+   two pass approach similar to the above.  That shortfall is due to
+   the last deflate block compressing more efficiently with a smaller
+   header on the second pass.  EXCESS is set to be large enough so
+   that there is enough uncompressed data for the second pass to fill
+   out the requested size, and small enough so that the final deflate
+   block of the second pass will be close in size to the final deflate
+   block of the third and final pass.  MARGIN is chosen to be just
+   large enough to assure that the final compression has enough room
+   to complete in all cases.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "zlib.h"
+
+#define local static
+
+/* print nastygram and leave */
+local void quit(char *why)
+{
+    fprintf(stderr, "fitblk abort: %s\n", why);
+    exit(1);
+}
+
+#define RAWLEN 4096    /* intermediate uncompressed buffer size */
+
+/* compress from file to def until provided buffer is full or end of
+   input reached; return last deflate() return value, or Z_ERRNO if
+   there was read error on the file */
+local int partcompress(FILE *in, z_streamp def)
+{
+    int ret, flush;
+    unsigned char raw[RAWLEN];
+
+    flush = Z_NO_FLUSH;
+    do {
+        def->avail_in = fread(raw, 1, RAWLEN, in);
+        if (ferror(in))
+            return Z_ERRNO;
+        def->next_in = raw;
+        if (feof(in))
+            flush = Z_FINISH;
+        ret = deflate(def, flush);
+        assert(ret != Z_STREAM_ERROR);
+    } while (def->avail_out != 0 && flush == Z_NO_FLUSH);
+    return ret;
+}
+
+/* recompress from inf's input to def's output; the input for inf and
+   the output for def are set in those structures before calling;
+   return last deflate() return value, or Z_MEM_ERROR if inflate()
+   was not able to allocate enough memory when it needed to */
+local int recompress(z_streamp inf, z_streamp def)
+{
+    int ret, flush;
+    unsigned char raw[RAWLEN];
+
+    flush = Z_NO_FLUSH;
+    do {
+        /* decompress */
+        inf->avail_out = RAWLEN;
+        inf->next_out = raw;
+        ret = inflate(inf, Z_NO_FLUSH);
+        assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR &&
+               ret != Z_NEED_DICT);
+        if (ret == Z_MEM_ERROR)
+            return ret;
+
+        /* compress what was decompresed until done or no room */
+        def->avail_in = RAWLEN - inf->avail_out;
+        def->next_in = raw;
+        if (inf->avail_out != 0)
+            flush = Z_FINISH;
+        ret = deflate(def, flush);
+        assert(ret != Z_STREAM_ERROR);
+    } while (ret != Z_STREAM_END && def->avail_out != 0);
+    return ret;
+}
+
+#define EXCESS 256      /* empirically determined stream overage */
+#define MARGIN 8        /* amount to back off for completion */
+
+/* compress from stdin to fixed-size block on stdout */
+int main(int argc, char **argv)
+{
+    int ret;                /* return code */
+    unsigned size;          /* requested fixed output block size */
+    unsigned have;          /* bytes written by deflate() call */
+    unsigned char *blk;     /* intermediate and final stream */
+    unsigned char *tmp;     /* close to desired size stream */
+    z_stream def, inf;      /* zlib deflate and inflate states */
+
+    /* get requested output size */
+    if (argc != 2)
+        quit("need one argument: size of output block");
+    ret = strtol(argv[1], argv + 1, 10);
+    if (argv[1][0] != 0)
+        quit("argument must be a number");
+    if (ret < 8)            /* 8 is minimum zlib stream size */
+        quit("need positive size of 8 or greater");
+    size = (unsigned)ret;
+
+    /* allocate memory for buffers and compression engine */
+    blk = malloc(size + EXCESS);
+    def.zalloc = Z_NULL;
+    def.zfree = Z_NULL;
+    def.opaque = Z_NULL;
+    ret = deflateInit(&def, Z_DEFAULT_COMPRESSION);
+    if (ret != Z_OK || blk == NULL)
+        quit("out of memory");
+
+    /* compress from stdin until output full, or no more input */
+    def.avail_out = size + EXCESS;
+    def.next_out = blk;
+    ret = partcompress(stdin, &def);
+    if (ret == Z_ERRNO)
+        quit("error reading input");
+
+    /* if it all fit, then size was undersubscribed -- done! */
+    if (ret == Z_STREAM_END && def.avail_out >= EXCESS) {
+        /* write block to stdout */
+        have = size + EXCESS - def.avail_out;
+        if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))
+            quit("error writing output");
+
+        /* clean up and print results to stderr */
+        ret = deflateEnd(&def);
+        assert(ret != Z_STREAM_ERROR);
+        free(blk);
+        fprintf(stderr,
+                "%u bytes unused out of %u requested (all input)\n",
+                size - have, size);
+        return 0;
+    }
+
+    /* it didn't all fit -- set up for recompression */
+    inf.zalloc = Z_NULL;
+    inf.zfree = Z_NULL;
+    inf.opaque = Z_NULL;
+    inf.avail_in = 0;
+    inf.next_in = Z_NULL;
+    ret = inflateInit(&inf);
+    tmp = malloc(size + EXCESS);
+    if (ret != Z_OK || tmp == NULL)
+        quit("out of memory");
+    ret = deflateReset(&def);
+    assert(ret != Z_STREAM_ERROR);
+
+    /* do first recompression close to the right amount */
+    inf.avail_in = size + EXCESS;
+    inf.next_in = blk;
+    def.avail_out = size + EXCESS;
+    def.next_out = tmp;
+    ret = recompress(&inf, &def);
+    if (ret == Z_MEM_ERROR)
+        quit("out of memory");
+
+    /* set up for next reocmpression */
+    ret = inflateReset(&inf);
+    assert(ret != Z_STREAM_ERROR);
+    ret = deflateReset(&def);
+    assert(ret != Z_STREAM_ERROR);
+
+    /* do second and final recompression (third compression) */
+    inf.avail_in = size - MARGIN;   /* assure stream will complete */
+    inf.next_in = tmp;
+    def.avail_out = size;
+    def.next_out = blk;
+    ret = recompress(&inf, &def);
+    if (ret == Z_MEM_ERROR)
+        quit("out of memory");
+    assert(ret == Z_STREAM_END);    /* otherwise MARGIN too small */
+
+    /* done -- write block to stdout */
+    have = size - def.avail_out;
+    if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))
+        quit("error writing output");
+
+    /* clean up and print results to stderr */
+    free(tmp);
+    ret = inflateEnd(&inf);
+    assert(ret != Z_STREAM_ERROR);
+    ret = deflateEnd(&def);
+    assert(ret != Z_STREAM_ERROR);
+    free(blk);
+    fprintf(stderr,
+            "%u bytes unused out of %u requested (%lu input)\n",
+            size - have, size, def.total_in);
+    return 0;
+}
diff --git a/zlib/examples/gun.c b/zlib/examples/gun.c
new file mode 100644 (file)
index 0000000..bfec590
--- /dev/null
@@ -0,0 +1,693 @@
+/* gun.c -- simple gunzip to give an example of the use of inflateBack()
+ * Copyright (C) 2003, 2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+   Version 1.3  12 June 2005  Mark Adler */
+
+/* Version history:
+   1.0  16 Feb 2003  First version for testing of inflateBack()
+   1.1  21 Feb 2005  Decompress concatenated gzip streams
+                     Remove use of "this" variable (C++ keyword)
+                     Fix return value for in()
+                     Improve allocation failure checking
+                     Add typecasting for void * structures
+                     Add -h option for command version and usage
+                     Add a bunch of comments
+   1.2  20 Mar 2005  Add Unix compress (LZW) decompression
+                     Copy file attributes from input file to output file
+   1.3  12 Jun 2005  Add casts for error messages [Oberhumer]
+ */
+
+/*
+   gun [ -t ] [ name ... ]
+
+   decompresses the data in the named gzip files.  If no arguments are given,
+   gun will decompress from stdin to stdout.  The names must end in .gz, -gz,
+   .z, -z, _z, or .Z.  The uncompressed data will be written to a file name
+   with the suffix stripped.  On success, the original file is deleted.  On
+   failure, the output file is deleted.  For most failures, the command will
+   continue to process the remaining names on the command line.  A memory
+   allocation failure will abort the command.  If -t is specified, then the
+   listed files or stdin will be tested as gzip files for integrity (without
+   checking for a proper suffix), no output will be written, and no files
+   will be deleted.
+
+   Like gzip, gun allows concatenated gzip streams and will decompress them,
+   writing all of the uncompressed data to the output.  Unlike gzip, gun allows
+   an empty file on input, and will produce no error writing an empty output
+   file.
+
+   gun will also decompress files made by Unix compress, which uses LZW
+   compression.  These files are automatically detected by virtue of their
+   magic header bytes.  Since the end of Unix compress stream is marked by the
+   end-of-file, they cannot be concantenated.  If a Unix compress stream is
+   encountered in an input file, it is the last stream in that file.
+
+   Like gunzip and uncompress, the file attributes of the orignal compressed
+   file are maintained in the final uncompressed file, to the extent that the
+   user permissions allow it.
+
+   On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version
+   1.2.4) is on the same file, when gun is linked with zlib 1.2.2.  Also the
+   LZW decompression provided by gun is about twice as fast as the standard
+   Unix uncompress command.
+ */
+
+/* external functions and related types and constants */
+#include <stdio.h>          /* fprintf() */
+#include <stdlib.h>         /* malloc(), free() */
+#include <string.h>         /* strerror(), strcmp(), strlen(), memcpy() */
+#include <errno.h>          /* errno */
+#include <fcntl.h>          /* open() */
+#include <unistd.h>         /* read(), write(), close(), chown(), unlink() */
+#include <sys/types.h>
+#include <sys/stat.h>       /* stat(), chmod() */
+#include <utime.h>          /* utime() */
+#include "zlib.h"           /* inflateBackInit(), inflateBack(), */
+                            /* inflateBackEnd(), crc32() */
+
+/* function declaration */
+#define local static
+
+/* buffer constants */
+#define SIZE 32768U         /* input and output buffer sizes */
+#define PIECE 16384         /* limits i/o chunks for 16-bit int case */
+
+/* structure for infback() to pass to input function in() -- it maintains the
+   input file and a buffer of size SIZE */
+struct ind {
+    int infile;
+    unsigned char *inbuf;
+};
+
+/* Load input buffer, assumed to be empty, and return bytes loaded and a
+   pointer to them.  read() is called until the buffer is full, or until it
+   returns end-of-file or error.  Return 0 on error. */
+local unsigned in(void *in_desc, unsigned char **buf)
+{
+    int ret;
+    unsigned len;
+    unsigned char *next;
+    struct ind *me = (struct ind *)in_desc;
+
+    next = me->inbuf;
+    *buf = next;
+    len = 0;
+    do {
+        ret = PIECE;
+        if ((unsigned)ret > SIZE - len)
+            ret = (int)(SIZE - len);
+        ret = (int)read(me->infile, next, ret);
+        if (ret == -1) {
+            len = 0;
+            break;
+        }
+        next += ret;
+        len += ret;
+    } while (ret != 0 && len < SIZE);
+    return len;
+}
+
+/* structure for infback() to pass to output function out() -- it maintains the
+   output file, a running CRC-32 check on the output and the total number of
+   bytes output, both for checking against the gzip trailer.  (The length in
+   the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and
+   the output is greater than 4 GB.) */
+struct outd {
+    int outfile;
+    int check;                  /* true if checking crc and total */
+    unsigned long crc;
+    unsigned long total;
+};
+
+/* Write output buffer and update the CRC-32 and total bytes written.  write()
+   is called until all of the output is written or an error is encountered.
+   On success out() returns 0.  For a write failure, out() returns 1.  If the
+   output file descriptor is -1, then nothing is written.
+ */
+local int out(void *out_desc, unsigned char *buf, unsigned len)
+{
+    int ret;
+    struct outd *me = (struct outd *)out_desc;
+
+    if (me->check) {
+        me->crc = crc32(me->crc, buf, len);
+        me->total += len;
+    }
+    if (me->outfile != -1)
+        do {
+            ret = PIECE;
+            if ((unsigned)ret > len)
+                ret = (int)len;
+            ret = (int)write(me->outfile, buf, ret);
+            if (ret == -1)
+                return 1;
+            buf += ret;
+            len -= ret;
+        } while (len != 0);
+    return 0;
+}
+
+/* next input byte macro for use inside lunpipe() and gunpipe() */
+#define NEXT() (have ? 0 : (have = in(indp, &next)), \
+                last = have ? (have--, (int)(*next++)) : -1)
+
+/* memory for gunpipe() and lunpipe() --
+   the first 256 entries of prefix[] and suffix[] are never used, could
+   have offset the index, but it's faster to waste the memory */
+unsigned char inbuf[SIZE];              /* input buffer */
+unsigned char outbuf[SIZE];             /* output buffer */
+unsigned short prefix[65536];           /* index to LZW prefix string */
+unsigned char suffix[65536];            /* one-character LZW suffix */
+unsigned char match[65280 + 2];         /* buffer for reversed match or gzip
+                                           32K sliding window */
+
+/* throw out what's left in the current bits byte buffer (this is a vestigial
+   aspect of the compressed data format derived from an implementation that
+   made use of a special VAX machine instruction!) */
+#define FLUSHCODE() \
+    do { \
+        left = 0; \
+        rem = 0; \
+        if (chunk > have) { \
+            chunk -= have; \
+            have = 0; \
+            if (NEXT() == -1) \
+                break; \
+            chunk--; \
+            if (chunk > have) { \
+                chunk = have = 0; \
+                break; \
+            } \
+        } \
+        have -= chunk; \
+        next += chunk; \
+        chunk = 0; \
+    } while (0)
+
+/* Decompress a compress (LZW) file from indp to outfile.  The compress magic
+   header (two bytes) has already been read and verified.  There are have bytes
+   of buffered input at next.  strm is used for passing error information back
+   to gunpipe().
+
+   lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of
+   file, read error, or write error (a write error indicated by strm->next_in
+   not equal to Z_NULL), or Z_DATA_ERROR for invalid input.
+ */
+local int lunpipe(unsigned have, unsigned char *next, struct ind *indp,
+                  int outfile, z_stream *strm)
+{
+    int last;                   /* last byte read by NEXT(), or -1 if EOF */
+    int chunk;                  /* bytes left in current chunk */
+    int left;                   /* bits left in rem */
+    unsigned rem;               /* unused bits from input */
+    int bits;                   /* current bits per code */
+    unsigned code;              /* code, table traversal index */
+    unsigned mask;              /* mask for current bits codes */
+    int max;                    /* maximum bits per code for this stream */
+    int flags;                  /* compress flags, then block compress flag */
+    unsigned end;               /* last valid entry in prefix/suffix tables */
+    unsigned temp;              /* current code */
+    unsigned prev;              /* previous code */
+    unsigned final;             /* last character written for previous code */
+    unsigned stack;             /* next position for reversed string */
+    unsigned outcnt;            /* bytes in output buffer */
+    struct outd outd;           /* output structure */
+
+    /* set up output */
+    outd.outfile = outfile;
+    outd.check = 0;
+
+    /* process remainder of compress header -- a flags byte */
+    flags = NEXT();
+    if (last == -1)
+        return Z_BUF_ERROR;
+    if (flags & 0x60) {
+        strm->msg = (char *)"unknown lzw flags set";
+        return Z_DATA_ERROR;
+    }
+    max = flags & 0x1f;
+    if (max < 9 || max > 16) {
+        strm->msg = (char *)"lzw bits out of range";
+        return Z_DATA_ERROR;
+    }
+    if (max == 9)                           /* 9 doesn't really mean 9 */
+        max = 10;
+    flags &= 0x80;                          /* true if block compress */
+
+    /* clear table */
+    bits = 9;
+    mask = 0x1ff;
+    end = flags ? 256 : 255;
+
+    /* set up: get first 9-bit code, which is the first decompressed byte, but
+       don't create a table entry until the next code */
+    if (NEXT() == -1)                       /* no compressed data is ok */
+        return Z_OK;
+    final = prev = (unsigned)last;          /* low 8 bits of code */
+    if (NEXT() == -1)                       /* missing a bit */
+        return Z_BUF_ERROR;
+    if (last & 1) {                         /* code must be < 256 */
+        strm->msg = (char *)"invalid lzw code";
+        return Z_DATA_ERROR;
+    }
+    rem = (unsigned)last >> 1;              /* remaining 7 bits */
+    left = 7;
+    chunk = bits - 2;                       /* 7 bytes left in this chunk */
+    outbuf[0] = (unsigned char)final;       /* write first decompressed byte */
+    outcnt = 1;
+
+    /* decode codes */
+    stack = 0;
+    for (;;) {
+        /* if the table will be full after this, increment the code size */
+        if (end >= mask && bits < max) {
+            FLUSHCODE();
+            bits++;
+            mask <<= 1;
+            mask++;
+        }
+
+        /* get a code of length bits */
+        if (chunk == 0)                     /* decrement chunk modulo bits */
+            chunk = bits;
+        code = rem;                         /* low bits of code */
+        if (NEXT() == -1) {                 /* EOF is end of compressed data */
+            /* write remaining buffered output */
+            if (outcnt && out(&outd, outbuf, outcnt)) {
+                strm->next_in = outbuf;     /* signal write error */
+                return Z_BUF_ERROR;
+            }
+            return Z_OK;
+        }
+        code += (unsigned)last << left;     /* middle (or high) bits of code */
+        left += 8;
+        chunk--;
+        if (bits > left) {                  /* need more bits */
+            if (NEXT() == -1)               /* can't end in middle of code */
+                return Z_BUF_ERROR;
+            code += (unsigned)last << left; /* high bits of code */
+            left += 8;
+            chunk--;
+        }
+        code &= mask;                       /* mask to current code length */
+        left -= bits;                       /* number of unused bits */
+        rem = (unsigned)last >> (8 - left); /* unused bits from last byte */
+
+        /* process clear code (256) */
+        if (code == 256 && flags) {
+            FLUSHCODE();
+            bits = 9;                       /* initialize bits and mask */
+            mask = 0x1ff;
+            end = 255;                      /* empty table */
+            continue;                       /* get next code */
+        }
+
+        /* special code to reuse last match */
+        temp = code;                        /* save the current code */
+        if (code > end) {
+            /* Be picky on the allowed code here, and make sure that the code
+               we drop through (prev) will be a valid index so that random
+               input does not cause an exception.  The code != end + 1 check is
+               empirically derived, and not checked in the original uncompress
+               code.  If this ever causes a problem, that check could be safely
+               removed.  Leaving this check in greatly improves gun's ability
+               to detect random or corrupted input after a compress header.
+               In any case, the prev > end check must be retained. */
+            if (code != end + 1 || prev > end) {
+                strm->msg = (char *)"invalid lzw code";
+                return Z_DATA_ERROR;
+            }
+            match[stack++] = (unsigned char)final;
+            code = prev;
+        }
+
+        /* walk through linked list to generate output in reverse order */
+        while (code >= 256) {
+            match[stack++] = suffix[code];
+            code = prefix[code];
+        }
+        match[stack++] = (unsigned char)code;
+        final = code;
+
+        /* link new table entry */
+        if (end < mask) {
+            end++;
+            prefix[end] = (unsigned short)prev;
+            suffix[end] = (unsigned char)final;
+        }
+
+        /* set previous code for next iteration */
+        prev = temp;
+
+        /* write output in forward order */
+        while (stack > SIZE - outcnt) {
+            while (outcnt < SIZE)
+                outbuf[outcnt++] = match[--stack];
+            if (out(&outd, outbuf, outcnt)) {
+                strm->next_in = outbuf; /* signal write error */
+                return Z_BUF_ERROR;
+            }
+            outcnt = 0;
+        }
+        do {
+            outbuf[outcnt++] = match[--stack];
+        } while (stack);
+
+        /* loop for next code with final and prev as the last match, rem and
+           left provide the first 0..7 bits of the next code, end is the last
+           valid table entry */
+    }
+}
+
+/* Decompress a gzip file from infile to outfile.  strm is assumed to have been
+   successfully initialized with inflateBackInit().  The input file may consist
+   of a series of gzip streams, in which case all of them will be decompressed
+   to the output file.  If outfile is -1, then the gzip stream(s) integrity is
+   checked and nothing is written.
+
+   The return value is a zlib error code: Z_MEM_ERROR if out of memory,
+   Z_DATA_ERROR if the header or the compressed data is invalid, or if the
+   trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends
+   prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip
+   stream) follows a valid gzip stream.
+ */
+local int gunpipe(z_stream *strm, int infile, int outfile)
+{
+    int ret, first, last;
+    unsigned have, flags, len;
+    unsigned char *next;
+    struct ind ind, *indp;
+    struct outd outd;
+
+    /* setup input buffer */
+    ind.infile = infile;
+    ind.inbuf = inbuf;
+    indp = &ind;
+
+    /* decompress concatenated gzip streams */
+    have = 0;                               /* no input data read in yet */
+    first = 1;                              /* looking for first gzip header */
+    strm->next_in = Z_NULL;                 /* so Z_BUF_ERROR means EOF */
+    for (;;) {
+        /* look for the two magic header bytes for a gzip stream */
+        if (NEXT() == -1) {
+            ret = Z_OK;
+            break;                          /* empty gzip stream is ok */
+        }
+        if (last != 31 || (NEXT() != 139 && last != 157)) {
+            strm->msg = (char *)"incorrect header check";
+            ret = first ? Z_DATA_ERROR : Z_ERRNO;
+            break;                          /* not a gzip or compress header */
+        }
+        first = 0;                          /* next non-header is junk */
+
+        /* process a compress (LZW) file -- can't be concatenated after this */
+        if (last == 157) {
+            ret = lunpipe(have, next, indp, outfile, strm);
+            break;
+        }
+
+        /* process remainder of gzip header */
+        ret = Z_BUF_ERROR;
+        if (NEXT() != 8) {                  /* only deflate method allowed */
+            if (last == -1) break;
+            strm->msg = (char *)"unknown compression method";
+            ret = Z_DATA_ERROR;
+            break;
+        }
+        flags = NEXT();                     /* header flags */
+        NEXT();                             /* discard mod time, xflgs, os */
+        NEXT();
+        NEXT();
+        NEXT();
+        NEXT();
+        NEXT();
+        if (last == -1) break;
+        if (flags & 0xe0) {
+            strm->msg = (char *)"unknown header flags set";
+            ret = Z_DATA_ERROR;
+            break;
+        }
+        if (flags & 4) {                    /* extra field */
+            len = NEXT();
+            len += (unsigned)(NEXT()) << 8;
+            if (last == -1) break;
+            while (len > have) {
+                len -= have;
+                have = 0;
+                if (NEXT() == -1) break;
+                len--;
+            }
+            if (last == -1) break;
+            have -= len;
+            next += len;
+        }
+        if (flags & 8)                      /* file name */
+            while (NEXT() != 0 && last != -1)
+                ;
+        if (flags & 16)                     /* comment */
+            while (NEXT() != 0 && last != -1)
+                ;
+        if (flags & 2) {                    /* header crc */
+            NEXT();
+            NEXT();
+        }
+        if (last == -1) break;
+
+        /* set up output */
+        outd.outfile = outfile;
+        outd.check = 1;
+        outd.crc = crc32(0L, Z_NULL, 0);
+        outd.total = 0;
+
+        /* decompress data to output */
+        strm->next_in = next;
+        strm->avail_in = have;
+        ret = inflateBack(strm, in, indp, out, &outd);
+        if (ret != Z_STREAM_END) break;
+        next = strm->next_in;
+        have = strm->avail_in;
+        strm->next_in = Z_NULL;             /* so Z_BUF_ERROR means EOF */
+
+        /* check trailer */
+        ret = Z_BUF_ERROR;
+        if (NEXT() != (outd.crc & 0xff) ||
+            NEXT() != ((outd.crc >> 8) & 0xff) ||
+            NEXT() != ((outd.crc >> 16) & 0xff) ||
+            NEXT() != ((outd.crc >> 24) & 0xff)) {
+            /* crc error */
+            if (last != -1) {
+                strm->msg = (char *)"incorrect data check";
+                ret = Z_DATA_ERROR;
+            }
+            break;
+        }
+        if (NEXT() != (outd.total & 0xff) ||
+            NEXT() != ((outd.total >> 8) & 0xff) ||
+            NEXT() != ((outd.total >> 16) & 0xff) ||
+            NEXT() != ((outd.total >> 24) & 0xff)) {
+            /* length error */
+            if (last != -1) {
+                strm->msg = (char *)"incorrect length check";
+                ret = Z_DATA_ERROR;
+            }
+            break;
+        }
+
+        /* go back and look for another gzip stream */
+    }
+
+    /* clean up and return */
+    return ret;
+}
+
+/* Copy file attributes, from -> to, as best we can.  This is best effort, so
+   no errors are reported.  The mode bits, including suid, sgid, and the sticky
+   bit are copied (if allowed), the owner's user id and group id are copied
+   (again if allowed), and the access and modify times are copied. */
+local void copymeta(char *from, char *to)
+{
+    struct stat was;
+    struct utimbuf when;
+
+    /* get all of from's Unix meta data, return if not a regular file */
+    if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG)
+        return;
+
+    /* set to's mode bits, ignore errors */
+    (void)chmod(to, was.st_mode & 07777);
+
+    /* copy owner's user and group, ignore errors */
+    (void)chown(to, was.st_uid, was.st_gid);
+
+    /* copy access and modify times, ignore errors */
+    when.actime = was.st_atime;
+    when.modtime = was.st_mtime;
+    (void)utime(to, &when);
+}
+
+/* Decompress the file inname to the file outnname, of if test is true, just
+   decompress without writing and check the gzip trailer for integrity.  If
+   inname is NULL or an empty string, read from stdin.  If outname is NULL or
+   an empty string, write to stdout.  strm is a pre-initialized inflateBack
+   structure.  When appropriate, copy the file attributes from inname to
+   outname.
+
+   gunzip() returns 1 if there is an out-of-memory error or an unexpected
+   return code from gunpipe().  Otherwise it returns 0.
+ */
+local int gunzip(z_stream *strm, char *inname, char *outname, int test)
+{
+    int ret;
+    int infile, outfile;
+
+    /* open files */
+    if (inname == NULL || *inname == 0) {
+        inname = "-";
+        infile = 0;     /* stdin */
+    }
+    else {
+        infile = open(inname, O_RDONLY, 0);
+        if (infile == -1) {
+            fprintf(stderr, "gun cannot open %s\n", inname);
+            return 0;
+        }
+    }
+    if (test)
+        outfile = -1;
+    else if (outname == NULL || *outname == 0) {
+        outname = "-";
+        outfile = 1;    /* stdout */
+    }
+    else {
+        outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+        if (outfile == -1) {
+            close(infile);
+            fprintf(stderr, "gun cannot create %s\n", outname);
+            return 0;
+        }
+    }
+    errno = 0;
+
+    /* decompress */
+    ret = gunpipe(strm, infile, outfile);
+    if (outfile > 2) close(outfile);
+    if (infile > 2) close(infile);
+
+    /* interpret result */
+    switch (ret) {
+    case Z_OK:
+    case Z_ERRNO:
+        if (infile > 2 && outfile > 2) {
+            copymeta(inname, outname);          /* copy attributes */
+            unlink(inname);
+        }
+        if (ret == Z_ERRNO)
+            fprintf(stderr, "gun warning: trailing garbage ignored in %s\n",
+                    inname);
+        break;
+    case Z_DATA_ERROR:
+        if (outfile > 2) unlink(outname);
+        fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg);
+        break;
+    case Z_MEM_ERROR:
+        if (outfile > 2) unlink(outname);
+        fprintf(stderr, "gun out of memory error--aborting\n");
+        return 1;
+    case Z_BUF_ERROR:
+        if (outfile > 2) unlink(outname);
+        if (strm->next_in != Z_NULL) {
+            fprintf(stderr, "gun write error on %s: %s\n",
+                    outname, strerror(errno));
+        }
+        else if (errno) {
+            fprintf(stderr, "gun read error on %s: %s\n",
+                    inname, strerror(errno));
+        }
+        else {
+            fprintf(stderr, "gun unexpected end of file on %s\n",
+                    inname);
+        }
+        break;
+    default:
+        if (outfile > 2) unlink(outname);
+        fprintf(stderr, "gun internal error--aborting\n");
+        return 1;
+    }
+    return 0;
+}
+
+/* Process the gun command line arguments.  See the command syntax near the
+   beginning of this source file. */
+int main(int argc, char **argv)
+{
+    int ret, len, test;
+    char *outname;
+    unsigned char *window;
+    z_stream strm;
+
+    /* initialize inflateBack state for repeated use */
+    window = match;                         /* reuse LZW match buffer */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    ret = inflateBackInit(&strm, 15, window);
+    if (ret != Z_OK) {
+        fprintf(stderr, "gun out of memory error--aborting\n");
+        return 1;
+    }
+
+    /* decompress each file to the same name with the suffix removed */
+    argc--;
+    argv++;
+    test = 0;
+    if (argc && strcmp(*argv, "-h") == 0) {
+        fprintf(stderr, "gun 1.3 (12 Jun 2005)\n");
+        fprintf(stderr, "Copyright (c) 2005 Mark Adler\n");
+        fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n");
+        return 0;
+    }
+    if (argc && strcmp(*argv, "-t") == 0) {
+        test = 1;
+        argc--;
+        argv++;
+    }
+    if (argc)
+        do {
+            if (test)
+                outname = NULL;
+            else {
+                len = (int)strlen(*argv);
+                if (strcmp(*argv + len - 3, ".gz") == 0 ||
+                    strcmp(*argv + len - 3, "-gz") == 0)
+                    len -= 3;
+                else if (strcmp(*argv + len - 2, ".z") == 0 ||
+                    strcmp(*argv + len - 2, "-z") == 0 ||
+                    strcmp(*argv + len - 2, "_z") == 0 ||
+                    strcmp(*argv + len - 2, ".Z") == 0)
+                    len -= 2;
+                else {
+                    fprintf(stderr, "gun error: no gz type on %s--skipping\n",
+                            *argv);
+                    continue;
+                }
+                outname = malloc(len + 1);
+                if (outname == NULL) {
+                    fprintf(stderr, "gun out of memory error--aborting\n");
+                    ret = 1;
+                    break;
+                }
+                memcpy(outname, *argv, len);
+                outname[len] = 0;
+            }
+            ret = gunzip(&strm, *argv, outname, test);
+            if (outname != NULL) free(outname);
+            if (ret) break;
+        } while (argv++, --argc);
+    else
+        ret = gunzip(&strm, NULL, NULL, test);
+
+    /* clean up */
+    inflateBackEnd(&strm);
+    return ret;
+}
diff --git a/zlib/examples/gzjoin.c b/zlib/examples/gzjoin.c
new file mode 100644 (file)
index 0000000..129347c
--- /dev/null
@@ -0,0 +1,448 @@
+/* gzjoin -- command to join gzip files into one gzip file
+
+  Copyright (C) 2004 Mark Adler, all rights reserved
+  version 1.0, 11 Dec 2004
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the author be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Mark Adler    madler@alumni.caltech.edu
+ */
+
+/*
+ * Change history:
+ *
+ * 1.0  11 Dec 2004     - First version
+ * 1.1  12 Jun 2005     - Changed ssize_t to long for portability
+ */
+
+/*
+   gzjoin takes one or more gzip files on the command line and writes out a
+   single gzip file that will uncompress to the concatenation of the
+   uncompressed data from the individual gzip files.  gzjoin does this without
+   having to recompress any of the data and without having to calculate a new
+   crc32 for the concatenated uncompressed data.  gzjoin does however have to
+   decompress all of the input data in order to find the bits in the compressed
+   data that need to be modified to concatenate the streams.
+
+   gzjoin does not do an integrity check on the input gzip files other than
+   checking the gzip header and decompressing the compressed data.  They are
+   otherwise assumed to be complete and correct.
+
+   Each joint between gzip files removes at least 18 bytes of previous trailer
+   and subsequent header, and inserts an average of about three bytes to the
+   compressed data in order to connect the streams.  The output gzip file
+   has a minimal ten-byte gzip header with no file name or modification time.
+
+   This program was written to illustrate the use of the Z_BLOCK option of
+   inflate() and the crc32_combine() function.  gzjoin will not compile with
+   versions of zlib earlier than 1.2.3.
+ */
+
+#include <stdio.h>      /* fputs(), fprintf(), fwrite(), putc() */
+#include <stdlib.h>     /* exit(), malloc(), free() */
+#include <fcntl.h>      /* open() */
+#include <unistd.h>     /* close(), read(), lseek() */
+#include "zlib.h"
+    /* crc32(), crc32_combine(), inflateInit2(), inflate(), inflateEnd() */
+
+#define local static
+
+/* exit with an error (return a value to allow use in an expression) */
+local int bail(char *why1, char *why2)
+{
+    fprintf(stderr, "gzjoin error: %s%s, output incomplete\n", why1, why2);
+    exit(1);
+    return 0;
+}
+
+/* -- simple buffered file input with access to the buffer -- */
+
+#define CHUNK 32768         /* must be a power of two and fit in unsigned */
+
+/* bin buffered input file type */
+typedef struct {
+    char *name;             /* name of file for error messages */
+    int fd;                 /* file descriptor */
+    unsigned left;          /* bytes remaining at next */
+    unsigned char *next;    /* next byte to read */
+    unsigned char *buf;     /* allocated buffer of length CHUNK */
+} bin;
+
+/* close a buffered file and free allocated memory */
+local void bclose(bin *in)
+{
+    if (in != NULL) {
+        if (in->fd != -1)
+            close(in->fd);
+        if (in->buf != NULL)
+            free(in->buf);
+        free(in);
+    }
+}
+
+/* open a buffered file for input, return a pointer to type bin, or NULL on
+   failure */
+local bin *bopen(char *name)
+{
+    bin *in;
+
+    in = malloc(sizeof(bin));
+    if (in == NULL)
+        return NULL;
+    in->buf = malloc(CHUNK);
+    in->fd = open(name, O_RDONLY, 0);
+    if (in->buf == NULL || in->fd == -1) {
+        bclose(in);
+        return NULL;
+    }
+    in->left = 0;
+    in->next = in->buf;
+    in->name = name;
+    return in;
+}
+
+/* load buffer from file, return -1 on read error, 0 or 1 on success, with
+   1 indicating that end-of-file was reached */
+local int bload(bin *in)
+{
+    long len;
+
+    if (in == NULL)
+        return -1;
+    if (in->left != 0)
+        return 0;
+    in->next = in->buf;
+    do {
+        len = (long)read(in->fd, in->buf + in->left, CHUNK - in->left);
+        if (len < 0)
+            return -1;
+        in->left += (unsigned)len;
+    } while (len != 0 && in->left < CHUNK);
+    return len == 0 ? 1 : 0;
+}
+
+/* get a byte from the file, bail if end of file */
+#define bget(in) (in->left ? 0 : bload(in), \
+                  in->left ? (in->left--, *(in->next)++) : \
+                    bail("unexpected end of file on ", in->name))
+
+/* get a four-byte little-endian unsigned integer from file */
+local unsigned long bget4(bin *in)
+{
+    unsigned long val;
+
+    val = bget(in);
+    val += (unsigned long)(bget(in)) << 8;
+    val += (unsigned long)(bget(in)) << 16;
+    val += (unsigned long)(bget(in)) << 24;
+    return val;
+}
+
+/* skip bytes in file */
+local void bskip(bin *in, unsigned skip)
+{
+    /* check pointer */
+    if (in == NULL)
+        return;
+
+    /* easy case -- skip bytes in buffer */
+    if (skip <= in->left) {
+        in->left -= skip;
+        in->next += skip;
+        return;
+    }
+
+    /* skip what's in buffer, discard buffer contents */
+    skip -= in->left;
+    in->left = 0;
+
+    /* seek past multiples of CHUNK bytes */
+    if (skip > CHUNK) {
+        unsigned left;
+
+        left = skip & (CHUNK - 1);
+        if (left == 0) {
+            /* exact number of chunks: seek all the way minus one byte to check
+               for end-of-file with a read */
+            lseek(in->fd, skip - 1, SEEK_CUR);
+            if (read(in->fd, in->buf, 1) != 1)
+                bail("unexpected end of file on ", in->name);
+            return;
+        }
+
+        /* skip the integral chunks, update skip with remainder */
+        lseek(in->fd, skip - left, SEEK_CUR);
+        skip = left;
+    }
+
+    /* read more input and skip remainder */
+    bload(in);
+    if (skip > in->left)
+        bail("unexpected end of file on ", in->name);
+    in->left -= skip;
+    in->next += skip;
+}
+
+/* -- end of buffered input functions -- */
+
+/* skip the gzip header from file in */
+local void gzhead(bin *in)
+{
+    int flags;
+
+    /* verify gzip magic header and compression method */
+    if (bget(in) != 0x1f || bget(in) != 0x8b || bget(in) != 8)
+        bail(in->name, " is not a valid gzip file");
+
+    /* get and verify flags */
+    flags = bget(in);
+    if ((flags & 0xe0) != 0)
+        bail("unknown reserved bits set in ", in->name);
+
+    /* skip modification time, extra flags, and os */
+    bskip(in, 6);
+
+    /* skip extra field if present */
+    if (flags & 4) {
+        unsigned len;
+
+        len = bget(in);
+        len += (unsigned)(bget(in)) << 8;
+        bskip(in, len);
+    }
+
+    /* skip file name if present */
+    if (flags & 8)
+        while (bget(in) != 0)
+            ;
+
+    /* skip comment if present */
+    if (flags & 16)
+        while (bget(in) != 0)
+            ;
+
+    /* skip header crc if present */
+    if (flags & 2)
+        bskip(in, 2);
+}
+
+/* write a four-byte little-endian unsigned integer to out */
+local void put4(unsigned long val, FILE *out)
+{
+    putc(val & 0xff, out);
+    putc((val >> 8) & 0xff, out);
+    putc((val >> 16) & 0xff, out);
+    putc((val >> 24) & 0xff, out);
+}
+
+/* Load up zlib stream from buffered input, bail if end of file */
+local void zpull(z_streamp strm, bin *in)
+{
+    if (in->left == 0)
+        bload(in);
+    if (in->left == 0)
+        bail("unexpected end of file on ", in->name);
+    strm->avail_in = in->left;
+    strm->next_in = in->next;
+}
+
+/* Write header for gzip file to out and initialize trailer. */
+local void gzinit(unsigned long *crc, unsigned long *tot, FILE *out)
+{
+    fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out);
+    *crc = crc32(0L, Z_NULL, 0);
+    *tot = 0;
+}
+
+/* Copy the compressed data from name, zeroing the last block bit of the last
+   block if clr is true, and adding empty blocks as needed to get to a byte
+   boundary.  If clr is false, then the last block becomes the last block of
+   the output, and the gzip trailer is written.  crc and tot maintains the
+   crc and length (modulo 2^32) of the output for the trailer.  The resulting
+   gzip file is written to out.  gzinit() must be called before the first call
+   of gzcopy() to write the gzip header and to initialize crc and tot. */
+local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot,
+                  FILE *out)
+{
+    int ret;                /* return value from zlib functions */
+    int pos;                /* where the "last block" bit is in byte */
+    int last;               /* true if processing the last block */
+    bin *in;                /* buffered input file */
+    unsigned char *start;   /* start of compressed data in buffer */
+    unsigned char *junk;    /* buffer for uncompressed data -- discarded */
+    z_off_t len;            /* length of uncompressed data (support > 4 GB) */
+    z_stream strm;          /* zlib inflate stream */
+
+    /* open gzip file and skip header */
+    in = bopen(name);
+    if (in == NULL)
+        bail("could not open ", name);
+    gzhead(in);
+
+    /* allocate buffer for uncompressed data and initialize raw inflate
+       stream */
+    junk = malloc(CHUNK);
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit2(&strm, -15);
+    if (junk == NULL || ret != Z_OK)
+        bail("out of memory", "");
+
+    /* inflate and copy compressed data, clear last-block bit if requested */
+    len = 0;
+    zpull(&strm, in);
+    start = strm.next_in;
+    last = start[0] & 1;
+    if (last && clr)
+        start[0] &= ~1;
+    strm.avail_out = 0;
+    for (;;) {
+        /* if input used and output done, write used input and get more */
+        if (strm.avail_in == 0 && strm.avail_out != 0) {
+            fwrite(start, 1, strm.next_in - start, out);
+            start = in->buf;
+            in->left = 0;
+            zpull(&strm, in);
+        }
+
+        /* decompress -- return early when end-of-block reached */
+        strm.avail_out = CHUNK;
+        strm.next_out = junk;
+        ret = inflate(&strm, Z_BLOCK);
+        switch (ret) {
+        case Z_MEM_ERROR:
+            bail("out of memory", "");
+        case Z_DATA_ERROR:
+            bail("invalid compressed data in ", in->name);
+        }
+
+        /* update length of uncompressed data */
+        len += CHUNK - strm.avail_out;
+
+        /* check for block boundary (only get this when block copied out) */
+        if (strm.data_type & 128) {
+            /* if that was the last block, then done */
+            if (last)
+                break;
+
+            /* number of unused bits in last byte */
+            pos = strm.data_type & 7;
+
+            /* find the next last-block bit */
+            if (pos != 0) {
+                /* next last-block bit is in last used byte */
+                pos = 0x100 >> pos;
+                last = strm.next_in[-1] & pos;
+                if (last && clr)
+                    strm.next_in[-1] &= ~pos;
+            }
+            else {
+                /* next last-block bit is in next unused byte */
+                if (strm.avail_in == 0) {
+                    /* don't have that byte yet -- get it */
+                    fwrite(start, 1, strm.next_in - start, out);
+                    start = in->buf;
+                    in->left = 0;
+                    zpull(&strm, in);
+                }
+                last = strm.next_in[0] & 1;
+                if (last && clr)
+                    strm.next_in[0] &= ~1;
+            }
+        }
+    }
+
+    /* update buffer with unused input */
+    in->left = strm.avail_in;
+    in->next = strm.next_in;
+
+    /* copy used input, write empty blocks to get to byte boundary */
+    pos = strm.data_type & 7;
+    fwrite(start, 1, in->next - start - 1, out);
+    last = in->next[-1];
+    if (pos == 0 || !clr)
+        /* already at byte boundary, or last file: write last byte */
+        putc(last, out);
+    else {
+        /* append empty blocks to last byte */
+        last &= ((0x100 >> pos) - 1);       /* assure unused bits are zero */
+        if (pos & 1) {
+            /* odd -- append an empty stored block */
+            putc(last, out);
+            if (pos == 1)
+                putc(0, out);               /* two more bits in block header */
+            fwrite("\0\0\xff\xff", 1, 4, out);
+        }
+        else {
+            /* even -- append 1, 2, or 3 empty fixed blocks */
+            switch (pos) {
+            case 6:
+                putc(last | 8, out);
+                last = 0;
+            case 4:
+                putc(last | 0x20, out);
+                last = 0;
+            case 2:
+                putc(last | 0x80, out);
+                putc(0, out);
+            }
+        }
+    }
+
+    /* update crc and tot */
+    *crc = crc32_combine(*crc, bget4(in), len);
+    *tot += (unsigned long)len;
+
+    /* clean up */
+    inflateEnd(&strm);
+    free(junk);
+    bclose(in);
+
+    /* write trailer if this is the last gzip file */
+    if (!clr) {
+        put4(*crc, out);
+        put4(*tot, out);
+    }
+}
+
+/* join the gzip files on the command line, write result to stdout */
+int main(int argc, char **argv)
+{
+    unsigned long crc, tot;     /* running crc and total uncompressed length */
+
+    /* skip command name */
+    argc--;
+    argv++;
+
+    /* show usage if no arguments */
+    if (argc == 0) {
+        fputs("gzjoin usage: gzjoin f1.gz [f2.gz [f3.gz ...]] > fjoin.gz\n",
+              stderr);
+        return 0;
+    }
+
+    /* join gzip files on command line and write to stdout */
+    gzinit(&crc, &tot, stdout);
+    while (argc--)
+        gzcopy(*argv++, argc, &crc, &tot, stdout);
+
+    /* done */
+    return 0;
+}
diff --git a/zlib/examples/zlib_how.html b/zlib/examples/zlib_how.html
new file mode 100644 (file)
index 0000000..40998db
--- /dev/null
@@ -0,0 +1,523 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+  "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>zlib Usage Example</title>
+<!--  Copyright (c) 2004 Mark Adler.  -->
+</head>
+<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#00A000">
+<h2 align="center"> zlib Usage Example </h2>
+We often get questions about how the <tt>deflate()</tt> and <tt>inflate()</tt> functions should be used.
+Users wonder when they should provide more input, when they should use more output,
+what to do with a <tt>Z_BUF_ERROR</tt>, how to make sure the process terminates properly, and
+so on.  So for those who have read <tt>zlib.h</tt> (a few times), and
+would like further edification, below is an annotated example in C of simple routines to compress and decompress
+from an input file to an output file using <tt>deflate()</tt> and <tt>inflate()</tt> respectively.  The
+annotations are interspersed between lines of the code.  So please read between the lines.
+We hope this helps explain some of the intricacies of <em>zlib</em>.
+<p>
+Without further adieu, here is the program <a href="zpipe.c"><tt>zpipe.c</tt></a>:
+<pre><b>
+/* zpipe.c: example of proper use of zlib's inflate() and deflate()
+   Not copyrighted -- provided to the public domain
+   Version 1.2  9 November 2004  Mark Adler */
+
+/* Version history:
+   1.0  30 Oct 2004  First version
+   1.1   8 Nov 2004  Add void casting for unused return values
+                     Use switch statement for inflate() return values
+   1.2   9 Nov 2004  Add assertions to document zlib guarantees
+ */
+</b></pre><!-- -->
+We now include the header files for the required definitions.  From
+<tt>stdio.h</tt> we use <tt>fopen()</tt>, <tt>fread()</tt>, <tt>fwrite()</tt>,
+<tt>feof()</tt>, <tt>ferror()</tt>, and <tt>fclose()</tt> for file i/o, and
+<tt>fputs()</tt> for error messages.  From <tt>string.h</tt> we use
+<tt>strcmp()</tt> for command line argument processing.
+From <tt>assert.h</tt> we use the <tt>assert()</tt> macro.
+From <tt>zlib.h</tt>
+we use the basic compression functions <tt>deflateInit()</tt>,
+<tt>deflate()</tt>, and <tt>deflateEnd()</tt>, and the basic decompression
+functions <tt>inflateInit()</tt>, <tt>inflate()</tt>, and
+<tt>inflateEnd()</tt>.
+<pre><b>
+#include &lt;stdio.h&gt;
+#include &lt;string.h&gt;
+#include &lt;assert.h&gt;
+#include "zlib.h"
+</b></pre><!-- -->
+<tt>CHUNK</tt> is simply the buffer size for feeding data to and pulling data
+from the <em>zlib</em> routines.  Larger buffer sizes would be more efficient,
+especially for <tt>inflate()</tt>.  If the memory is available, buffers sizes
+on the order of 128K or 256K bytes should be used.
+<pre><b>
+#define CHUNK 16384
+</b></pre><!-- -->
+The <tt>def()</tt> routine compresses data from an input file to an output file.  The output data
+will be in the <em>zlib</em> format, which is different from the <em>gzip</em> or <em>zip</em>
+formats.  The <em>zlib</em> format has a very small header of only two bytes to identify it as
+a <em>zlib</em> stream and to provide decoding information, and a four-byte trailer with a fast
+check value to verify the integrity of the uncompressed data after decoding.
+<pre><b>
+/* Compress from file source to file dest until EOF on source.
+   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_STREAM_ERROR if an invalid compression
+   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
+   version of the library linked do not match, or Z_ERRNO if there is
+   an error reading or writing the files. */
+int def(FILE *source, FILE *dest, int level)
+{
+</b></pre>
+Here are the local variables for <tt>def()</tt>.  <tt>ret</tt> will be used for <em>zlib</em>
+return codes.  <tt>flush</tt> will keep track of the current flushing state for <tt>deflate()</tt>,
+which is either no flushing, or flush to completion after the end of the input file is reached.
+<tt>have</tt> is the amount of data returned from <tt>deflate()</tt>.  The <tt>strm</tt> structure
+is used to pass information to and from the <em>zlib</em> routines, and to maintain the
+<tt>deflate()</tt> state.  <tt>in</tt> and <tt>out</tt> are the input and output buffers for
+<tt>deflate()</tt>.
+<pre><b>
+    int ret, flush;
+    unsigned have;
+    z_stream strm;
+    char in[CHUNK];
+    char out[CHUNK];
+</b></pre><!-- -->
+The first thing we do is to initialize the <em>zlib</em> state for compression using
+<tt>deflateInit()</tt>.  This must be done before the first use of <tt>deflate()</tt>.
+The <tt>zalloc</tt>, <tt>zfree</tt>, and <tt>opaque</tt> fields in the <tt>strm</tt>
+structure must be initialized before calling <tt>deflateInit()</tt>.  Here they are
+set to the <em>zlib</em> constant <tt>Z_NULL</tt> to request that <em>zlib</em> use
+the default memory allocation routines.  An application may also choose to provide
+custom memory allocation routines here.  <tt>deflateInit()</tt> will allocate on the
+order of 256K bytes for the internal state.
+(See <a href="zlib_tech.html"><em>zlib Technical Details</em></a>.)
+<p>
+<tt>deflateInit()</tt> is called with a pointer to the structure to be initialized and
+the compression level, which is an integer in the range of -1 to 9.  Lower compression
+levels result in faster execution, but less compression.  Higher levels result in
+greater compression, but slower execution.  The <em>zlib</em> constant Z_DEFAULT_COMPRESSION,
+equal to -1,
+provides a good compromise between compression and speed and is equivalent to level 6.
+Level 0 actually does no compression at all, and in fact expands the data slightly to produce
+the <em>zlib</em> format (it is not a byte-for-byte copy of the input).
+More advanced applications of <em>zlib</em>
+may use <tt>deflateInit2()</tt> here instead.  Such an application may want to reduce how
+much memory will be used, at some price in compression.  Or it may need to request a
+<em>gzip</em> header and trailer instead of a <em>zlib</em> header and trailer, or raw
+encoding with no header or trailer at all.
+<p>
+We must check the return value of <tt>deflateInit()</tt> against the <em>zlib</em> constant
+<tt>Z_OK</tt> to make sure that it was able to
+allocate memory for the internal state, and that the provided arguments were valid.
+<tt>deflateInit()</tt> will also check that the version of <em>zlib</em> that the <tt>zlib.h</tt>
+file came from matches the version of <em>zlib</em> actually linked with the program.  This
+is especially important for environments in which <em>zlib</em> is a shared library.
+<p>
+Note that an application can initialize multiple, independent <em>zlib</em> streams, which can
+operate in parallel.  The state information maintained in the structure allows the <em>zlib</em>
+routines to be reentrant.
+<pre><b>
+    /* allocate deflate state */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    ret = deflateInit(&amp;strm, level);
+    if (ret != Z_OK)
+        return ret;
+</b></pre><!-- -->
+With the pleasantries out of the way, now we can get down to business.  The outer <tt>do</tt>-loop
+reads all of the input file and exits at the bottom of the loop once end-of-file is reached.
+This loop contains the only call of <tt>deflate()</tt>.  So we must make sure that all of the
+input data has been processed and that all of the output data has been generated and consumed
+before we fall out of the loop at the bottom.
+<pre><b>
+    /* compress until end of file */
+    do {
+</b></pre>
+We start off by reading data from the input file.  The number of bytes read is put directly
+into <tt>avail_in</tt>, and a pointer to those bytes is put into <tt>next_in</tt>.  We also
+check to see if end-of-file on the input has been reached.  If we are at the end of file, then <tt>flush</tt> is set to the
+<em>zlib</em> constant <tt>Z_FINISH</tt>, which is later passed to <tt>deflate()</tt> to
+indicate that this is the last chunk of input data to compress.  We need to use <tt>feof()</tt>
+to check for end-of-file as opposed to seeing if fewer than <tt>CHUNK</tt> bytes have been read.  The
+reason is that if the input file length is an exact multiple of <tt>CHUNK</tt>, we will miss
+the fact that we got to the end-of-file, and not know to tell <tt>deflate()</tt> to finish
+up the compressed stream.  If we are not yet at the end of the input, then the <em>zlib</em>
+constant <tt>Z_NO_FLUSH</tt> will be passed to <tt>deflate</tt> to indicate that we are still
+in the middle of the uncompressed data.
+<p>
+If there is an error in reading from the input file, the process is aborted with
+<tt>deflateEnd()</tt> being called to free the allocated <em>zlib</em> state before returning
+the error.  We wouldn't want a memory leak, now would we?  <tt>deflateEnd()</tt> can be called
+at any time after the state has been initialized.  Once that's done, <tt>deflateInit()</tt> (or
+<tt>deflateInit2()</tt>) would have to be called to start a new compression process.  There is
+no point here in checking the <tt>deflateEnd()</tt> return code.  The deallocation can't fail.
+<pre><b>
+        strm.avail_in = fread(in, 1, CHUNK, source);
+        if (ferror(source)) {
+            (void)deflateEnd(&amp;strm);
+            return Z_ERRNO;
+        }
+        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
+        strm.next_in = in;
+</b></pre><!-- -->
+The inner <tt>do</tt>-loop passes our chunk of input data to <tt>deflate()</tt>, and then
+keeps calling <tt>deflate()</tt> until it is done producing output.  Once there is no more
+new output, <tt>deflate()</tt> is guaranteed to have consumed all of the input, i.e.,
+<tt>avail_in</tt> will be zero.
+<pre><b>
+        /* run deflate() on input until output buffer not full, finish
+           compression if all of source has been read in */
+        do {
+</b></pre>
+Output space is provided to <tt>deflate()</tt> by setting <tt>avail_out</tt> to the number
+of available output bytes and <tt>next_out</tt> to a pointer to that space.
+<pre><b>
+            strm.avail_out = CHUNK;
+            strm.next_out = out;
+</b></pre>
+Now we call the compression engine itself, <tt>deflate()</tt>.  It takes as many of the
+<tt>avail_in</tt> bytes at <tt>next_in</tt> as it can process, and writes as many as
+<tt>avail_out</tt> bytes to <tt>next_out</tt>.  Those counters and pointers are then
+updated past the input data consumed and the output data written.  It is the amount of
+output space available that may limit how much input is consumed.
+Hence the inner loop to make sure that
+all of the input is consumed by providing more output space each time.  Since <tt>avail_in</tt>
+and <tt>next_in</tt> are updated by <tt>deflate()</tt>, we don't have to mess with those
+between <tt>deflate()</tt> calls until it's all used up.
+<p>
+The parameters to <tt>deflate()</tt> are a pointer to the <tt>strm</tt> structure containing
+the input and output information and the internal compression engine state, and a parameter
+indicating whether and how to flush data to the output.  Normally <tt>deflate</tt> will consume
+several K bytes of input data before producing any output (except for the header), in order
+to accumulate statistics on the data for optimum compression.  It will then put out a burst of
+compressed data, and proceed to consume more input before the next burst.  Eventually,
+<tt>deflate()</tt>
+must be told to terminate the stream, complete the compression with provided input data, and
+write out the trailer check value.  <tt>deflate()</tt> will continue to compress normally as long
+as the flush parameter is <tt>Z_NO_FLUSH</tt>.  Once the <tt>Z_FINISH</tt> parameter is provided,
+<tt>deflate()</tt> will begin to complete the compressed output stream.  However depending on how
+much output space is provided, <tt>deflate()</tt> may have to be called several times until it
+has provided the complete compressed stream, even after it has consumed all of the input.  The flush
+parameter must continue to be <tt>Z_FINISH</tt> for those subsequent calls.
+<p>
+There are other values of the flush parameter that are used in more advanced applications.  You can
+force <tt>deflate()</tt> to produce a burst of output that encodes all of the input data provided
+so far, even if it wouldn't have otherwise, for example to control data latency on a link with
+compressed data.  You can also ask that <tt>deflate()</tt> do that as well as erase any history up to
+that point so that what follows can be decompressed independently, for example for random access
+applications.  Both requests will degrade compression by an amount depending on how often such
+requests are made.
+<p>
+<tt>deflate()</tt> has a return value that can indicate errors, yet we do not check it here.  Why
+not?  Well, it turns out that <tt>deflate()</tt> can do no wrong here.  Let's go through
+<tt>deflate()</tt>'s return values and dispense with them one by one.  The possible values are
+<tt>Z_OK</tt>, <tt>Z_STREAM_END</tt>, <tt>Z_STREAM_ERROR</tt>, or <tt>Z_BUF_ERROR</tt>.  <tt>Z_OK</tt>
+is, well, ok.  <tt>Z_STREAM_END</tt> is also ok and will be returned for the last call of
+<tt>deflate()</tt>.  This is already guaranteed by calling <tt>deflate()</tt> with <tt>Z_FINISH</tt>
+until it has no more output.  <tt>Z_STREAM_ERROR</tt> is only possible if the stream is not
+initialized properly, but we did initialize it properly.  There is no harm in checking for
+<tt>Z_STREAM_ERROR</tt> here, for example to check for the possibility that some
+other part of the application inadvertently clobbered the memory containing the <em>zlib</em> state.
+<tt>Z_BUF_ERROR</tt> will be explained further below, but
+suffice it to say that this is simply an indication that <tt>deflate()</tt> could not consume
+more input or produce more output.  <tt>deflate()</tt> can be called again with more output space
+or more available input, which it will be in this code.
+<pre><b>
+            ret = deflate(&amp;strm, flush);    /* no bad return value */
+            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+</b></pre>
+Now we compute how much output <tt>deflate()</tt> provided on the last call, which is the
+difference between how much space was provided before the call, and how much output space
+is still available after the call.  Then that data, if any, is written to the output file.
+We can then reuse the output buffer for the next call of <tt>deflate()</tt>.  Again if there
+is a file i/o error, we call <tt>deflateEnd()</tt> before returning to avoid a memory leak.
+<pre><b>
+            have = CHUNK - strm.avail_out;
+            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+                (void)deflateEnd(&amp;strm);
+                return Z_ERRNO;
+            }
+</b></pre>
+The inner <tt>do</tt>-loop is repeated until the last <tt>deflate()</tt> call fails to fill the
+provided output buffer.  Then we know that <tt>deflate()</tt> has done as much as it can with
+the provided input, and that all of that input has been consumed.  We can then fall out of this
+loop and reuse the input buffer.
+<p>
+The way we tell that <tt>deflate()</tt> has no more output is by seeing that it did not fill
+the output buffer, leaving <tt>avail_out</tt> greater than zero.  However suppose that
+<tt>deflate()</tt> has no more output, but just so happened to exactly fill the output buffer!
+<tt>avail_out</tt> is zero, and we can't tell that <tt>deflate()</tt> has done all it can.
+As far as we know, <tt>deflate()</tt>
+has more output for us.  So we call it again.  But now <tt>deflate()</tt> produces no output
+at all, and <tt>avail_out</tt> remains unchanged as <tt>CHUNK</tt>.  That <tt>deflate()</tt> call
+wasn't able to do anything, either consume input or produce output, and so it returns
+<tt>Z_BUF_ERROR</tt>.  (See, I told you I'd cover this later.)  However this is not a problem at
+all.  Now we finally have the desired indication that <tt>deflate()</tt> is really done,
+and so we drop out of the inner loop to provide more input to <tt>deflate()</tt>.
+<p>
+With <tt>flush</tt> set to <tt>Z_FINISH</tt>, this final set of <tt>deflate()</tt> calls will
+complete the output stream.  Once that is done, subsequent calls of <tt>deflate()</tt> would return
+<tt>Z_STREAM_ERROR</tt> if the flush parameter is not <tt>Z_FINISH</tt>, and do no more processing
+until the state is reinitialized.
+<p>
+Some applications of <em>zlib</em> have two loops that call <tt>deflate()</tt>
+instead of the single inner loop we have here.  The first loop would call
+without flushing and feed all of the data to <tt>deflate()</tt>.  The second loop would call
+<tt>deflate()</tt> with no more
+data and the <tt>Z_FINISH</tt> parameter to complete the process.  As you can see from this
+example, that can be avoided by simply keeping track of the current flush state.
+<pre><b>
+        } while (strm.avail_out == 0);
+        assert(strm.avail_in == 0);     /* all input will be used */
+</b></pre><!-- -->
+Now we check to see if we have already processed all of the input file.  That information was
+saved in the <tt>flush</tt> variable, so we see if that was set to <tt>Z_FINISH</tt>.  If so,
+then we're done and we fall out of the outer loop.  We're guaranteed to get <tt>Z_STREAM_END</tt>
+from the last <tt>deflate()</tt> call, since we ran it until the last chunk of input was
+consumed and all of the output was generated.
+<pre><b>
+        /* done when last data in file processed */
+    } while (flush != Z_FINISH);
+    assert(ret == Z_STREAM_END);        /* stream will be complete */
+</b></pre><!-- -->
+The process is complete, but we still need to deallocate the state to avoid a memory leak
+(or rather more like a memory hemorrhage if you didn't do this).  Then
+finally we can return with a happy return value.
+<pre><b>
+    /* clean up and return */
+    (void)deflateEnd(&amp;strm);
+    return Z_OK;
+}
+</b></pre><!-- -->
+Now we do the same thing for decompression in the <tt>inf()</tt> routine. <tt>inf()</tt>
+decompresses what is hopefully a valid <em>zlib</em> stream from the input file and writes the
+uncompressed data to the output file.  Much of the discussion above for <tt>def()</tt>
+applies to <tt>inf()</tt> as well, so the discussion here will focus on the differences between
+the two.
+<pre><b>
+/* Decompress from file source to file dest until stream ends or EOF.
+   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_DATA_ERROR if the deflate data is
+   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
+   the version of the library linked do not match, or Z_ERRNO if there
+   is an error reading or writing the files. */
+int inf(FILE *source, FILE *dest)
+{
+</b></pre>
+The local variables have the same functionality as they do for <tt>def()</tt>.  The
+only difference is that there is no <tt>flush</tt> variable, since <tt>inflate()</tt>
+can tell from the <em>zlib</em> stream itself when the stream is complete.
+<pre><b>
+    int ret;
+    unsigned have;
+    z_stream strm;
+    char in[CHUNK];
+    char out[CHUNK];
+</b></pre><!-- -->
+The initialization of the state is the same, except that there is no compression level,
+of course, and two more elements of the structure are initialized.  <tt>avail_in</tt>
+and <tt>next_in</tt> must be initialized before calling <tt>inflateInit()</tt>.  This
+is because the application has the option to provide the start of the zlib stream in
+order for <tt>inflateInit()</tt> to have access to information about the compression
+method to aid in memory allocation.  In the current implementation of <em>zlib</em>
+(up through versions 1.2.x), the method-dependent memory allocations are deferred to the first call of
+<tt>inflate()</tt> anyway.  However those fields must be initialized since later versions
+of <em>zlib</em> that provide more compression methods may take advantage of this interface.
+In any case, no decompression is performed by <tt>inflateInit()</tt>, so the
+<tt>avail_out</tt> and <tt>next_out</tt> fields do not need to be initialized before calling.
+<p>
+Here <tt>avail_in</tt> is set to zero and <tt>next_in</tt> is set to <tt>Z_NULL</tt> to
+indicate that no input data is being provided.
+<pre><b>
+    /* allocate inflate state */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit(&amp;strm);
+    if (ret != Z_OK)
+        return ret;
+</b></pre><!-- -->
+The outer <tt>do</tt>-loop decompresses input until <tt>inflate()</tt> indicates
+that it has reached the end of the compressed data and has produced all of the uncompressed
+output.  This is in contrast to <tt>def()</tt> which processes all of the input file.
+If end-of-file is reached before the compressed data self-terminates, then the compressed
+data is incomplete and an error is returned.
+<pre><b>
+    /* decompress until deflate stream ends or end of file */
+    do {
+</b></pre>
+We read input data and set the <tt>strm</tt> structure accordingly.  If we've reached the
+end of the input file, then we leave the outer loop and report an error, since the
+compressed data is incomplete.  Note that we may read more data than is eventually consumed
+by <tt>inflate()</tt>, if the input file continues past the <em>zlib</em> stream.
+For applications where <em>zlib</em> streams are embedded in other data, this routine would
+need to be modified to return the unused data, or at least indicate how much of the input
+data was not used, so the application would know where to pick up after the <em>zlib</em> stream.
+<pre><b>
+        strm.avail_in = fread(in, 1, CHUNK, source);
+        if (ferror(source)) {
+            (void)inflateEnd(&amp;strm);
+            return Z_ERRNO;
+        }
+        if (strm.avail_in == 0)
+            break;
+        strm.next_in = in;
+</b></pre><!-- -->
+The inner <tt>do</tt>-loop has the same function it did in <tt>def()</tt>, which is to
+keep calling <tt>inflate()</tt> until has generated all of the output it can with the
+provided input.
+<pre><b>
+        /* run inflate() on input until output buffer not full */
+        do {
+</b></pre>
+Just like in <tt>def()</tt>, the same output space is provided for each call of <tt>inflate()</tt>.
+<pre><b>
+            strm.avail_out = CHUNK;
+            strm.next_out = out;
+</b></pre>
+Now we run the decompression engine itself.  There is no need to adjust the flush parameter, since
+the <em>zlib</em> format is self-terminating. The main difference here is that there are
+return values that we need to pay attention to.  <tt>Z_DATA_ERROR</tt>
+indicates that <tt>inflate()</tt> detected an error in the <em>zlib</em> compressed data format,
+which means that either the data is not a <em>zlib</em> stream to begin with, or that the data was
+corrupted somewhere along the way since it was compressed.  The other error to be processed is
+<tt>Z_MEM_ERROR</tt>, which can occur since memory allocation is deferred until <tt>inflate()</tt>
+needs it, unlike <tt>deflate()</tt>, whose memory is allocated at the start by <tt>deflateInit()</tt>.
+<p>
+Advanced applications may use
+<tt>deflateSetDictionary()</tt> to prime <tt>deflate()</tt> with a set of likely data to improve the
+first 32K or so of compression.  This is noted in the <em>zlib</em> header, so <tt>inflate()</tt>
+requests that that dictionary be provided before it can start to decompress.  Without the dictionary,
+correct decompression is not possible.  For this routine, we have no idea what the dictionary is,
+so the <tt>Z_NEED_DICT</tt> indication is converted to a <tt>Z_DATA_ERROR</tt>.
+<p>
+<tt>inflate()</tt> can also return <tt>Z_STREAM_ERROR</tt>, which should not be possible here,
+but could be checked for as noted above for <tt>def()</tt>.  <tt>Z_BUF_ERROR</tt> does not need to be
+checked for here, for the same reasons noted for <tt>def()</tt>.  <tt>Z_STREAM_END</tt> will be
+checked for later.
+<pre><b>
+            ret = inflate(&amp;strm, Z_NO_FLUSH);
+            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+            switch (ret) {
+            case Z_NEED_DICT:
+                ret = Z_DATA_ERROR;     /* and fall through */
+            case Z_DATA_ERROR:
+            case Z_MEM_ERROR:
+                (void)inflateEnd(&amp;strm);
+                return ret;
+            }
+</b></pre>
+The output of <tt>inflate()</tt> is handled identically to that of <tt>deflate()</tt>.
+<pre><b>
+            have = CHUNK - strm.avail_out;
+            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+                (void)inflateEnd(&amp;strm);
+                return Z_ERRNO;
+            }
+</b></pre>
+The inner <tt>do</tt>-loop ends when <tt>inflate()</tt> has no more output as indicated
+by not filling the output buffer, just as for <tt>deflate()</tt>.  In this case, we cannot
+assert that <tt>strm.avail_in</tt> will be zero, since the deflate stream may end before the file
+does.
+<pre><b>
+        } while (strm.avail_out == 0);
+</b></pre><!-- -->
+The outer <tt>do</tt>-loop ends when <tt>inflate()</tt> reports that it has reached the
+end of the input <em>zlib</em> stream, has completed the decompression and integrity
+check, and has provided all of the output.  This is indicated by the <tt>inflate()</tt>
+return value <tt>Z_STREAM_END</tt>.  The inner loop is guaranteed to leave <tt>ret</tt>
+equal to <tt>Z_STREAM_END</tt> if the last chunk of the input file read contained the end
+of the <em>zlib</em> stream.  So if the return value is not <tt>Z_STREAM_END</tt>, the
+loop continues to read more input.
+<pre><b>
+        /* done when inflate() says it's done */
+    } while (ret != Z_STREAM_END);
+</b></pre><!-- -->
+At this point, decompression successfully completed, or we broke out of the loop due to no
+more data being available from the input file.  If the last <tt>inflate()</tt> return value
+is not <tt>Z_STREAM_END</tt>, then the <em>zlib</em> stream was incomplete and a data error
+is returned.  Otherwise, we return with a happy return value.  Of course, <tt>inflateEnd()</tt>
+is called first to avoid a memory leak.
+<pre><b>
+    /* clean up and return */
+    (void)inflateEnd(&amp;strm);
+    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
+}
+</b></pre><!-- -->
+That ends the routines that directly use <em>zlib</em>.  The following routines make this
+a command-line program by running data through the above routines from <tt>stdin</tt> to
+<tt>stdout</tt>, and handling any errors reported by <tt>def()</tt> or <tt>inf()</tt>.
+<p>
+<tt>zerr()</tt> is used to interpret the possible error codes from <tt>def()</tt>
+and <tt>inf()</tt>, as detailed in their comments above, and print out an error message.
+Note that these are only a subset of the possible return values from <tt>deflate()</tt>
+and <tt>inflate()</tt>.
+<pre><b>
+/* report a zlib or i/o error */
+void zerr(int ret)
+{
+    fputs("zpipe: ", stderr);
+    switch (ret) {
+    case Z_ERRNO:
+        if (ferror(stdin))
+            fputs("error reading stdin\n", stderr);
+        if (ferror(stdout))
+            fputs("error writing stdout\n", stderr);
+        break;
+    case Z_STREAM_ERROR:
+        fputs("invalid compression level\n", stderr);
+        break;
+    case Z_DATA_ERROR:
+        fputs("invalid or incomplete deflate data\n", stderr);
+        break;
+    case Z_MEM_ERROR:
+        fputs("out of memory\n", stderr);
+        break;
+    case Z_VERSION_ERROR:
+        fputs("zlib version mismatch!\n", stderr);
+    }
+}
+</b></pre><!-- -->
+Here is the <tt>main()</tt> routine used to test <tt>def()</tt> and <tt>inf()</tt>.  The
+<tt>zpipe</tt> command is simply a compression pipe from <tt>stdin</tt> to <tt>stdout</tt>, if
+no arguments are given, or it is a decompression pipe if <tt>zpipe -d</tt> is used.  If any other
+arguments are provided, no compression or decompression is performed.  Instead a usage
+message is displayed.  Examples are <tt>zpipe < foo.txt > foo.txt.z</tt> to compress, and
+<tt>zpipe -d < foo.txt.z > foo.txt</tt> to decompress.
+<pre><b>
+/* compress or decompress from stdin to stdout */
+int main(int argc, char **argv)
+{
+    int ret;
+
+    /* do compression if no arguments */
+    if (argc == 1) {
+        ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
+        if (ret != Z_OK)
+            zerr(ret);
+        return ret;
+    }
+
+    /* do decompression if -d specified */
+    else if (argc == 2 &amp;&amp; strcmp(argv[1], "-d") == 0) {
+        ret = inf(stdin, stdout);
+        if (ret != Z_OK)
+            zerr(ret);
+        return ret;
+    }
+
+    /* otherwise, report usage */
+    else {
+        fputs("zpipe usage: zpipe [-d] &lt; source &gt; dest\n", stderr);
+        return 1;
+    }
+}
+</b></pre>
+<hr>
+<i>Copyright (c) 2004 by Mark Adler<br>Last modified 13 November 2004</i>
+</body>
+</html>
diff --git a/zlib/examples/zpipe.c b/zlib/examples/zpipe.c
new file mode 100644 (file)
index 0000000..26abb56
--- /dev/null
@@ -0,0 +1,191 @@
+/* zpipe.c: example of proper use of zlib's inflate() and deflate()
+   Not copyrighted -- provided to the public domain
+   Version 1.2  9 November 2004  Mark Adler */
+
+/* Version history:
+   1.0  30 Oct 2004  First version
+   1.1   8 Nov 2004  Add void casting for unused return values
+                     Use switch statement for inflate() return values
+   1.2   9 Nov 2004  Add assertions to document zlib guarantees
+   1.3   6 Apr 2005  Remove incorrect assertion in inf()
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "zlib.h"
+
+#define CHUNK 16384
+
+/* Compress from file source to file dest until EOF on source.
+   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_STREAM_ERROR if an invalid compression
+   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
+   version of the library linked do not match, or Z_ERRNO if there is
+   an error reading or writing the files. */
+int def(FILE *source, FILE *dest, int level)
+{
+    int ret, flush;
+    unsigned have;
+    z_stream strm;
+    char in[CHUNK];
+    char out[CHUNK];
+
+    /* allocate deflate state */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    ret = deflateInit(&strm, level);
+    if (ret != Z_OK)
+        return ret;
+
+    /* compress until end of file */
+    do {
+        strm.avail_in = fread(in, 1, CHUNK, source);
+        if (ferror(source)) {
+            (void)deflateEnd(&strm);
+            return Z_ERRNO;
+        }
+        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
+        strm.next_in = in;
+
+        /* run deflate() on input until output buffer not full, finish
+           compression if all of source has been read in */
+        do {
+            strm.avail_out = CHUNK;
+            strm.next_out = out;
+            ret = deflate(&strm, flush);    /* no bad return value */
+            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+            have = CHUNK - strm.avail_out;
+            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+                (void)deflateEnd(&strm);
+                return Z_ERRNO;
+            }
+        } while (strm.avail_out == 0);
+        assert(strm.avail_in == 0);     /* all input will be used */
+
+        /* done when last data in file processed */
+    } while (flush != Z_FINISH);
+    assert(ret == Z_STREAM_END);        /* stream will be complete */
+
+    /* clean up and return */
+    (void)deflateEnd(&strm);
+    return Z_OK;
+}
+
+/* Decompress from file source to file dest until stream ends or EOF.
+   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_DATA_ERROR if the deflate data is
+   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
+   the version of the library linked do not match, or Z_ERRNO if there
+   is an error reading or writing the files. */
+int inf(FILE *source, FILE *dest)
+{
+    int ret;
+    unsigned have;
+    z_stream strm;
+    char in[CHUNK];
+    char out[CHUNK];
+
+    /* allocate inflate state */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit(&strm);
+    if (ret != Z_OK)
+        return ret;
+
+    /* decompress until deflate stream ends or end of file */
+    do {
+        strm.avail_in = fread(in, 1, CHUNK, source);
+        if (ferror(source)) {
+            (void)inflateEnd(&strm);
+            return Z_ERRNO;
+        }
+        if (strm.avail_in == 0)
+            break;
+        strm.next_in = in;
+
+        /* run inflate() on input until output buffer not full */
+        do {
+            strm.avail_out = CHUNK;
+            strm.next_out = out;
+            ret = inflate(&strm, Z_NO_FLUSH);
+            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+            switch (ret) {
+            case Z_NEED_DICT:
+                ret = Z_DATA_ERROR;     /* and fall through */
+            case Z_DATA_ERROR:
+            case Z_MEM_ERROR:
+                (void)inflateEnd(&strm);
+                return ret;
+            }
+            have = CHUNK - strm.avail_out;
+            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+                (void)inflateEnd(&strm);
+                return Z_ERRNO;
+            }
+        } while (strm.avail_out == 0);
+
+        /* done when inflate() says it's done */
+    } while (ret != Z_STREAM_END);
+
+    /* clean up and return */
+    (void)inflateEnd(&strm);
+    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
+}
+
+/* report a zlib or i/o error */
+void zerr(int ret)
+{
+    fputs("zpipe: ", stderr);
+    switch (ret) {
+    case Z_ERRNO:
+        if (ferror(stdin))
+            fputs("error reading stdin\n", stderr);
+        if (ferror(stdout))
+            fputs("error writing stdout\n", stderr);
+        break;
+    case Z_STREAM_ERROR:
+        fputs("invalid compression level\n", stderr);
+        break;
+    case Z_DATA_ERROR:
+        fputs("invalid or incomplete deflate data\n", stderr);
+        break;
+    case Z_MEM_ERROR:
+        fputs("out of memory\n", stderr);
+        break;
+    case Z_VERSION_ERROR:
+        fputs("zlib version mismatch!\n", stderr);
+    }
+}
+
+/* compress or decompress from stdin to stdout */
+int main(int argc, char **argv)
+{
+    int ret;
+
+    /* do compression if no arguments */
+    if (argc == 1) {
+        ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
+        if (ret != Z_OK)
+            zerr(ret);
+        return ret;
+    }
+
+    /* do decompression if -d specified */
+    else if (argc == 2 && strcmp(argv[1], "-d") == 0) {
+        ret = inf(stdin, stdout);
+        if (ret != Z_OK)
+            zerr(ret);
+        return ret;
+    }
+
+    /* otherwise, report usage */
+    else {
+        fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
+        return 1;
+    }
+}
diff --git a/zlib/examples/zran.c b/zlib/examples/zran.c
new file mode 100644 (file)
index 0000000..8c7717e
--- /dev/null
@@ -0,0 +1,404 @@
+/* zran.c -- example of zlib/gzip stream indexing and random access
+ * Copyright (C) 2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+   Version 1.0  29 May 2005  Mark Adler */
+
+/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary()
+   for random access of a compressed file.  A file containing a zlib or gzip
+   stream is provided on the command line.  The compressed stream is decoded in
+   its entirety, and an index built with access points about every SPAN bytes
+   in the uncompressed output.  The compressed file is left open, and can then
+   be read randomly, having to decompress on the average SPAN/2 uncompressed
+   bytes before getting to the desired block of data.
+
+   An access point can be created at the start of any deflate block, by saving
+   the starting file offset and bit of that block, and the 32K bytes of
+   uncompressed data that precede that block.  Also the uncompressed offset of
+   that block is saved to provide a referece for locating a desired starting
+   point in the uncompressed stream.  build_index() works by decompressing the
+   input zlib or gzip stream a block at a time, and at the end of each block
+   deciding if enough uncompressed data has gone by to justify the creation of
+   a new access point.  If so, that point is saved in a data structure that
+   grows as needed to accommodate the points.
+
+   To use the index, an offset in the uncompressed data is provided, for which
+   the latest accees point at or preceding that offset is located in the index.
+   The input file is positioned to the specified location in the index, and if
+   necessary the first few bits of the compressed data is read from the file.
+   inflate is initialized with those bits and the 32K of uncompressed data, and
+   the decompression then proceeds until the desired offset in the file is
+   reached.  Then the decompression continues to read the desired uncompressed
+   data from the file.
+
+   Another approach would be to generate the index on demand.  In that case,
+   requests for random access reads from the compressed data would try to use
+   the index, but if a read far enough past the end of the index is required,
+   then further index entries would be generated and added.
+
+   There is some fair bit of overhead to starting inflation for the random
+   access, mainly copying the 32K byte dictionary.  So if small pieces of the
+   file are being accessed, it would make sense to implement a cache to hold
+   some lookahead and avoid many calls to extract() for small lengths.
+
+   Another way to build an index would be to use inflateCopy().  That would
+   not be constrained to have access points at block boundaries, but requires
+   more memory per access point, and also cannot be saved to file due to the
+   use of pointers in the state.  The approach here allows for storage of the
+   index in a file.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zlib.h"
+
+#define local static
+
+#define SPAN 1048576L       /* desired distance between access points */
+#define WINSIZE 32768U      /* sliding window size */
+#define CHUNK 16384         /* file input buffer size */
+
+/* access point entry */
+struct point {
+    off_t out;          /* corresponding offset in uncompressed data */
+    off_t in;           /* offset in input file of first full byte */
+    int bits;           /* number of bits (1-7) from byte at in - 1, or 0 */
+    unsigned char window[WINSIZE];  /* preceding 32K of uncompressed data */
+};
+
+/* access point list */
+struct access {
+    int have;           /* number of list entries filled in */
+    int size;           /* number of list entries allocated */
+    struct point *list; /* allocated list */
+};
+
+/* Deallocate an index built by build_index() */
+local void free_index(struct access *index)
+{
+    if (index != NULL) {
+        free(index->list);
+        free(index);
+    }
+}
+
+/* Add an entry to the access point list.  If out of memory, deallocate the
+   existing list and return NULL. */
+local struct access *addpoint(struct access *index, int bits,
+    off_t in, off_t out, unsigned left, unsigned char *window)
+{
+    struct point *next;
+
+    /* if list is empty, create it (start with eight points) */
+    if (index == NULL) {
+        index = malloc(sizeof(struct access));
+        if (index == NULL) return NULL;
+        index->list = malloc(sizeof(struct point) << 3);
+        if (index->list == NULL) {
+            free(index);
+            return NULL;
+        }
+        index->size = 8;
+        index->have = 0;
+    }
+
+    /* if list is full, make it bigger */
+    else if (index->have == index->size) {
+        index->size <<= 1;
+        next = realloc(index->list, sizeof(struct point) * index->size);
+        if (next == NULL) {
+            free_index(index);
+            return NULL;
+        }
+        index->list = next;
+    }
+
+    /* fill in entry and increment how many we have */
+    next = index->list + index->have;
+    next->bits = bits;
+    next->in = in;
+    next->out = out;
+    if (left)
+        memcpy(next->window, window + WINSIZE - left, left);
+    if (left < WINSIZE)
+        memcpy(next->window + left, window, WINSIZE - left);
+    index->have++;
+
+    /* return list, possibly reallocated */
+    return index;
+}
+
+/* Make one entire pass through the compressed stream and build an index, with
+   access points about every span bytes of uncompressed output -- span is
+   chosen to balance the speed of random access against the memory requirements
+   of the list, about 32K bytes per access point.  Note that data after the end
+   of the first zlib or gzip stream in the file is ignored.  build_index()
+   returns the number of access points on success (>= 1), Z_MEM_ERROR for out
+   of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a
+   file read error.  On success, *built points to the resulting index. */
+local int build_index(FILE *in, off_t span, struct access **built)
+{
+    int ret;
+    off_t totin, totout;        /* our own total counters to avoid 4GB limit */
+    off_t last;                 /* totout value of last access point */
+    struct access *index;       /* access points being generated */
+    z_stream strm;
+    unsigned char input[CHUNK];
+    unsigned char window[WINSIZE];
+
+    /* initialize inflate */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit2(&strm, 47);      /* automatic zlib or gzip decoding */
+    if (ret != Z_OK)
+        return ret;
+
+    /* inflate the input, maintain a sliding window, and build an index -- this
+       also validates the integrity of the compressed data using the check
+       information at the end of the gzip or zlib stream */
+    totin = totout = last = 0;
+    index = NULL;               /* will be allocated by first addpoint() */
+    strm.avail_out = 0;
+    do {
+        /* get some compressed data from input file */
+        strm.avail_in = fread(input, 1, CHUNK, in);
+        if (ferror(in)) {
+            ret = Z_ERRNO;
+            goto build_index_error;
+        }
+        if (strm.avail_in == 0) {
+            ret = Z_DATA_ERROR;
+            goto build_index_error;
+        }
+        strm.next_in = input;
+
+        /* process all of that, or until end of stream */
+        do {
+            /* reset sliding window if necessary */
+            if (strm.avail_out == 0) {
+                strm.avail_out = WINSIZE;
+                strm.next_out = window;
+            }
+
+            /* inflate until out of input, output, or at end of block --
+               update the total input and output counters */
+            totin += strm.avail_in;
+            totout += strm.avail_out;
+            ret = inflate(&strm, Z_BLOCK);      /* return at end of block */
+            totin -= strm.avail_in;
+            totout -= strm.avail_out;
+            if (ret == Z_NEED_DICT)
+                ret = Z_DATA_ERROR;
+            if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
+                goto build_index_error;
+            if (ret == Z_STREAM_END)
+                break;
+
+            /* if at end of block, consider adding an index entry (note that if
+               data_type indicates an end-of-block, then all of the
+               uncompressed data from that block has been delivered, and none
+               of the compressed data after that block has been consumed,
+               except for up to seven bits) -- the totout == 0 provides an
+               entry point after the zlib or gzip header, and assures that the
+               index always has at least one access point; we avoid creating an
+               access point after the last block by checking bit 6 of data_type
+             */
+            if ((strm.data_type & 128) && !(strm.data_type & 64) &&
+                (totout == 0 || totout - last > span)) {
+                index = addpoint(index, strm.data_type & 7, totin,
+                                 totout, strm.avail_out, window);
+                if (index == NULL) {
+                    ret = Z_MEM_ERROR;
+                    goto build_index_error;
+                }
+                last = totout;
+            }
+        } while (strm.avail_in != 0);
+    } while (ret != Z_STREAM_END);
+
+    /* clean up and return index (release unused entries in list) */
+    (void)inflateEnd(&strm);
+    index = realloc(index, sizeof(struct point) * index->have);
+    index->size = index->have;
+    *built = index;
+    return index->size;
+
+    /* return error */
+  build_index_error:
+    (void)inflateEnd(&strm);
+    if (index != NULL)
+        free_index(index);
+    return ret;
+}
+
+/* Use the index to read len bytes from offset into buf, return bytes read or
+   negative for error (Z_DATA_ERROR or Z_MEM_ERROR).  If data is requested past
+   the end of the uncompressed data, then extract() will return a value less
+   than len, indicating how much as actually read into buf.  This function
+   should not return a data error unless the file was modified since the index
+   was generated.  extract() may also return Z_ERRNO if there is an error on
+   reading or seeking the input file. */
+local int extract(FILE *in, struct access *index, off_t offset,
+                  unsigned char *buf, int len)
+{
+    int ret, skip;
+    z_stream strm;
+    struct point *here;
+    unsigned char input[CHUNK];
+    unsigned char discard[WINSIZE];
+
+    /* proceed only if something reasonable to do */
+    if (len < 0)
+        return 0;
+
+    /* find where in stream to start */
+    here = index->list;
+    ret = index->have;
+    while (--ret && here[1].out <= offset)
+        here++;
+
+    /* initialize file and inflate state to start there */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit2(&strm, -15);         /* raw inflate */
+    if (ret != Z_OK)
+        return ret;
+    ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
+    if (ret == -1)
+        goto extract_ret;
+    if (here->bits) {
+        ret = getc(in);
+        if (ret == -1) {
+            ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;
+            goto extract_ret;
+        }
+        (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits));
+    }
+    (void)inflateSetDictionary(&strm, here->window, WINSIZE);
+
+    /* skip uncompressed bytes until offset reached, then satisfy request */
+    offset -= here->out;
+    strm.avail_in = 0;
+    skip = 1;                               /* while skipping to offset */
+    do {
+        /* define where to put uncompressed data, and how much */
+        if (offset == 0 && skip) {          /* at offset now */
+            strm.avail_out = len;
+            strm.next_out = buf;
+            skip = 0;                       /* only do this once */
+        }
+        if (offset > WINSIZE) {             /* skip WINSIZE bytes */
+            strm.avail_out = WINSIZE;
+            strm.next_out = discard;
+            offset -= WINSIZE;
+        }
+        else if (offset != 0) {             /* last skip */
+            strm.avail_out = (unsigned)offset;
+            strm.next_out = discard;
+            offset = 0;
+        }
+
+        /* uncompress until avail_out filled, or end of stream */
+        do {
+            if (strm.avail_in == 0) {
+                strm.avail_in = fread(input, 1, CHUNK, in);
+                if (ferror(in)) {
+                    ret = Z_ERRNO;
+                    goto extract_ret;
+                }
+                if (strm.avail_in == 0) {
+                    ret = Z_DATA_ERROR;
+                    goto extract_ret;
+                }
+                strm.next_in = input;
+            }
+            ret = inflate(&strm, Z_NO_FLUSH);       /* normal inflate */
+            if (ret == Z_NEED_DICT)
+                ret = Z_DATA_ERROR;
+            if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
+                goto extract_ret;
+            if (ret == Z_STREAM_END)
+                break;
+        } while (strm.avail_out != 0);
+
+        /* if reach end of stream, then don't keep trying to get more */
+        if (ret == Z_STREAM_END)
+            break;
+
+        /* do until offset reached and requested data read, or stream ends */
+    } while (skip);
+
+    /* compute number of uncompressed bytes read after offset */
+    ret = skip ? 0 : len - strm.avail_out;
+
+    /* clean up and return bytes read or error */
+  extract_ret:
+    (void)inflateEnd(&strm);
+    return ret;
+}
+
+/* Demonstrate the use of build_index() and extract() by processing the file
+   provided on the command line, and the extracting 16K from about 2/3rds of
+   the way through the uncompressed output, and writing that to stdout. */
+int main(int argc, char **argv)
+{
+    int len;
+    off_t offset;
+    FILE *in;
+    struct access *index;
+    unsigned char buf[CHUNK];
+
+    /* open input file */
+    if (argc != 2) {
+        fprintf(stderr, "usage: zran file.gz\n");
+        return 1;
+    }
+    in = fopen(argv[1], "rb");
+    if (in == NULL) {
+        fprintf(stderr, "zran: could not open %s for reading\n", argv[1]);
+        return 1;
+    }
+
+    /* build index */
+    len = build_index(in, SPAN, &index);
+    if (len < 0) {
+        fclose(in);
+        switch (len) {
+        case Z_MEM_ERROR:
+            fprintf(stderr, "zran: out of memory\n");
+            break;
+        case Z_DATA_ERROR:
+            fprintf(stderr, "zran: compressed data error in %s\n", argv[1]);
+            break;
+        case Z_ERRNO:
+            fprintf(stderr, "zran: read error on %s\n", argv[1]);
+            break;
+        default:
+            fprintf(stderr, "zran: error %d while building index\n", len);
+        }
+        return 1;
+    }
+    fprintf(stderr, "zran: built index with %d access points\n", len);
+
+    /* use index by reading some bytes from an arbitrary offset */
+    offset = (index->list[index->have - 1].out << 1) / 3;
+    len = extract(in, index, offset, buf, CHUNK);
+    if (len < 0)
+        fprintf(stderr, "zran: extraction failed: %s error\n",
+                len == Z_MEM_ERROR ? "out of memory" : "input corrupted");
+    else {
+        fwrite(buf, 1, len, stdout);
+        fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset);
+    }
+
+    /* clean up and exit */
+    free_index(index);
+    fclose(in);
+    return 0;
+}
index 556953e..681a5c9 100644 (file)
@@ -1,5 +1,5 @@
 /* gzio.c -- IO on .gz files
- * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  *
  * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
@@ -11,7 +11,7 @@
 
 #include "zutil.h"
 
-#ifdef NO_DEFLATE       /* for compatiblity with old definition */
+#ifdef NO_DEFLATE       /* for compatibility with old definition */
 #  define NO_GZCOMPRESS
 #endif
 
@@ -234,7 +234,7 @@ gzFile ZEXPORT gzopen (const char *path, const char *mode)
 */
 gzFile ZEXPORT gzdopen (int fd, const char *mode)
 {
-    char name[20];
+    char name[46];      /* allow for up to 128-bit integers */
 
     if (fd < 0) return (gzFile)Z_NULL;
     sprintf(name, "<fd:%d>", fd); /* for debugging */
@@ -274,7 +274,7 @@ local int get_byte(gz_stream *s)
     if (s->z_eof) return EOF;
     if (s->stream.avail_in == 0) {
         errno = 0;
-        s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+        s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
         if (s->stream.avail_in == 0) {
             s->z_eof = 1;
             if (ferror(s->file)) s->z_err = Z_ERRNO;
@@ -309,7 +309,7 @@ local void check_header(gz_stream *s)
     if (len < 2) {
         if (len) s->inbuf[0] = s->stream.next_in[0];
         errno = 0;
-        len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
+        len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
         if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
         s->stream.avail_in += len;
         s->stream.next_in = s->inbuf;
@@ -420,6 +420,7 @@ int ZEXPORT gzread (gzFile file, voidp buf, unsigned len)
         s->stream.avail_out--;
         s->back = EOF;
         s->out++;
+        start++;
         if (s->last) {
             s->z_err = Z_STREAM_END;
             return 1;
@@ -441,8 +442,8 @@ int ZEXPORT gzread (gzFile file, voidp buf, unsigned len)
                 s->stream.avail_in  -= n;
             }
             if (s->stream.avail_out > 0) {
-                s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
-                                             s->file);
+                s->stream.avail_out -=
+                    (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
             }
             len -= s->stream.avail_out;
             s->in  += len;
@@ -453,17 +454,13 @@ int ZEXPORT gzread (gzFile file, voidp buf, unsigned len)
         if (s->stream.avail_in == 0 && !s->z_eof) {
 
             errno = 0;
-            s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+            s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
             if (s->stream.avail_in == 0) {
                 s->z_eof = 1;
                 if (ferror(s->file)) {
                     s->z_err = Z_ERRNO;
                     break;
                 }
-                if (feof(s->file)) {        /* avoid error for empty file */
-                    s->z_err = Z_STREAM_END;
-                    break;
-                }
             }
             s->stream.next_in = s->inbuf;
         }
@@ -497,6 +494,9 @@ int ZEXPORT gzread (gzFile file, voidp buf, unsigned len)
     }
     s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
 
+    if (len == s->stream.avail_out &&
+        (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
+        return -1;
     return (int)(len - s->stream.avail_out);
 }
 
@@ -630,9 +630,8 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
 }
 #else /* not ANSI C */
 
-int ZEXPORTVA gzprintf (gzFile file, const char *format,
-    int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10,
-        int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20)
+int ZEXPORTVA gzprintf (gzFile file, const char *format, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10,
+                       int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20)
 {
     char buf[Z_PRINTF_BUFSIZE];
     int len;
@@ -868,7 +867,7 @@ z_off_t ZEXPORT gztell (gzFile file)
      Returns 1 when EOF has previously been detected reading the given
    input stream, otherwise zero.
 */
-int ZEXPORT gzeof (gzFile file)
+int ZEXPORT gzeof ( gzFile file)
 {
     gz_stream *s = (gz_stream*)file;
 
@@ -882,6 +881,17 @@ int ZEXPORT gzeof (gzFile file)
 }
 
 /* ===========================================================================
+     Returns 1 if reading and doing so transparently, otherwise zero.
+*/
+int ZEXPORT gzdirect (gzFile file)
+{
+    gz_stream *s = (gz_stream*)file;
+
+    if (s == NULL || s->mode != 'r') return 0;
+    return s->transparent;
+}
+
+/* ===========================================================================
    Outputs a long in LSB order to the given file
 */
 local void putLong (FILE *file, uLong x)
@@ -916,7 +926,6 @@ local uLong getLong (gz_stream *s)
 */
 int ZEXPORT gzclose (gzFile file)
 {
-    int err;
     gz_stream *s = (gz_stream*)file;
 
     if (s == NULL) return Z_STREAM_ERROR;
@@ -925,8 +934,8 @@ int ZEXPORT gzclose (gzFile file)
 #ifdef NO_GZCOMPRESS
         return Z_STREAM_ERROR;
 #else
-        err = do_flush (file, Z_FINISH);
-        if (err != Z_OK) return destroy((gz_stream*)file);
+        if (do_flush (file, Z_FINISH) != Z_OK)
+            return destroy((gz_stream*)file);
 
         putLong (s->file, s->crc);
         putLong (s->file, (uLong)(s->in & 0xffffffff));
@@ -935,10 +944,16 @@ int ZEXPORT gzclose (gzFile file)
     return destroy((gz_stream*)file);
 }
 
+#ifdef STDC
+#  define zstrerror(errnum) strerror(errnum)
+#else
+#  define zstrerror(errnum) ""
+#endif
+
 /* ===========================================================================
-     Returns the error message for the last error which occured on the
+     Returns the error message for the last error which occurred on the
    given compressed file. errnum is set to zlib error number. If an
-   error occured in the file system and not in the compression library,
+   error occurred in the file system and not in the compression library,
    errnum is set to Z_ERRNO and the application may consult errno
    to get the exact error code.
 */
index 180f0e7..f3c842b 100644 (file)
@@ -1,5 +1,5 @@
 /* infback.c -- inflate using a call-back interface
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2005 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -26,7 +26,7 @@ local void fixedtables OF((struct inflate_state FAR *state))
    windowBits is in the range 8..15, and window is a user-supplied
    window and output buffer that is 2**windowBits bytes.
  */
-int ZEXPORT inflateBackInit_(z_stream FAR *strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)
+int ZEXPORT inflateBackInit_(z_streamstrm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)
 {
     struct inflate_state FAR *state;
 
@@ -46,7 +46,8 @@ int ZEXPORT inflateBackInit_(z_stream FAR *strm, int windowBits, unsigned char F
                                                sizeof(struct inflate_state));
     if (state == Z_NULL) return Z_MEM_ERROR;
     Tracev((stderr, "inflate: allocated\n"));
-    strm->state = (voidpf)state;
+    strm->state = (struct internal_state FAR *)state;
+    state->dmax = 32768U;
     state->wbits = windowBits;
     state->wsize = 1U << windowBits;
     state->window = window;
@@ -232,7 +233,7 @@ local void fixedtables(struct inflate_state FAR *state)
    inflateBack() can also return Z_STREAM_ERROR if the input parameters
    are not correct, i.e. strm is Z_NULL or the state was not initialized.
  */
-int ZEXPORT inflateBack(z_stream FAR *strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)
+int ZEXPORT inflateBack(z_streamstrm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)
 {
     struct inflate_state FAR *state;
     unsigned char FAR *next;    /* next input */
@@ -600,7 +601,7 @@ int ZEXPORT inflateBack(z_stream FAR *strm, in_func in, void FAR *in_desc, out_f
     return ret;
 }
 
-int ZEXPORT inflateBackEnd(z_stream FAR *strm)
+int ZEXPORT inflateBackEnd(z_streamstrm)
 {
     if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
         return Z_STREAM_ERROR;
index 6fa72db..9ad5b82 100644 (file)
@@ -1,5 +1,5 @@
 /* inflate.c -- zlib decompression
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2005 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -116,8 +116,11 @@ int ZEXPORT inflateReset(z_streamp strm)
     state->mode = HEAD;
     state->last = 0;
     state->havedict = 0;
+    state->dmax = 32768U;
+    state->head = Z_NULL;
     state->wsize = 0;
     state->whave = 0;
+    state->write = 0;
     state->hold = 0;
     state->bits = 0;
     state->lencode = state->distcode = state->next = state->codes;
@@ -125,6 +128,19 @@ int ZEXPORT inflateReset(z_streamp strm)
     return Z_OK;
 }
 
+int ZEXPORT inflatePrime(z_streamp strm, int bits, int value)
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+    value &= (1L << bits) - 1;
+    state->hold += value << state->bits;
+    state->bits += bits;
+    return Z_OK;
+}
+
 int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size)
 {
     struct inflate_state FAR *state;
@@ -143,7 +159,7 @@ int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, i
             ZALLOC(strm, 1, sizeof(struct inflate_state));
     if (state == Z_NULL) return Z_MEM_ERROR;
     Tracev((stderr, "inflate: allocated\n"));
-    strm->state = (voidpf)state;
+    strm->state = (struct internal_state FAR *)state;
     if (windowBits < 0) {
         state->wrap = 0;
         windowBits = -windowBits;
@@ -573,6 +589,8 @@ int ZEXPORT inflate(z_streamp strm, int flush)
                 break;
             }
             state->flags = 0;           /* expect zlib header */
+            if (state->head != Z_NULL)
+                state->head->done = -1;
             if (!(state->wrap & 1) ||   /* check if zlib header allowed */
 #else
             if (
@@ -588,11 +606,13 @@ int ZEXPORT inflate(z_streamp strm, int flush)
                 break;
             }
             DROPBITS(4);
-            if (BITS(4) + 8 > state->wbits) {
+            len = BITS(4) + 8;
+            if (len > state->wbits) {
                 strm->msg = (char *)"invalid window size";
                 state->mode = BAD;
                 break;
             }
+            state->dmax = 1U << len;
             Tracev((stderr, "inflate:   zlib header ok\n"));
             strm->adler = state->check = adler32(0L, Z_NULL, 0);
             state->mode = hold & 0x200 ? DICTID : TYPE;
@@ -612,16 +632,24 @@ int ZEXPORT inflate(z_streamp strm, int flush)
                 state->mode = BAD;
                 break;
             }
+            if (state->head != Z_NULL)
+                state->head->text = (int)((hold >> 8) & 1);
             if (state->flags & 0x0200) CRC2(state->check, hold);
             INITBITS();
             state->mode = TIME;
         case TIME:
             NEEDBITS(32);
+            if (state->head != Z_NULL)
+                state->head->time = hold;
             if (state->flags & 0x0200) CRC4(state->check, hold);
             INITBITS();
             state->mode = OS;
         case OS:
             NEEDBITS(16);
+            if (state->head != Z_NULL) {
+                state->head->xflags = (int)(hold & 0xff);
+                state->head->os = (int)(hold >> 8);
+            }
             if (state->flags & 0x0200) CRC2(state->check, hold);
             INITBITS();
             state->mode = EXLEN;
@@ -629,15 +657,26 @@ int ZEXPORT inflate(z_streamp strm, int flush)
             if (state->flags & 0x0400) {
                 NEEDBITS(16);
                 state->length = (unsigned)(hold);
+                if (state->head != Z_NULL)
+                    state->head->extra_len = (unsigned)hold;
                 if (state->flags & 0x0200) CRC2(state->check, hold);
                 INITBITS();
             }
+            else if (state->head != Z_NULL)
+                state->head->extra = Z_NULL;
             state->mode = EXTRA;
         case EXTRA:
             if (state->flags & 0x0400) {
                 copy = state->length;
                 if (copy > have) copy = have;
                 if (copy) {
+                    if (state->head != Z_NULL &&
+                        state->head->extra != Z_NULL) {
+                        len = state->head->extra_len - state->length;
+                        zmemcpy(state->head->extra + len, next,
+                                len + copy > state->head->extra_max ?
+                                state->head->extra_max - len : copy);
+                    }
                     if (state->flags & 0x0200)
                         state->check = crc32(state->check, next, copy);
                     have -= copy;
@@ -646,6 +685,7 @@ int ZEXPORT inflate(z_streamp strm, int flush)
                 }
                 if (state->length) goto inf_leave;
             }
+            state->length = 0;
             state->mode = NAME;
         case NAME:
             if (state->flags & 0x0800) {
@@ -653,13 +693,20 @@ int ZEXPORT inflate(z_streamp strm, int flush)
                 copy = 0;
                 do {
                     len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->name != Z_NULL &&
+                            state->length < state->head->name_max)
+                        state->head->name[state->length++] = len;
                 } while (len && copy < have);
-                if (state->flags & 0x02000)
+                if (state->flags & 0x0200)
                     state->check = crc32(state->check, next, copy);
                 have -= copy;
                 next += copy;
                 if (len) goto inf_leave;
             }
+            else if (state->head != Z_NULL)
+                state->head->name = Z_NULL;
+            state->length = 0;
             state->mode = COMMENT;
         case COMMENT:
             if (state->flags & 0x1000) {
@@ -667,13 +714,19 @@ int ZEXPORT inflate(z_streamp strm, int flush)
                 copy = 0;
                 do {
                     len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->comment != Z_NULL &&
+                            state->length < state->head->comm_max)
+                        state->head->comment[state->length++] = len;
                 } while (len && copy < have);
-                if (state->flags & 0x02000)
+                if (state->flags & 0x0200)
                     state->check = crc32(state->check, next, copy);
                 have -= copy;
                 next += copy;
                 if (len) goto inf_leave;
             }
+            else if (state->head != Z_NULL)
+                state->head->comment = Z_NULL;
             state->mode = HCRC;
         case HCRC:
             if (state->flags & 0x0200) {
@@ -685,6 +738,10 @@ int ZEXPORT inflate(z_streamp strm, int flush)
                 }
                 INITBITS();
             }
+            if (state->head != Z_NULL) {
+                state->head->hcrc = (int)((state->flags >> 9) & 1);
+                state->head->done = 1;
+            }
             strm->adler = state->check = crc32(0L, Z_NULL, 0);
             state->mode = TYPE;
             break;
@@ -960,6 +1017,13 @@ int ZEXPORT inflate(z_streamp strm, int flush)
                 state->offset += BITS(state->extra);
                 DROPBITS(state->extra);
             }
+#ifdef INFLATE_STRICT
+            if (state->offset > state->dmax) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+#endif
             if (state->offset > state->whave + out - left) {
                 strm->msg = (char *)"invalid distance too far back";
                 state->mode = BAD;
@@ -1097,12 +1161,16 @@ int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt d
     /* check state */
     if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
     state = (struct inflate_state FAR *)strm->state;
-    if (state->mode != DICT) return Z_STREAM_ERROR;
+    if (state->wrap != 0 && state->mode != DICT)
+        return Z_STREAM_ERROR;
 
     /* check for correct dictionary id */
-    id = adler32(0L, Z_NULL, 0);
-    id = adler32(id, dictionary, dictLength);
-    if (id != state->check) return Z_DATA_ERROR;
+    if (state->mode == DICT) {
+        id = adler32(0L, Z_NULL, 0);
+        id = adler32(id, dictionary, dictLength);
+        if (id != state->check)
+            return Z_DATA_ERROR;
+    }
 
     /* copy dictionary to window */
     if (updatewindow(strm, strm->avail_out)) {
@@ -1124,6 +1192,21 @@ int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt d
     return Z_OK;
 }
 
+int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head)
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+    /* save header structure */
+    state->head = head;
+    head->done = 0;
+    return Z_OK;
+}
+
 /*
    Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
    or when out of input.  When called, *have is the number of pattern bytes
@@ -1219,6 +1302,7 @@ int ZEXPORT inflateCopy(z_streamp dest, z_streamp source)
     struct inflate_state FAR *state;
     struct inflate_state FAR *copy;
     unsigned char FAR *window;
+    unsigned wsize;
 
     /* check input */
     if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
@@ -1241,14 +1325,19 @@ int ZEXPORT inflateCopy(z_streamp dest, z_streamp source)
     }
 
     /* copy state */
-    *dest = *source;
-    *copy = *state;
-    copy->lencode = copy->codes + (state->lencode - state->codes);
-    copy->distcode = copy->codes + (state->distcode - state->codes);
+    zmemcpy(dest, source, sizeof(z_stream));
+    zmemcpy(copy, state, sizeof(struct inflate_state));
+    if (state->lencode >= state->codes &&
+        state->lencode <= state->codes + ENOUGH - 1) {
+        copy->lencode = copy->codes + (state->lencode - state->codes);
+        copy->distcode = copy->codes + (state->distcode - state->codes);
+    }
     copy->next = copy->codes + (state->next - state->codes);
-    if (window != Z_NULL)
-        zmemcpy(window, state->window, 1U << state->wbits);
+    if (window != Z_NULL) {
+        wsize = 1U << state->wbits;
+        zmemcpy(window, state->window, wsize);
+    }
     copy->window = window;
-    dest->state = (voidpf)copy;
+    dest->state = (struct internal_state FAR *)copy;
     return Z_OK;
 }
index e9a89aa..b9fa62f 100644 (file)
@@ -1,5 +1,5 @@
 /* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2004 Mark Adler
+ * Copyright (C) 1995-2005 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  *
  * - add https://svn.uhulinux.hu/packages/dev/zlib/patches/02-rsync.patch.
@@ -12,7 +12,7 @@
 #define MAXBITS 15
 
 const char inflate_copyright[] =
-   " inflate 1.2.2.f-rpm-rsync Copyright 1995-2004 Mark Adler ";
+   " inflate 1.2.2.f-rpm-rsync Copyright 1995-2005 Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -59,7 +59,7 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code
         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
     static const unsigned short lext[31] = { /* Length codes 257..285 extra */
         16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
-        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 199};
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 206, 69};
     static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
         257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
@@ -131,7 +131,7 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code
         left -= count[len];
         if (left < 0) return -1;        /* over-subscribed */
     }
-    if (left > 0 && (type == CODES || (codes - count[0] != 1)))
+    if (left > 0 && (type == CODES || max != 1))
         return -1;                      /* incomplete set */
 
     /* generate offsets into symbol table for each length for sorting */
@@ -229,6 +229,7 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code
         /* replicate for those indices with low len bits equal to huff */
         incr = 1U << (len - drop);
         fill = 1U << curr;
+        min = fill;                 /* save offset to next table */
         do {
             fill -= incr;
             next[(huff >> drop) + fill] = this;
@@ -259,7 +260,7 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code
                 drop = root;
 
             /* increment past last table */
-            next += 1U << curr;
+            next += min;            /* here min is 1 << curr */
 
             /* determine length of next table */
             curr = len - drop;
index 1bfb4d9..735583b 100644 (file)
@@ -1,5 +1,5 @@
 /* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2005 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -36,12 +36,12 @@ typedef struct {
  */
 
 /* Maximum size of dynamic tree.  The maximum found in a long but non-
-   exhaustive search was 1004 code structures (850 for length/literals
-   and 154 for distances, the latter actually the result of an
+   exhaustive search was 1444 code structures (852 for length/literals
+   and 592 for distances, the latter actually the result of an
    exhaustive search).  The true maximum is not known, but the value
    below is more than safe. */
-#define ENOUGH 1440
-#define MAXD 154
+#define ENOUGH 2048
+#define MAXD 592
 
 /* Type of code to build for inftable() */
 typedef enum {
diff --git a/zlib/make_vms.com b/zlib/make_vms.com
new file mode 100644 (file)
index 0000000..c3e5b58
--- /dev/null
@@ -0,0 +1,461 @@
+$! make libz under VMS written by 
+$! Martin P.J. Zinser 
+$! <zinser@zinser.no-ip.info or zinser@sysdev.deutsche-boerse.com>
+$!
+$ on error then goto err_exit
+$!
+$!
+$! Just some general constants...
+$!
+$ true  = 1
+$ false = 0
+$ tmpnam = "temp_" + f$getjpi("","pid")
+$ SAY = "WRITE SYS$OUTPUT"
+$!
+$! Setup variables holding "config" information
+$!
+$ Make     = ""
+$ name     = "Zlib"
+$ version  = "?.?.?"
+$ v_string = "ZLIB_VERSION"
+$ v_file   = "zlib.h"
+$ ccopt    = ""
+$ lopts    = ""
+$ linkonly = false
+$ optfile  = name + ".opt"
+$ its_decc = false
+$ its_vaxc = false
+$ its_gnuc = false
+$ axp      = f$getsyi("HW_MODEL").ge.1024
+$ s_case   = false
+$! Check for MMK/MMS
+$!
+$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS"
+$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK"
+$!
+$!
+$ gosub find_version
+$!
+$ gosub check_opts
+$!
+$! Look for the compiler used
+$!
+$ gosub check_compiler
+$ if its_decc
+$ then
+$   ccopt = "/prefix=all" + ccopt
+$   if f$trnlnm("SYS") .eqs. ""
+$   then
+$     if axp 
+$     then 
+$       define sys sys$library:
+$     else
+$       ccopt = "/decc" + ccopt
+$       define sys decc$library_include:
+$     endif
+$   endif
+$ endif
+$ if its_vaxc .or. its_gnuc
+$ then
+$    if f$trnlnm("SYS").eqs."" then define sys sys$library:
+$ endif  
+$!
+$! Build the thing plain or with mms
+$!
+$ write sys$output "Compiling Zlib sources ..."
+$ if make.eqs.""
+$  then
+$   dele example.obj;*,minigzip.obj;*
+$   CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" -
+                adler32.c zlib.h zconf.h
+$   CALL MAKE compress.OBJ "CC ''CCOPT' compress" -
+                compress.c zlib.h zconf.h
+$   CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" -
+                crc32.c zlib.h zconf.h
+$   CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" -
+                deflate.c deflate.h zutil.h zlib.h zconf.h
+$   CALL MAKE gzio.OBJ "CC ''CCOPT' gzio" -
+                gzio.c zutil.h zlib.h zconf.h
+$   CALL MAKE infback.OBJ "CC ''CCOPT' infback" -
+                infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h
+$   CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" -
+                inffast.c zutil.h zlib.h zconf.h inffast.h
+$   CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" -
+                inflate.c zutil.h zlib.h zconf.h infblock.h
+$   CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" -
+                inftrees.c zutil.h zlib.h zconf.h inftrees.h
+$   CALL MAKE trees.OBJ "CC ''CCOPT' trees" -
+                trees.c deflate.h zutil.h zlib.h zconf.h
+$   CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" -
+                uncompr.c zlib.h zconf.h
+$   CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" -
+                zutil.c zutil.h zlib.h zconf.h
+$   write sys$output "Building Zlib ..."
+$   CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ
+$   write sys$output "Building example..."
+$   CALL MAKE example.OBJ "CC ''CCOPT' example" -
+                example.c zlib.h zconf.h
+$   call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb
+$   if f$search("x11vms:xvmsutils.olb") .nes. ""
+$   then
+$     write sys$output "Building minigzip..."
+$     CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" -
+                minigzip.c zlib.h zconf.h
+$     call make minigzip.exe - 
+                "LINK minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib" - 
+                minigzip.obj libz.olb
+$   endif
+$  else
+$   gosub crea_mms
+$   SAY "Make ''name' ''version' with ''Make' "
+$   'make'
+$  endif
+$!
+$! Alpha gets a shareable image
+$!
+$ If axp
+$ Then
+$   gosub crea_olist
+$   write sys$output "Creating libzshr.exe"
+$   call anal_obj_axp modules.opt _link.opt
+$   if s_case 
+$   then
+$      open/append optf modules.opt
+$      write optf "case_sensitive=YES"
+$      close optf
+$   endif
+$   LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,_link.opt/opt
+$ endif
+$ write sys$output "Zlib build completed"
+$ exit
+$CC_ERR:
+$ write sys$output "C compiler required to build ''name'"
+$ goto err_exit
+$ERR_EXIT:
+$ set message/facil/ident/sever/text
+$ write sys$output "Exiting..."
+$ exit 2
+$!
+$!
+$MAKE: SUBROUTINE   !SUBROUTINE TO CHECK DEPENDENCIES
+$ V = 'F$Verify(0)
+$! P1 = What we are trying to make
+$! P2 = Command to make it
+$! P3 - P8  What it depends on
+$
+$ If F$Search(P1) .Eqs. "" Then Goto Makeit
+$ Time = F$CvTime(F$File(P1,"RDT"))
+$arg=3
+$Loop:
+$       Argument = P'arg
+$       If Argument .Eqs. "" Then Goto Exit
+$       El=0
+$Loop2:
+$       File = F$Element(El," ",Argument)
+$       If File .Eqs. " " Then Goto Endl
+$       AFile = ""
+$Loop3:
+$       OFile = AFile
+$       AFile = F$Search(File)
+$       If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl
+$       If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit
+$       Goto Loop3
+$NextEL:
+$       El = El + 1
+$       Goto Loop2
+$EndL:
+$ arg=arg+1
+$ If arg .Le. 8 Then Goto Loop
+$ Goto Exit
+$
+$Makeit:
+$ VV=F$VERIFY(0)
+$ write sys$output P2
+$ 'P2
+$ VV='F$Verify(VV)
+$Exit:
+$ If V Then Set Verify
+$ENDSUBROUTINE
+$!------------------------------------------------------------------------------
+$!
+$! Check command line options and set symbols accordingly
+$!
+$ CHECK_OPTS:
+$ i = 1
+$ OPT_LOOP:
+$ if i .lt. 9
+$ then
+$   cparm = f$edit(p'i',"upcase")
+$   if cparm .eqs. "DEBUG"
+$   then
+$     ccopt = ccopt + "/noopt/deb"
+$     lopts = lopts + "/deb"
+$   endif
+$   if f$locate("CCOPT=",cparm) .lt. f$length(cparm)
+$   then
+$     start = f$locate("=",cparm) + 1
+$     len   = f$length(cparm) - start
+$     ccopt = ccopt + f$extract(start,len,cparm)
+$     if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) -
+         then s_case = true
+$   endif
+$   if cparm .eqs. "LINK" then linkonly = true
+$   if f$locate("LOPTS=",cparm) .lt. f$length(cparm) 
+$   then
+$     start = f$locate("=",cparm) + 1
+$     len   = f$length(cparm) - start
+$     lopts = lopts + f$extract(start,len,cparm)
+$   endif
+$   if f$locate("CC=",cparm) .lt. f$length(cparm) 
+$   then
+$     start  = f$locate("=",cparm) + 1
+$     len    = f$length(cparm) - start
+$     cc_com = f$extract(start,len,cparm)
+      if (cc_com .nes. "DECC") .and. - 
+         (cc_com .nes. "VAXC") .and. - 
+        (cc_com .nes. "GNUC")
+$     then
+$       write sys$output "Unsupported compiler choice ''cc_com' ignored"
+$       write sys$output "Use DECC, VAXC, or GNUC instead"
+$     else 
+$      if cc_com .eqs. "DECC" then its_decc = true   
+$      if cc_com .eqs. "VAXC" then its_vaxc = true   
+$      if cc_com .eqs. "GNUC" then its_gnuc = true   
+$     endif 
+$   endif
+$   if f$locate("MAKE=",cparm) .lt. f$length(cparm) 
+$   then
+$     start  = f$locate("=",cparm) + 1
+$     len    = f$length(cparm) - start
+$     mmks = f$extract(start,len,cparm)
+$     if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS") 
+$     then
+$       make = mmks
+$     else 
+$       write sys$output "Unsupported make choice ''mmks' ignored"
+$       write sys$output "Use MMK or MMS instead"
+$     endif 
+$   endif
+$   i = i + 1
+$   goto opt_loop
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Look for the compiler used 
+$!
+$CHECK_COMPILER:
+$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc))
+$ then
+$   its_decc = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE") .nes. "")
+$   its_vaxc = .not. its_decc .and. (F$Search("SYS$System:VAXC.Exe") .nes. "")
+$   its_gnuc = .not. (its_decc .or. its_vaxc) .and. (f$trnlnm("gnu_cc") .nes. "")
+$ endif
+$!
+$! Exit if no compiler available
+$!
+$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) 
+$ then goto CC_ERR
+$ else
+$   if its_decc then write sys$output "CC compiler check ... Compaq C"
+$   if its_vaxc then write sys$output "CC compiler check ... VAX C"
+$   if its_gnuc then write sys$output "CC compiler check ... GNU C"
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! If MMS/MMK are available dump out the descrip.mms if required
+$!
+$CREA_MMS:
+$ write sys$output "Creating descrip.mms..."
+$ create descrip.mms
+$ open/append out descrip.mms
+$ copy sys$input: out
+$ deck
+# descrip.mms: MMS description file for building zlib on VMS
+# written by Martin P.J. Zinser 
+# <zinser@zinser.no-ip.info or zinser@sysdev.deutsche-boerse.com>
+
+OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj, infback.obj\
+       deflate.obj, trees.obj, zutil.obj, inflate.obj, \
+       inftrees.obj, inffast.obj
+
+$ eod
+$ write out "CFLAGS=", ccopt 
+$ write out "LOPTS=", lopts
+$ copy sys$input: out
+$ deck
+
+all : example.exe minigzip.exe libz.olb
+        @ write sys$output " Example applications available"
+
+libz.olb : libz.olb($(OBJS))
+       @ write sys$output " libz available"
+
+example.exe : example.obj libz.olb
+              link $(LOPTS) example,libz.olb/lib
+
+minigzip.exe : minigzip.obj libz.olb
+              link $(LOPTS) minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib
+
+clean : 
+       delete *.obj;*,libz.olb;*,*.opt;*,*.exe;*
+
+
+# Other dependencies.
+adler32.obj  : adler32.c zutil.h zlib.h zconf.h
+compress.obj : compress.c zlib.h zconf.h
+crc32.obj    : crc32.c zutil.h zlib.h zconf.h
+deflate.obj  : deflate.c deflate.h zutil.h zlib.h zconf.h
+example.obj  : example.c zlib.h zconf.h
+gzio.obj     : gzio.c zutil.h zlib.h zconf.h
+inffast.obj  : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h
+inflate.obj  : inflate.c zutil.h zlib.h zconf.h 
+inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h
+minigzip.obj : minigzip.c zlib.h zconf.h
+trees.obj    : trees.c deflate.h zutil.h zlib.h zconf.h
+uncompr.obj  : uncompr.c zlib.h zconf.h
+zutil.obj    : zutil.c zutil.h zlib.h zconf.h
+infback.obj  : infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h
+$ eod
+$ close out
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Read list of core library sources from makefile.in and create options
+$! needed to build shareable image
+$!
+$CREA_OLIST:
+$ open/read min makefile.in
+$ open/write mod modules.opt
+$ src_check = "OBJS ="
+$MRLOOP:
+$ read/end=mrdone min rec
+$ if (f$extract(0,6,rec) .nes. src_check) then goto mrloop
+$ rec = rec - src_check 
+$ gosub extra_filnam
+$ if (f$element(1,"\",rec) .eqs. "\") then goto mrdone
+$MRSLOOP:
+$ read/end=mrdone min rec
+$ gosub extra_filnam 
+$ if (f$element(1,"\",rec) .nes. "\") then goto mrsloop
+$MRDONE:
+$ close min
+$ close mod
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Take record extracted in crea_olist and split it into single filenames
+$!
+$EXTRA_FILNAM:
+$ myrec = f$edit(rec - "\", "trim,compress")
+$ i = 0
+$FELOOP:
+$ srcfil = f$element(i," ", myrec)
+$ if (srcfil .nes. " ")
+$ then
+$   write mod f$parse(srcfil,,,"NAME"), ".obj"
+$   i = i + 1
+$   goto feloop  
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Find current Zlib version number
+$!
+$FIND_VERSION:
+$ open/read h_in 'v_file'
+$hloop:
+$ read/end=hdone h_in rec
+$ rec = f$edit(rec,"TRIM")
+$ if (f$extract(0,1,rec) .nes. "#") then goto hloop
+$ rec = f$edit(rec - "#", "TRIM")
+$ if f$element(0," ",rec) .nes. "define" then goto hloop
+$ if f$element(1," ",rec) .eqs. v_string
+$ then
+$   version = 'f$element(2," ",rec)'
+$   goto hdone
+$ endif
+$ goto hloop
+$hdone:
+$ close h_in
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Analyze Object files for OpenVMS AXP to extract Procedure and Data 
+$! information to build a symbol vector for a shareable image
+$! All the "brains" of this logic was suggested by Hartmut Becker
+$! (Hartmut.Becker@compaq.com). All the bugs were introduced by me
+$! (zinser@decus.de), so if you do have problem reports please do not
+$! bother Hartmut/HP, but get in touch with me
+$!
+$ ANAL_OBJ_AXP: Subroutine   
+$ V = 'F$Verify(0)
+$ SAY := "WRITE_ SYS$OUTPUT"
+$ 
+$ IF F$SEARCH("''P1'") .EQS. ""
+$ THEN
+$    SAY "ANAL_OBJ_AXP-E-NOSUCHFILE:  Error, inputfile ''p1' not available"
+$    goto exit_aa
+$ ENDIF
+$ IF "''P2'" .EQS. ""
+$ THEN
+$    SAY "ANAL_OBJ_AXP:  Error, no output file provided"
+$    goto exit_aa
+$ ENDIF
+$
+$ open/read in 'p1
+$ create a.tmp
+$ open/append atmp a.tmp
+$ loop:
+$ read/end=end_loop in line
+$ f= f$search(line)
+$ if f .eqs. ""
+$ then
+$      write sys$output "ANAL_OBJ_AXP-w-nosuchfile, ''line'"
+$      goto loop
+$ endif
+$ define/user sys$output nl:
+$ define/user sys$error nl:
+$ anal/obj/gsd 'f /out=x.tmp
+$ open/read xtmp x.tmp
+$ XLOOP:
+$ read/end=end_xloop xtmp xline
+$ xline = f$edit(xline,"compress")
+$ write atmp xline
+$ goto xloop
+$ END_XLOOP:
+$ close xtmp
+$ goto loop
+$ end_loop:
+$ close in
+$ close atmp
+$ if f$search("a.tmp") .eqs. "" -
+       then $ exit
+$ ! all global definitions
+$ search a.tmp "symbol:","EGSY$V_DEF 1","EGSY$V_NORM 1"/out=b.tmp
+$ ! all procedures
+$ search b.tmp "EGSY$V_NORM 1"/wind=(0,1) /out=c.tmp
+$ search c.tmp "symbol:"/out=d.tmp
+$ define/user sys$output nl:
+$ edito/edt/command=sys$input d.tmp
+sub/symbol: "/symbol_vector=(/whole
+sub/"/=PROCEDURE)/whole
+exit
+$ ! all data
+$ search b.tmp "EGSY$V_DEF 1"/wind=(0,1) /out=e.tmp
+$ search e.tmp "symbol:"/out=f.tmp
+$ define/user sys$output nl:
+$ edito/edt/command=sys$input f.tmp
+sub/symbol: "/symbol_vector=(/whole
+sub/"/=DATA)/whole
+exit
+$ sort/nodupl d.tmp,f.tmp 'p2'
+$ delete a.tmp;*,b.tmp;*,c.tmp;*,d.tmp;*,e.tmp;*,f.tmp;*
+$ if f$search("x.tmp") .nes. "" -
+       then $ delete x.tmp;*
+$!
+$ EXIT_AA:
+$ if V then set verify
+$ endsubroutine 
+$!------------------------------------------------------------------------------
index 81c80c7..7c0a429 100644 (file)
@@ -1,5 +1,5 @@
 /* minigzip.c -- simulate gzip using the zlib compression library
- * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -21,8 +21,6 @@
 #ifdef STDC
 #  include <string.h>
 #  include <stdlib.h>
-#else
-   extern void exit  OF((int));
 #endif
 
 #ifdef USE_MMAP
@@ -111,7 +109,7 @@ void error(const char *msg)
  * Compress input to output then close both files.
  */
 
-void gz_compress(FILE   *in, gzFile out)
+void gz_compress(FILE *in, gzFile out)
 {
     local char buf[BUFLEN];
     int len;
@@ -142,7 +140,7 @@ void gz_compress(FILE   *in, gzFile out)
 /* Try compressing the input file at once using mmap. Return Z_OK if
  * if success, Z_ERRNO otherwise.
  */
-int gz_compress_mmap(FILE   *in, gzFile out)
+int gz_compress_mmap(FILE *in, gzFile out)
 {
     int len;
     int err;
@@ -175,7 +173,7 @@ int gz_compress_mmap(FILE   *in, gzFile out)
 /* ===========================================================================
  * Uncompress input to output then close both files.
  */
-void gz_uncompress(gzFile in, FILE   *out)
+void gz_uncompress(gzFile in, FILE *out)
 {
     local char buf[BUFLEN];
     int len;
@@ -200,7 +198,7 @@ void gz_uncompress(gzFile in, FILE   *out)
  * Compress the given file: create a corresponding .gz file and remove the
  * original.
  */
-void file_compress(char  *file, char  *mode)
+void file_compress(char *file, char *mode)
 {
     local char outfile[MAX_NAME_LEN];
     FILE  *in;
@@ -228,7 +226,7 @@ void file_compress(char  *file, char  *mode)
 /* ===========================================================================
  * Uncompress the given file and remove the original.
  */
-void file_uncompress(char * file)
+void file_uncompress(char *file)
 {
     local char buf[MAX_NAME_LEN];
     char *infile, *outfile;
@@ -300,6 +298,8 @@ int main(int argc, char *argv[])
         break;
       argc--, argv++;
     }
+    if (outmode[3] == ' ')
+        outmode[3] = 0;
     if (argc == 0) {
         SET_BINARY_MODE(stdin);
         SET_BINARY_MODE(stdout);
index bf14280..f728ebe 100644 (file)
       <QPG:Files>
          <QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/>
          <QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/>
-         <QPG:Add file="../libz.so.1.2.2" install="/opt/lib/" user="root:bin" permission="644"/>
-         <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.2"/>
-         <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.2"/>
-         <QPG:Add file="../libz.so.1.2.2" install="/opt/lib/" component="slib"/>
+         <QPG:Add file="../libz.so.1.2.2.4" install="/opt/lib/" user="root:bin" permission="644"/>
+         <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.2.4"/>
+         <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.2.4"/>
+         <QPG:Add file="../libz.so.1.2.2.4" install="/opt/lib/" component="slib"/>
       </QPG:Files>
 
       <QPG:PackageFilter>
@@ -63,7 +63,7 @@
             </QPM:ProductDescription>
 
             <QPM:ReleaseDescription>
-               <QPM:ReleaseVersion>1.2.2</QPM:ReleaseVersion>
+               <QPM:ReleaseVersion>1.2.2.4</QPM:ReleaseVersion>
                <QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
                <QPM:ReleaseStability>Stable</QPM:ReleaseStability>
                <QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>
index a818c88..6f523bc 100644 (file)
@@ -1,5 +1,5 @@
 /* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2003 Jean-loup Gailly
+ * Copyright (C) 1995-2005 Jean-loup Gailly
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -572,7 +572,7 @@ local void gen_bitlen(deflate_state *s, tree_desc *desc)
         while (n != 0) {
             m = s->heap[--h];
             if (m > max_code) continue;
-            if (tree[m].Len != (unsigned) bits) {
+            if ((unsigned) tree[m].Len != (unsigned) bits) {
                 Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
                 s->opt_len += ((long)bits - (long)tree[m].Len)
                               *(long)tree[m].Freq;
@@ -916,7 +916,7 @@ void _tr_align(deflate_state *s)
  * Determine the best encoding for the current block: dynamic trees, static
  * trees or store, and output the encoded block to the zip file.
  */
-void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int eof)
+void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int pad, int eof)
 {
     ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
     int max_blindex = 0;  /* index of last bit length code of non zero freq */
@@ -924,8 +924,9 @@ void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int eof)
     /* Build the Huffman trees unless a stored block is forced */
     if (s->level > 0) {
 
-         /* Check if the file is ascii or binary */
-        if (s->strm->data_type == Z_UNKNOWN) set_data_type(s);
+        /* Check if the file is binary or text */
+        if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
+            set_data_type(s);
 
         /* Construct the literal and distance trees */
         build_tree(s, (tree_desc *)(&(s->l_desc)));
@@ -976,7 +977,7 @@ void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int eof)
 #ifdef FORCE_STATIC
     } else if (static_lenb >= 0) { /* force static trees */
 #else
-    } else if (static_lenb == opt_lenb) {
+    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
 #endif
         send_bits(s, (STATIC_TREES<<1)+eof, 3);
         compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
@@ -1003,6 +1004,12 @@ void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int eof)
 #ifdef DEBUG
         s->compressed_len += 7;  /* align on byte boundary */
 #endif
+#ifdef DEBUG
+    } else if (pad && (s->compressed_len % 8) != 0) {
+#else
+    } else if (pad) {
+#endif
+        _tr_stored_block(s, buf, 0, eof);
     }
     Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
            s->compressed_len-7*eof));
@@ -1105,20 +1112,23 @@ local void compress_block(deflate_state *s, ct_data *ltree, ct_data *dtree)
 }
 
 /* ===========================================================================
- * Set the data type to ASCII or BINARY, using a crude approximation:
- * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
- * IN assertion: the fields freq of dyn_ltree are set and the total of all
- * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ * Set the data type to BINARY or TEXT, using a crude approximation:
+ * set it to Z_TEXT if all symbols are either printable characters (33 to 255)
+ * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise.
+ * IN assertion: the fields Freq of dyn_ltree are set.
  */
 local void set_data_type(deflate_state *s)
 {
-    int n = 0;
-    unsigned ascii_freq = 0;
-    unsigned bin_freq = 0;
-    while (n < 7)        bin_freq += s->dyn_ltree[n++].Freq;
-    while (n < 128)    ascii_freq += s->dyn_ltree[n++].Freq;
-    while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
-    s->strm->data_type = bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII;
+    int n;
+
+    for (n = 0; n < 9; n++)
+        if (s->dyn_ltree[n].Freq != 0)
+            break;
+    if (n == 9)
+        for (n = 14; n < 32; n++)
+            if (s->dyn_ltree[n].Freq != 0)
+                break;
+    s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY;
 }
 
 /* ===========================================================================
index 162ab8f..8cff589 100644 (file)
@@ -5,8 +5,8 @@ VS_VERSION_INFO         VERSIONINFO
 #else
 VS_VERSION_INFO                VERSIONINFO     MOVEABLE IMPURE LOADONCALL DISCARDABLE
 #endif
-  FILEVERSION          1,2,2
-  PRODUCTVERSION       1,2,2
+  FILEVERSION          1,2,2,4
+  PRODUCTVERSION       1,2,2,4
   FILEFLAGSMASK                VS_FFI_FILEFLAGSMASK
 #ifdef _DEBUG
   FILEFLAGS            1
@@ -23,12 +23,12 @@ BEGIN
     //language ID = U.S. English, char set = Windows, Multilingual
     BEGIN
       VALUE "FileDescription", "zlib data compression library\0"
-      VALUE "FileVersion",     "1.2.2\0"
+      VALUE "FileVersion",     "1.2.2.4\0"
       VALUE "InternalName",    "zlib1.dll\0"
       VALUE "LegalCopyright",  "(C) 1995-2004 Jean-loup Gailly & Mark Adler\0"
       VALUE "OriginalFilename",        "zlib1.dll\0"
       VALUE "ProductName",     "zlib\0"
-      VALUE "ProductVersion",  "1.2.2\0"
+      VALUE "ProductVersion",  "1.2.2.4\0"
       VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
     END
   END
index bfe3511..562b5e8 100644 (file)
@@ -1,5 +1,5 @@
 /* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2004 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 #if defined(_WINDOWS) && !defined(WINDOWS)
 #  define WINDOWS
 #endif
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-#  define WIN32
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
 #endif
 #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
 #  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
index 3c21403..03a9431 100644 (file)
@@ -1,5 +1,5 @@
 /* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2004 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 #  define get_crc_table         z_get_crc_table
 #  define zError                z_zError
 
+#  define alloc_func            z_alloc_func
+#  define free_func             z_free_func
+#  define in_func               z_in_func
+#  define out_func              z_out_func
 #  define Byte                  z_Byte
 #  define uInt                  z_uInt
 #  define uLong                 z_uLong
 #if defined(_WINDOWS) && !defined(WINDOWS)
 #  define WINDOWS
 #endif
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-#  define WIN32
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
 #endif
 #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
 #  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
index 3139e24..b91375e 100644 (file)
@@ -1,4 +1,4 @@
-.TH ZLIB 3 "3 October 2004"
+.TH ZLIB 3 "11 July 2005"
 .SH NAME
 zlib \- compression/decompression library
 .SH SYNOPSIS
@@ -133,8 +133,8 @@ before asking for help.
 Send questions and/or comments to zlib@gzip.org,
 or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
 .SH AUTHORS
-Version 1.2.2
-Copyright (C) 1995-2004 Jean-loup Gailly (jloup@gzip.org)
+Version 1.2.2.4
+Copyright (C) 1995-2005 Jean-loup Gailly (jloup@gzip.org)
 and Mark Adler (madler@alumni.caltech.edu).
 .LP
 This software is provided "as-is,"
index 3c3a0a4..f413388 100644 (file)
@@ -1,7 +1,7 @@
 /* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.2.2.2, December 30th, 2004
+  version 1.2.2.4, July 11th, 2005
 
-  Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler
+  Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -579,7 +579,9 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
    deflateInit or deflateInit2, a part of the dictionary may in effect be
    discarded, for example if the dictionary is larger than the window size in
    deflate or deflate2. Thus the strings most likely to be useful should be
-   put at the end of the dictionary, not at the front.
+   put at the end of the dictionary, not at the front. In addition, the
+   current implementation of deflate will use at most the window size minus
+   262 bytes of the provided dictionary.
 
      Upon return of this function, strm->adler is set to the adler32 value
    of the dictionary; the decompressor may later use this value to determine
@@ -648,6 +650,24 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
    if strm->avail_out was zero.
 */
 
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain))
+       /*@modifies strm @*/;
+/*
+     Fine tune deflate's internal compression parameters.  This should only be
+   used by someone who understands the algorithm used by zlib's deflate for
+   searching for the best matching string, and even then only by the most
+   fanatic optimizer trying to squeeze out the last compressed bit for their
+   specific input data.  Read the deflate.c source code for the meaning of the
+   max_lazy, good_length, nice_length, and max_chain parameters.
+
+     deflateTune() can be called after deflateInit() or deflateInit2(), and
+   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
 ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
                                        uLong sourceLen))
        /*@modifies strm @*/;
@@ -732,15 +752,15 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
      windowBits can also be greater than 15 for optional gzip decoding. Add
    32 to windowBits to enable zlib and gzip decoding with automatic header
    detection, or add 16 to decode only the gzip format (the zlib format will
-   return a Z_DATA_ERROR.  If a gzip stream is being decoded, strm->adler is
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is
    a crc32 instead of an adler32.
 
      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
-   memLevel). msg is set to null if there is no error message.  inflateInit2
-   does not perform any decompression apart from reading the zlib header if
-   present: this will be done by inflate(). (So next_in and avail_in may be
-   modified, but next_out and avail_out are unchanged.)
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+   is set to null if there is no error message.  inflateInit2 does not perform
+   any decompression apart from reading the zlib header if present: this will
+   be done by inflate(). (So next_in and avail_in may be modified, but next_out
+   and avail_out are unchanged.)
 */
 
 ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
@@ -810,6 +830,22 @@ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm))
    stream state was inconsistent (such as zalloc or state being NULL).
 */
 
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     This function inserts bits in the inflate input stream.  The intent is
+  that this function is used to start inflating at a bit position in the
+  middle of a byte.  The provided bits will be used before any bytes are used
+  from next_in.  This function should only be used with raw inflate, and
+  should be used before the first inflate() call after inflateInit2() or
+  inflateReset().  bits must be less than or equal to 16, and that many of the
+  least significant bits of value will be inserted in the input.
+
+      inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
 ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
                                          gz_headerp head))
        /*@modifies strm, head @*/;
@@ -1261,6 +1297,13 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file))
    input stream, otherwise zero.
 */
 
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file))
+       /*@*/;
+/*
+     Returns 1 if file is being read directly without decompression, otherwise
+   zero.
+*/
+
 ZEXTERN int ZEXPORT    gzclose OF((gzFile file))
        /*@globals fileSystem @*/
        /*@modifies file, fileSystem @*/;
index 00b6438..0e08d37 100644 (file)
@@ -1,5 +1,5 @@
 /* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 struct internal_state      {int dummy;}; /* for buggy compilers */
 #endif
 
-#ifndef STDC
-extern void exit OF((int));
-#endif
-
 /*@observer@*/
 const char * const z_errmsg[10] = {
 "need dictionary",     /* Z_NEED_DICT       2  */
@@ -29,12 +25,12 @@ const char * const z_errmsg[10] = {
 ""};
 
 
-const char * ZEXPORT zlibVersion()
+const char * ZEXPORT zlibVersion(void)
 {
     return ZLIB_VERSION;
 }
 
-uLong ZEXPORT zlibCompileFlags()
+uLong ZEXPORT zlibCompileFlags(void)
 {
     uLong flags;
 
@@ -79,38 +75,38 @@ uLong ZEXPORT zlibCompileFlags()
     flags += 1 << 13;
 #endif
 #ifdef NO_GZCOMPRESS
-    flags += 1 << 16;
+    flags += 1L << 16;
 #endif
 #ifdef NO_GZIP
-    flags += 1 << 17;
+    flags += 1L << 17;
 #endif
 #ifdef PKZIP_BUG_WORKAROUND
-    flags += 1 << 20;
+    flags += 1L << 20;
 #endif
 #ifdef FASTEST
-    flags += 1 << 21;
+    flags += 1L << 21;
 #endif
 #ifdef STDC
 #  ifdef NO_vsnprintf
-        flags += 1 << 25;
+        flags += 1L << 25;
 #    ifdef HAS_vsprintf_void
-        flags += 1 << 26;
+        flags += 1L << 26;
 #    endif
 #  else
 #    ifdef HAS_vsnprintf_void
-        flags += 1 << 26;
+        flags += 1L << 26;
 #    endif
 #  endif
 #else
-        flags += 1 << 24;
+        flags += 1L << 24;
 #  ifdef NO_snprintf
-        flags += 1 << 25;
+        flags += 1L << 25;
 #    ifdef HAS_sprintf_void
-        flags += 1 << 26;
+        flags += 1L << 26;
 #    endif
 #  else
 #    ifdef HAS_snprintf_void
-        flags += 1 << 26;
+        flags += 1L << 26;
 #    endif
 #  endif
 #endif
@@ -124,8 +120,7 @@ uLong ZEXPORT zlibCompileFlags()
 #  endif
 int z_verbose = verbose;
 
-void z_error (m)
-    char *m;
+void z_error (char *m)
 {
     fprintf(stderr, "%s\n", m);
     exit(1);
@@ -141,16 +136,16 @@ const char * ZEXPORT zError(int err)
 }
 
 #if defined(_WIN32_WCE)
-    /* does not exist on WCE */
+    /* The Microsoft C Run-Time Library for Windows CE doesn't have
+     * errno.  We define it as a global variable to simplify porting.
+     * Its value is always 0 and should not be used.
+     */
     int errno = 0;
 #endif
 
 #ifndef HAVE_MEMCPY
 
-void zmemcpy(dest, source, len)
-    Bytef* dest;
-    const Bytef* source;
-    uInt  len;
+void zmemcpy(Bytef* dest, const Bytef* source, uInt  len)
 {
     if (len == 0) return;
     do {
@@ -158,10 +153,7 @@ void zmemcpy(dest, source, len)
     } while (--len != 0);
 }
 
-int zmemcmp(s1, s2, len)
-    const Bytef* s1;
-    const Bytef* s2;
-    uInt  len;
+int zmemcmp(const Bytef* s1, const Bytef* s2, uInt  len)
 {
     uInt j;
 
@@ -171,9 +163,7 @@ int zmemcmp(s1, s2, len)
     return 0;
 }
 
-void zmemzero(dest, len)
-    Bytef* dest;
-    uInt  len;
+void zmemzero(Bytef* dest, uInt  len)
 {
     if (len == 0) return;
     do {
index bff6f31..6ccaab7 100644 (file)
@@ -1,5 +1,5 @@
 /* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 #include "zlib.h"
 
 #ifdef STDC
-#  include <stddef.h>
+#  ifndef _WIN32_WCE
+#    include <stddef.h>
+#  endif
 #  include <string.h>
 #  include <stdlib.h>
 #endif
 #ifdef NO_ERRNO_H
+#   ifdef _WIN32_WCE
+      /* The Microsoft C Run-Time Library for Windows CE doesn't have
+       * errno.  We define it as a global variable to simplify porting.
+       * Its value is always 0 and should not be used.  We rename it to
+       * avoid conflict with other libraries that use the same workaround.
+       */
+#     define errno z_errno
+#   endif
     extern int errno;
 #else
-#   include <errno.h>
+#  ifndef _WIN32_WCE
+#    include <errno.h>
+#  endif
 #endif
 
 #ifndef local
@@ -108,6 +120,9 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 
 #ifdef OS2
 #  define OS_CODE  0x06
+#  ifdef M_I86
+     #include <malloc.h>
+#  endif
 #endif
 
 #if defined(MACOS) || defined(TARGET_OS_MAC)
@@ -196,16 +211,6 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 #  define NO_vsnprintf
 #endif
 
-#ifdef HAVE_STRERROR
-#  ifndef VMS
-     extern char *strerror OF((int))
-       /*@*/;
-#  endif
-#  define zstrerror(errnum) strerror(errnum)
-#else
-#  define zstrerror(errnum) ""
-#endif
-
 #if defined(pyr)
 #  define NO_MEMCPY
 #endif