zlib 0.79
diff --git a/ChangeLog b/ChangeLog
index 40fc89f..c0536d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 		ChangeLog file for zlib
 
+Changes in 0.79 (28 April 95)
+- add fast inflate (inffast.c)
+- In gzio destroy(), don't reference a freed structure
+- avoid many warnings for MSDOS
+
 Changes in 0.71 (14 April 95)
 - Fixed more MSDOS compilation problems :( There is still a bug with
   TurboC large model.
diff --git a/Makefile b/Makefile
index 478920a..facba8a 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@
 RANLIB=ranlib
 
 OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
-       zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o
+       zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
 
 TEST_OBJS = example.o minigzip.o inftest.o
 
@@ -48,7 +48,8 @@
 example.o: zlib.h zconf.h
 gzio.o: zutil.h zlib.h zconf.h
 infblock.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
-infcodes.o: zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h
+infcodes.o: zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h
 inflate.o: zutil.h zlib.h zconf.h infblock.h
 inftest.o: zutil.h zlib.h zconf.h
 inftrees.o: zutil.h zlib.h zconf.h inftrees.h
diff --git a/README b/README
index 5c42402..5705062 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-zlib 0.71 is a beta version of a general purpose compression library.
+zlib 0.79 is a beta version of a general purpose compression library.
 
 The data format used by the zlib library is described in the
 file zlib-3.1.doc, deflate-1.1.doc and gzip-4.1.doc, available
@@ -9,16 +9,10 @@
 which also tests that the library is working correctly.
 To compile all files and run the test program, just type: make test
 
-The changes made in version 0.71 are documented in the file ChangeLog.
-The main changes since 0.5 are:
-- added full inflate support
-- added minigzip.c
-- added gzdopen to reopen a file descriptor as gzFile
-- added transparent reading of non-gziped files in gzread.
-- fix some MSDOS problems. example and minigzip now work on MSDOS.
-- Simplified the crc32() interface. The pre- and post-conditioning
-  (one's complement) is now done inside crc32(). WARNING: this is
-  incompatible with previous versions; see zlib.h for the new usage.
+The changes made in version 0.79 are documented in the file ChangeLog.
+The main changes since 0.71 are:
+- add fast inflate (inffast.c)
+- In gzio destroy(), don't reference a freed structure
 
 On MSDOS, this version works in large and small model with MSC; in
 small model only with TurboC (bug being investigated). For both
diff --git a/deflate.c b/deflate.c
index 2409f07..7d44627 100644
--- a/deflate.c
+++ b/deflate.c
@@ -47,7 +47,7 @@
  *
  */
 
-/* $Id: deflate.c,v 1.3 1995/04/10 16:03:45 jloup Exp $ */
+/* $Id: deflate.c,v 1.4 1995/04/14 19:49:46 jloup Exp $ */
 
 #include "deflate.h"
 
@@ -195,9 +195,11 @@
     s->noheader = noheader;
     s->w_bits = windowBits;
     s->w_size = 1 << s->w_bits;
+    s->w_mask = s->w_size - 1;
 
     s->hash_bits = memLevel + 7;
     s->hash_size = 1 << s->hash_bits;
+    s->hash_mask = s->hash_size - 1;
     s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
 
     s->window = (Byte*) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
diff --git a/example.c b/example.c
index ea1a9eb..86541a7 100644
--- a/example.c
+++ b/example.c
@@ -3,7 +3,7 @@
  * For conditions of distribution and use, see copyright notice in zlib.h 
  */
 
-/* $Id: example.c,v 1.4 1995/04/14 13:32:49 jloup Exp $ */
+/* $Id: example.c,v 1.5 1995/04/14 20:35:56 jloup Exp $ */
 
 #include <stdio.h>
 #include "zlib.h"
@@ -60,7 +60,7 @@
     char *in;  /* input file */
 {
     local Byte uncompr[BUFLEN];
-    uLong uncomprLen = sizeof(uncompr);
+    int uncomprLen = sizeof(uncompr);
     int err;
     int len = strlen(hello)+1;
     gzFile file;
@@ -114,7 +114,7 @@
     c_stream.next_in  = (Byte*)hello;
     c_stream.next_out = compr;
 
-    while (c_stream.total_in != len) {
+    while (c_stream.total_in != (uLong)len) {
 	c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
 	err = deflate(&c_stream, Z_NO_FLUSH);
 	CHECK_ERR(err, "deflate");
diff --git a/gzio.c b/gzio.c
index b488e96..365b6f5 100644
--- a/gzio.c
+++ b/gzio.c
@@ -71,8 +71,9 @@
     if (s->file != NULL && fclose(s->file)) {
 	err = Z_ERRNO;
     }
+    if (s->z_err < 0) err = s->z_err;
     zcfree((voidp)0, s);
-    return s->z_err < 0 ? s->z_err : err;
+    return err;
 }
 
 /* ===========================================================================
@@ -235,9 +236,10 @@
 
     if (s->transparent) {
 	unsigned n = 0;
+	Byte *b = (Byte*)buf;
 	/* Copy the first two (non-magic) bytes if not done already */
 	while (s->stream.avail_in > 0 && len > 0) {
-	    *((Byte*)buf)++ = *s->stream.next_in++;
+	    *b++ = *s->stream.next_in++;
 	    s->stream.avail_in--;
 	    len--; n++;
 	}
@@ -364,7 +366,7 @@
 {
     int n;
     for (n = 0; n < 4; n++) {
-	fputc(x & 0xff, file);
+	fputc((int)(x & 0xff), file);
 	x >>= 8;
     }
 }
diff --git a/infblock.c b/infblock.c
index 3a58280..4d8bd48 100644
--- a/infblock.c
+++ b/infblock.c
@@ -60,16 +60,17 @@
       the two sets of lengths.
  */
 
-struct inflate_blocks_state *inflate_blocks_new(z,wsize)
+struct inflate_blocks_state *inflate_blocks_new(z, c, w)
 z_stream *z;
-uInt wsize;
+check_func c;
+uInt w;
 {
   struct inflate_blocks_state *s;
 
   if ((s = (struct inflate_blocks_state *)ZALLOC
        (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
     return s;
-  if ((s->window = (Byte *)ZALLOC(z,1,wsize)) == Z_NULL)
+  if ((s->window = (Byte *)ZALLOC(z, 1, w)) == Z_NULL)
   {
     ZFREE(z, s);
     return Z_NULL;
@@ -77,8 +78,10 @@
   s->mode = TYPE;
   s->bitk = 0;
   s->read = s->write = s->window;
-  s->end = s->window + wsize;
-  s->check = 1;
+  s->end = s->window + w;
+  s->checkfn = c;
+  if (s->checkfn != Z_NULL)
+    s->check = (*s->checkfn)(0L, Z_NULL, 0);
   return s;
 }
 
@@ -312,8 +315,9 @@
 uLong *c;
 int *e;
 {
-  *e = s->bitk > 7 ? (s->bitb >> (s->bitk & 7)) & 0xff : -1;
-  *c = s->check;
+  *e = (int)(s->bitk > 7 ? (s->bitb >> (s->bitk & 7)) & 0xff : -1);
+  if (s->checkfn != Z_NULL)
+    *c = s->check;
   if (s->mode == BTREE || s->mode == DTREE)
     ZFREE(z, s->sub.trees.blens);
   if (s->mode == CODES)
diff --git a/infblock.h b/infblock.h
index f70c471..a21d730 100644
--- a/infblock.h
+++ b/infblock.h
@@ -12,6 +12,7 @@
 
 extern struct inflate_blocks_state * inflate_blocks_new __P((
     z_stream *,
+    check_func checkfn,               /* check function */
     uInt));                     /* window size */
 
 extern int inflate_blocks __P((
diff --git a/infcodes.c b/infcodes.c
index ffae26d..489f9d6 100644
--- a/infcodes.c
+++ b/infcodes.c
@@ -6,6 +6,7 @@
 #include "zutil.h"
 #include "inftrees.h"
 #include "infutil.h"
+#include "inffast.h"
 #include "infcodes.h"
 
 /* simplify the use of the inflate_huft type with some defines */
@@ -98,7 +99,19 @@
   while (1) switch (c->mode)
   {		/* waiting for "i:"=input, "o:"=output, "x:"=nothing */
     case START:		/* x: set up for LEN */
-      /* %%% check for avail in and out to do fast loop %%% */
+#ifndef SLOW
+      if (m >= 258 && n >= 10)
+      {
+        UPDATE
+	r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+	LOAD
+	if (r != Z_OK)
+	{
+	  c->mode = r == Z_STREAM_END ? WASH : BAD;
+	  break;
+	}
+      }
+#endif /* !SLOW */
       c->sub.code.need = c->lbits;
       c->sub.code.tree = c->ltree;
       c->mode = LEN;
@@ -112,14 +125,14 @@
         if (e == -128)		/* invalid code */
 	{
 	  c->mode = BAD;
-	  z->msg = "invalid huffman code";
+	  z->msg = "invalid literal/length code";
 	  r = Z_DATA_ERROR;
 	  LEAVE
 	}
 	e = -e;
 	if (e & 64)		/* end of block */
 	{
-	  c->mode = END;
+	  c->mode = WASH;
 	  break;
 	}
 	c->sub.code.need = e;
@@ -153,7 +166,7 @@
         if (e == -128)
 	{
 	  c->mode = BAD;
-	  z->msg = "invalid huffman code";
+	  z->msg = "invalid distance code";
 	  r = Z_DATA_ERROR;
 	  LEAVE
 	}
@@ -171,7 +184,7 @@
       DUMPBITS(j)
       c->mode = COPY;
     case COPY:		/* o: copying bytes in window, waiting for space */
-      f = q - s->window < c->sub.copy.dist ?
+      f = (uInt)(q - s->window) < c->sub.copy.dist ?
 	  s->end - (c->sub.copy.dist - (q - s->window)) :
 	  q - c->sub.copy.dist;
       while (c->len)
diff --git a/inffast.c b/inffast.c
new file mode 100644
index 0000000..8c3e4ce
--- /dev/null
+++ b/inffast.c
@@ -0,0 +1,148 @@
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infutil.h"
+#include "inffast.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#ifdef DEBUG
+#  undef NEXTBYTE
+#  define NEXTBYTE (n--?0:fprintf(stderr,"inffast underrun\n"),*p++)
+#endif
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
+
+/* Called with number of bytes left to write in window at least 258
+   (the maximum string length) and number of input bytes available
+   at least ten.  The ten bytes are six bytes for the longest length/
+   distance pair plus four bytes for overloading the bit buffer. */
+
+int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl, *td;
+struct inflate_blocks_state *s;
+z_stream *z;
+{
+  inflate_huft *t;	/* temporary pointer */
+  int e;		/* extra bits or operation */
+  uLong b;		/* bit buffer */
+  uInt k;		/* bits in bit buffer */
+  Byte *p;		/* input data pointer */
+  uInt n;		/* bytes available there */
+  Byte *q;		/* output window write pointer */
+  uInt m;		/* bytes to end of window or read pointer */
+  uInt ml;		/* mask for literal/length tree */
+  uInt md;		/* mask for distance tree */
+  uInt c;		/* bytes to copy */
+  uInt d;		/* distance back to copy from */
+  Byte *r;		/* copy source pointer */
+
+  /* load input, output, bit values */
+  LOAD
+
+  /* initialize masks in registers */
+  ml = inflate_mask[bl];
+  md = inflate_mask[bd];
+
+  /* do until not enough input or output space for fast loop */
+  do {				/* assume called with m >= 258 && n >= 10 */
+    /* get literal/length code */
+    GRABBITS(20)		/* max bits for literal/length code */
+    if ((e = (t = tl + ((uInt)b & ml))->exop) < 0)
+      do {
+	if (e == -128)
+	{
+	  z->msg = "invalid literal/length code";
+          UNGRAB
+	  UPDATE
+	  return Z_DATA_ERROR;
+	}
+	DUMPBITS(t->bits)
+	e = -e;
+	if (e & 64)		/* end of block */
+	{
+          UNGRAB
+	  UPDATE
+	  return Z_STREAM_END;
+	}
+      } while ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) < 0);
+    DUMPBITS(t->bits)
+
+    /* process literal or length (end of block already trapped) */
+    if (e & 16)			/* then it's a literal */
+    {
+      *q++ = (Byte)t->base;
+      m--;
+    }
+    else			/* it's a length */
+    {
+      /* get length of block to copy (already have extra bits) */
+      c = t->base + ((uInt)b & inflate_mask[e]);
+      DUMPBITS(e);
+
+      /* decode distance base of block to copy */
+      GRABBITS(15);		/* max bits for distance code */
+      if ((e = (t = td + ((uInt)b & md))->exop) < 0)
+	do {
+	  if (e == -128)
+	  {
+	    z->msg = "invalid distance code";
+	    UNGRAB
+	    UPDATE
+	    return Z_DATA_ERROR;
+	  }
+	  DUMPBITS(t->bits)
+	  e = -e;
+	} while ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) < 0);
+      DUMPBITS(t->bits)
+
+      /* get extra bits to add to distance base */
+      GRABBITS(e)           /* get extra bits (up to 13) */
+      d = t->base + ((uInt)b & inflate_mask[e]);
+      DUMPBITS(e)
+
+      /* do the copy */
+      m -= c;
+      if (q - s->window >= d)		/* if offset before destination, */
+      {					/*  just copy */
+	r = q - d;
+	*q++ = *r++;  c--;		/* minimum count is three, */
+	*q++ = *r++;  c--;		/*  so unroll loop a little */
+	do {
+	  *q++ = *r++;
+	} while (--c);
+      }
+      else				/* else offset after destination */
+      {
+	e = d - (q - s->window);	/* bytes from offset to end */
+	r = s->end - e;			/* pointer to offset */
+	if (c > e)			/* if source crosses, */
+	{
+	  c -= e;			/* copy to end of window */
+	  do {
+	    *q++ = *r++;
+	  } while (--e);
+	  r = s->window;		/* copy rest from start of window */
+	}
+	do {				/* copy all or what's left */
+	  *q++ = *r++;
+	} while (--c);
+      }
+    }
+  } while (m >= 258 && n >= 10);
+
+  /* not enough input or output--restore pointers and return */
+  UNGRAB
+  UPDATE
+  return Z_OK;
+}
diff --git a/inffast.h b/inffast.h
new file mode 100644
index 0000000..2c05820
--- /dev/null
+++ b/inffast.h
@@ -0,0 +1,17 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+extern int inflate_fast __P((
+    uInt,
+    uInt,
+    inflate_huft *,
+    inflate_huft *,
+    struct inflate_blocks_state *,
+    z_stream *));
diff --git a/inflate-0.72.c b/inflate-0.72.c
new file mode 100644
index 0000000..56b0665
--- /dev/null
+++ b/inflate-0.72.c
@@ -0,0 +1,230 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+
+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
+
+/* inflate private state */
+struct internal_state {
+
+  /* mode */
+  enum {
+      METHOD,	/* waiting for method byte */
+      FLAG,	/* waiting for flag byte */
+      START,	/* make new blocks state */
+      BLOCKS,	/* decompressing blocks */
+      CHECK4,	/* four check bytes to go */
+      CHECK3,	/* three check bytes to go */
+      CHECK2,	/* two check bytes to go */
+      CHECK1,	/* one check byte to go */
+      DONE,	/* finished check, done */
+      ERROR}	/* got an error--stay here */
+    mode;		/* current inflate mode */
+
+  /* mode dependent information */
+  union {
+    uInt method;	/* if FLAGS, method byte */
+    struct inflate_blocks_state
+      *blocks;		/* if BLOCKS, current state */
+    struct {
+      uLong was;		/* computed check value */
+      uLong need;		/* stream check value */
+    } check;		/* if CHECK, check values to compare */
+  } sub;	/* submode */
+
+  /* mode independent information */
+  int  nowrap;		/* flag for no wrapper */
+  uInt wbits;  		/* log2(window size)  (8..15, defaults to 15) */
+
+};
+
+
+int inflateInit(z)
+z_stream *z;
+{
+    return inflateInit2(z, WBITS);
+}
+
+
+int inflateInit2(z, w)
+z_stream *z;
+int w;
+{
+  /* initialize state */
+  if (z == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->zalloc == Z_NULL) z->zalloc = zcalloc;
+  if (z->zfree == Z_NULL) z->zfree = zcfree;
+  z->total_in = z->total_out = 0;
+  z->msg = Z_NULL;
+  if ((z->state = (struct internal_state *)
+       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+    return Z_MEM_ERROR;
+  z->state->mode = METHOD;
+
+  /* handle undocumented nowrap option (no zlib header or check) */
+  z->state->nowrap = 0;
+  if (w < 0)
+  {
+    w = - w;
+    z->state->nowrap = 1;
+    z->state->mode = START;
+  }
+
+  /* set window size */
+  if (w < 8 || w > 15)
+  {
+    inflateEnd(z);
+    return Z_STREAM_ERROR;
+  }
+  z->state->wbits = w;
+  return Z_OK;
+}
+
+
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int inflate(z, f)
+z_stream *z;
+int f;
+{
+  int r;
+  uInt b;
+  uLong c;
+
+  if (z == Z_NULL || z->next_in == Z_NULL)
+    return Z_STREAM_ERROR;
+  r = Z_BUF_ERROR;
+  while (1) switch (z->state->mode)
+  {
+    case METHOD:
+      if (z->avail_in == 0) return r;  r = Z_OK;
+      if (((z->state->sub.method = NEXTBYTE) & 0xf != DEFLATED))
+      {
+        z->state->mode = ERROR;
+	z->msg = "unknown compression method";
+	return Z_DATA_ERROR;
+      }
+      if ((z->state->sub.method >> 4) > z->state->wbits)
+      {
+        z->state->mode = ERROR;
+	z->msg = "invalid window size";
+	return Z_DATA_ERROR;
+      }
+      z->state->mode = FLAG;
+    case FLAG:
+      if (z->avail_in == 0) return r;  r = Z_OK;
+      if ((b = NEXTBYTE) & 0x20)
+      {
+        z->state->mode = ERROR;
+	z->msg = "invalid reserved bit";
+	return Z_DATA_ERROR;
+      }
+      if (((z->state->sub.method << 8) + b) % 31)
+      {
+        z->state->mode = ERROR;
+	z->msg = "incorrect header check";
+	return Z_DATA_ERROR;
+      }
+      z->state->mode = START;
+    case START:
+      if ((z->state->sub.blocks =
+           inflate_blocks_new(z,1<< z->state->wbits)) == Z_NULL)
+        return Z_MEM_ERROR;
+      z->state->mode = BLOCKS;
+    case BLOCKS:
+      if ((r = inflate_blocks(z->state->sub.blocks, z, r)) != Z_STREAM_END)
+        return r;
+      inflate_blocks_free(z->state->sub.blocks, z, &c, &r);
+      if (z->state->nowrap)
+      {
+        if (r != -1)
+	  z->msg = "inflate bug--took one too many bytes";
+	z->state->mode = r == -1 ? DONE : ERROR;
+	break;
+      }
+      z->state->sub.check.was = c;
+      if (r != -1)
+      {
+	z->state->sub.check.need = (uLong)r << 24;
+        z->state->mode = CHECK3;
+        r = Z_OK;
+	break;
+      }
+      r = Z_OK;
+      z->state->mode = CHECK4;
+    case CHECK4:
+      if (z->avail_in == 0) return r;  r = Z_OK;
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = CHECK3;
+    case CHECK3:
+      if (z->avail_in == 0) return r;  r = Z_OK;
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = CHECK2;
+    case CHECK2:
+      if (z->avail_in == 0) return r;  r = Z_OK;
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = CHECK1;
+    case CHECK1:
+      if (z->avail_in == 0) return r;  r = Z_OK;
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+      if (z->state->sub.check.was != z->state->sub.check.need)
+      {
+        z->state->mode = ERROR;
+        z->msg = "incorrect data check";
+	return Z_DATA_ERROR;
+      }
+      z->state->mode = DONE;
+    case DONE:
+      return Z_STREAM_END;
+    case ERROR:
+      return Z_DATA_ERROR;
+    default:
+      return Z_STREAM_ERROR;
+  }
+}
+
+
+int inflateEnd(z)
+z_stream *z;
+{
+  uLong c;
+  int e;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode == BLOCKS)
+    inflate_blocks_free(z->state->sub.blocks, z, &c, &e);
+  ZFREE(z, z->state);
+  z->state = Z_NULL;
+  return Z_OK;
+}
+
+
+/* inflateSync not implemented yet--this just consumes input */
+int inflateSync(z)
+z_stream *z;
+{
+  if (z == Z_NULL) return Z_STREAM_ERROR;
+  if (z->avail_in == 0) return Z_BUF_ERROR;
+  do {
+    z->total_in++;
+  } while (--z->avail_in);
+  return Z_DATA_ERROR;
+}
+
+
+/* inflateReset not fully implemented yet--this frees and reallocates */
+int inflateReset(z)
+z_stream *z;
+{
+  int r;
+
+  if ((r = inflateEnd(z)) != Z_OK)
+    return r;
+  return inflateInit(z);
+}
diff --git a/inflate.c b/inflate.c
index 478f46d..38d70cc 100644
--- a/inflate.c
+++ b/inflate.c
@@ -25,10 +25,6 @@
       ERROR}	/* got an error--stay here */
     mode;		/* current inflate mode */
 
-  int  no_header;
-  uInt w_size;  /* LZ77 window size (32K by default) */
-  uInt w_bits;  /* log2(w_size)  (8..16) */
-
   /* mode dependent information */
   union {
     uInt method;	/* if FLAGS, method byte */
@@ -39,19 +35,26 @@
       uLong need;		/* stream check value */
     } check;		/* if CHECK, check values to compare */
   } sub;	/* submode */
+
+  /* mode independent information */
+  int  nowrap;		/* flag for no wrapper */
+  uInt wbits;  		/* log2(window size)  (8..15, defaults to 15) */
+
 };
 
 
-int inflateInit (strm)
-z_stream *strm;
+int inflateInit(z)
+z_stream *z;
 {
-    return inflateInit2(strm, WBITS);
+    return inflateInit2(z, WBITS);
 }
 
-int inflateInit2(z, windowBits)
+
+int inflateInit2(z, w)
 z_stream *z;
-int windowBits;
+int w;
 {
+  /* initialize state */
   if (z == Z_NULL)
     return Z_STREAM_ERROR;
   if (z->zalloc == Z_NULL) z->zalloc = zcalloc;
@@ -63,19 +66,22 @@
     return Z_MEM_ERROR;
   z->state->mode = METHOD;
 
-  z->state->no_header = 0;
-  if (windowBits < 0) { /* undocumented feature: no zlib header */
-    windowBits = - windowBits;
-    z->state->no_header = 1;
-    z->state->sub.method = DEFLATED;
+  /* handle undocumented nowrap option (no zlib header or check) */
+  z->state->nowrap = 0;
+  if (w < 0)
+  {
+    w = - w;
+    z->state->nowrap = 1;
     z->state->mode = START;
   }
-  if (windowBits < 8 || windowBits > 15) {
+
+  /* set window size */
+  if (w < 8 || w > 15)
+  {
     inflateEnd(z);
     return Z_STREAM_ERROR;
   }
-  z->state->w_bits = windowBits;
-  z->state->w_size = 1<<windowBits;
+  z->state->wbits = w;
   return Z_OK;
 }
 
@@ -103,7 +109,7 @@
 	z->msg = "unknown compression method";
 	return Z_DATA_ERROR;
       }
-      if ((z->state->sub.method >> 4) > z->state->w_bits)
+      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
       {
         z->state->mode = ERROR;
 	z->msg = "invalid window size";
@@ -126,17 +132,21 @@
       }
       z->state->mode = START;
     case START:
-      if ((z->state->sub.blocks = inflate_blocks_new(z,z->state->w_size))
-	  == Z_NULL)
+      if ((z->state->sub.blocks = inflate_blocks_new(z,
+         z->state->nowrap ? Z_NULL : adler32,
+         1<< z->state->wbits)) == Z_NULL)
         return Z_MEM_ERROR;
       z->state->mode = BLOCKS;
     case BLOCKS:
       if ((r = inflate_blocks(z->state->sub.blocks, z, r)) != Z_STREAM_END)
         return r;
       inflate_blocks_free(z->state->sub.blocks, z, &c, &r);
-      if (z->state->no_header) {
-	z->state->mode = DONE;
-	return Z_STREAM_END;
+      if (z->state->nowrap)
+      {
+        if (r != -1)
+	  z->msg = "inflate bug--took one too many bytes";
+	z->state->mode = r == -1 ? DONE : ERROR;
+	break;
       }
       z->state->sub.check.was = c;
       if (r != -1)
diff --git a/inflate.h b/inflate.h
deleted file mode 100644
index 843224f..0000000
--- a/inflate.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* temporary kludge assuming single pass decompression */
-
-/* $Id: inflate.h,v 1.2 1995/04/11 14:47:32 jloup Exp $ */
-
-#include <stdio.h>
-
-#define NEXTBYTE \
-   (istrm->total_in++, istrm->avail_in-- == 0 ? \
-      (z_error("too small"), 0) : *istrm->next_in++)
-
-#define FLUSH(n) { \
-   if (istrm->avail_out < n) z_error("too big"); \
-   istrm->avail_out -= n; \
-   memcpy(istrm->next_out, slide, n); \
-   istrm->next_out += n; \
-   istrm->total_out += n; \
-}
-#define WSIZE istrm->state->w_size
-#define slide istrm->state->window
-#define memzero(a,s) memset((a),0,(s))
-#define inflate z_inflate
-#define qflag 1
diff --git a/inftrees.c b/inftrees.c
index 4b00e3c..54c7c8e 100644
--- a/inftrees.c
+++ b/inftrees.c
@@ -246,7 +246,7 @@
         {
           x[h] = i;             /* save pattern for backing up */
           r.bits = (char)l;     /* bits to dump before this table */
-          r.exop = (char)(-j);  /* bits in this table */
+          r.exop = -(char)j;    /* bits in this table */
           r.next = q;           /* pointer to this table */
           j = i >> (w - l);     /* (get around Turbo C bug) */
           u[h-1][j] = r;        /* connect to last table */
diff --git a/infutil.c b/infutil.c
index 92d115f..1adadbf 100644
--- a/infutil.c
+++ b/infutil.c
@@ -40,7 +40,8 @@
   z->total_out += n;
 
   /* update check information */
-  s->check = adler32(s->check, q, n);
+  if (s->checkfn != Z_NULL)
+    s->check = (*s->checkfn)(s->check, q, n);
 
   /* copy as far as end of window */
   while (n--) *p++ = *q++;
@@ -48,8 +49,10 @@
   /* see if more to copy at beginning of window */
   if (q == s->end)
   {
-    /* wrap source pointer */
+    /* wrap pointers */
     q = s->window;
+    if (s->write == s->end)
+      s->write = s->window;
 
     /* compute bytes to copy */
     n = s->write - q;
@@ -61,7 +64,8 @@
     z->total_out += n;
 
     /* update check information */
-    s->check = adler32(s->check, q, n);
+    if (s->checkfn != Z_NULL)
+      s->check = (*s->checkfn)(s->check, q, n);
 
     /* copy */
     while (n--) *p++ = *q++;
diff --git a/infutil.h b/infutil.h
index af07372..30b230d 100644
--- a/infutil.h
+++ b/infutil.h
@@ -47,6 +47,7 @@
   Byte *end;		/* one byte after sliding window */
   Byte *read;		/* window read pointer */
   Byte *write;		/* window write pointer */
+  check_func checkfn;   /* check function */
   uLong check;		/* check on output */
 
 };
diff --git a/minigzip.c b/minigzip.c
index 688b3a1..4936d64 100644
--- a/minigzip.c
+++ b/minigzip.c
@@ -13,13 +13,15 @@
  * or in pipe mode.
  */
 
-/* $Id: minigzip.c,v 1.1 1995/04/14 13:35:59 jloup Exp $ */
+/* $Id: minigzip.c,v 1.2 1995/04/14 20:03:12 jloup Exp $ */
 
 #include <stdio.h>
 #include "zlib.h"
 
+extern void exit __P((int));
+
 #ifdef MSDOS
-#  include <fcntl.h>
+#  include <fcntl.h> /* ??? find where setmode declared */
 #  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
 #else
 #  define SET_BINARY_MODE(file)
@@ -87,7 +89,7 @@
 	if (len < 0) error (gzerror(in, &err));
 	if (len == 0) break;
 
-	if (fwrite(buf, 1, len, out) != len) error("failed fwrite");
+	if (fwrite(buf, 1, len, out) != (uInt)len) error("failed fwrite");
     }
     if (fclose(out)) error("failed fclose");
 
diff --git a/trees.c b/trees.c
index 79cab9f..62411a7 100644
--- a/trees.c
+++ b/trees.c
@@ -1011,7 +1011,7 @@
     if (s->bi_valid > 8) {
         put_short(s, s->bi_buf);
     } else if (s->bi_valid > 0) {
-        put_byte(s, s->bi_buf);
+        put_byte(s, (Byte)s->bi_buf);
     }
     s->bi_buf = 0;
     s->bi_valid = 0;
diff --git a/zconf.h b/zconf.h
index 29496d7..f08793b 100644
--- a/zconf.h
+++ b/zconf.h
@@ -3,7 +3,7 @@
  * For conditions of distribution and use, see copyright notice in zlib.h 
  */
 
-/* $Id: zconf.h,v 1.7 1995/04/12 20:42:28 jloup Exp $ */
+/* $Id: zconf.h,v 1.8 1995/04/14 20:59:22 jloup Exp $ */
 
 #ifndef _ZCONF_H
 #define _ZCONF_H
diff --git a/zlib.h b/zlib.h
index d1f2ca9..6983fb7 100644
--- a/zlib.h
+++ b/zlib.h
@@ -1,5 +1,5 @@
 /* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 0.7  April 14th, 1995.
+  version 0.79  April 28th, 1995.
 
   Copyright (C) 1995 Jean-loup Gailly and Mark Adler
 
@@ -28,7 +28,7 @@
 
 #include "zconf.h"
 
-#define ZLIB_VERSION "0.7"
+#define ZLIB_VERSION "0.79"
 
 /* 
      The 'zlib' compression library provides in-memory compression and
@@ -88,7 +88,7 @@
 
    zalloc must return Z_NULL if there is not enough memory for the object.
    On 16-bit systems, the functions zalloc and zfree must be able to allocate
-   exactly 65536 bytes, but will not be require to allocate more than this
+   exactly 65536 bytes, but will not be required to allocate more than this
    if the symbol MAXSEG_64K is defined (see zconf.h).
 
    The fields total_in and total_out can be used for statistics or
@@ -152,10 +152,10 @@
    to level 6).
 
      deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_STREAM_ERROR if the stream state was inconsistent (such
-   as zalloc being NULL). msg is set to null if there is no error message.
-   deflateInit does not perform any compression: this will be done by
-   deflate().  */
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level.
+   msg is set to null if there is no error message.  deflateInit does not
+   perform any compression: this will be done by deflate().
+*/
 
 
 extern int deflate __P((z_stream *strm, int flush));
@@ -164,8 +164,8 @@
 
   - Compress more input starting at next_in and update next_in and avail_in
     accordingly. If not all input can be processed (because there is not
-    enough room in the output buffer), next_in is updated and processing
-    will resume at this point for the next call of deflate().
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
 
   - Provide more output starting at next_out and update next_out and avail_out
     accordingly. This action is forced if the parameter flush is non zero.
@@ -175,20 +175,21 @@
 
   Before the call of deflate(), the application should ensure that at least
   one of the actions is possible, by providing more input and/or consuming
-  more output, and updating avail_in or avail_out accordingly.
-  The application can consume the compressed output when the output
-  buffer is full (avail_out == 0), or after each call of deflate().
+  more output, and updating avail_in or avail_out accordingly; avail_out
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (avail_out == 0), or after each call of deflate().
 
     If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression
-  block is byte aligned and flushed to the output buffer so that the
-  decompressor can get all input data available so far; if the compression
-  method is 8 (deflate without partial flush capability), the current block
-  is terminated. If flush is set to Z_FULL_FLUSH, the compression block is
-  terminated, a special marker is output and the compression dictionary is
-  discarded; this is useful to allow the decompressor to synchronize if one
-  compressed block has been damaged.
-    Flushing degrades compression and so should be used only when necessary.
-  Using Z_FULL_FLUSH too often can seriously degrade the compression.
+  block is terminated and flushed to the output buffer so that the
+  decompressor can get all input data available so far. For method 9, a future
+  variant on method 8, the current block will be flushed but not terminated.
+  If flush is set to Z_FULL_FLUSH, the compression block is terminated, a
+  special marker is output and the compression dictionary is discarded; this
+  is useful to allow the decompressor to synchronize if one compressed block
+  has been damaged (see inflateSync below).  Flushing degrades compression and
+  so should be used only when necessary.  Using Z_FULL_FLUSH too often can
+  seriously degrade the compression.
 
     If the parameter flush is set to Z_FINISH, all pending input is
   processed and all pending output is flushed. The next operation on this
@@ -197,19 +198,18 @@
   or a call of deflateEnd to deallocate the compression state. Z_FINISH can
   be used immediately after deflateInit if all the compression is to be
   done in a single step. In this case, avail_out must be at least 0.1%
-  larger than avail_in plus 8 bytes.
+  larger than avail_in plus 12 bytes.
 
-    deflate() may update strm->data_type if it can make a good guess about
+    deflate() may update data_type if it can make a good guess about
   the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
   binary. This field is only for information purposes and does not affect
   the compression algorithm in any manner.
 
-    deflate() return Z_OK if some progress has been made (more input processed
+    deflate() returns Z_OK if some progress has been made (more input processed
   or more output produced), Z_STREAM_ERROR if the stream state was
   inconsistent (for example if next_in or next_out was NULL), Z_BUF_ERROR if
   no progress is possible or if there was not enough room in the output buffer
-  when Z_FINISH is used.
-*/
+  when Z_FINISH is used. ??? to be changed (use Z_STEAM_END) */
 
 
 extern int deflateEnd __P((z_stream *strm));
@@ -232,8 +232,7 @@
    functions.
 
      inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_STREAM_ERROR if the stream state was inconsistent (such
-   as zalloc being NULL). msg is set to null if there is no error message.
+   enough memory.  msg is set to null if there is no error message.
    inflateInit does not perform any decompression: this will be done by
    inflate().
 */
@@ -255,8 +254,9 @@
   Before the call of inflate(), the application should ensure that at least
   one of the actions is possible, by providing more input and/or consuming
   more output, and updating the next_* and avail_* values accordingly.
-  The application can consume the uncompressed output when the output
-  buffer is full (avail_out == 0), or after each call of inflate().
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate().
 
     If the parameter flush is set to Z_PARTIAL_FLUSH, inflate flushes as much
   output as possible to the output buffer. The flushing behavior of inflate is
@@ -275,13 +275,13 @@
 
     inflate() returns Z_OK if some progress has been made (more input
   processed or more output produced), Z_STREAM_END if the end of the
-  compressed data has been reached, Z_DATA_ERROR if the input data was
-  corrupted, Z_STREAM_ERROR if the stream structure was inconsistent (for
-  example if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough
-  memory, Z_BUF_ERROR if no progress is possible or if there was not enough
-  room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR case,
-  the application may then call inflateSync to look for a good compression
-  block.
+  compressed data has been reached and all uncompressed output has been
+  produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
+  the stream structure was inconsistent (for example if next_in or next_out
+  was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
+  progress is possible or if there was not enough room in the output buffer
+  when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
+  call inflateSync to look for a good compression block.
 */
 
 
@@ -318,9 +318,9 @@
 
      The windowBits parameter is the base two logarithm of the window size
    (the size of the history buffer).  It should be in the range 8..15 for this
-   version of the library (the value 16 will be allowed soon). Larger values
-   of this parameter result in better compression at the expense of memory
-   usage. The default value is 15 if deflateInit is used instead.
+   version of the library (the value 16 will be allowed for method 9). Larger
+   values of this parameter result in better compression at the expense of
+   memory usage. The default value is 15 if deflateInit is used instead.
 
     The memLevel parameter specifies how much memory should be allocated
    for the internal compression state. memLevel=1 uses minimum memory but
@@ -338,8 +338,8 @@
 
      If next_in is not null, the library will use this buffer to hold also
    some history information; the buffer must either hold the entire input
-   data, or have at least (1<<windowBits) bytes and be writable. If next_in is
-   null, the library will allocate its own history buffer (and leave next_in
+   data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in
+   is null, the library will allocate its own history buffer (and leave next_in
    null). next_out need not be provided here but must be provided by the
    application for the next call of deflate().
 
@@ -350,8 +350,7 @@
    reset by the library in this case.
 
       deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
-   not enough memory, Z_STREAM_ERROR if the stream state was inconsistent
-   (such as zalloc being NULL) or the parameters are invalid (such as
+   not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
    an invalid method). msg is set to null if there is no error message.
    deflateInit2 does not perform any compression: this will be done by
    deflate().
@@ -406,7 +405,7 @@
 
      If next_out is not null, the library will use this buffer for the history
    buffer; the buffer must either be large enough to hold the entire output
-   data, or have at least 1<<(windowBits-1) bytes.  If next_out is null, the
+   data, or have at least 1<<windowBits bytes.  If next_out is null, the
    library will allocate its own buffer (and leave next_out null). next_in
    need not be provided here but must be provided by the application for the
    next call of inflate().
@@ -418,9 +417,8 @@
    avail_out is zero and all output has been consumed.
 
       inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
-   not enough memory, Z_STREAM_ERROR if the stream state was inconsistent
-   (such as zalloc being NULL) or the parameters are invalid (such as
-   windowBits < 9). msg is set to null if there is no error message.
+   not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
+   windowBits < 8). msg is set to null if there is no error message.
    inflateInit2 does not perform any compression: this will be done by
    inflate().
 */
@@ -585,7 +583,7 @@
 /*
      Update a running crc with the bytes buf[0..len-1] and return the updated
    crc. If buf is NULL, this function returns the required initial value
-   for the crc (0). Pre- and post-conditioning (one's complement) is performed
+   for the crc. Pre- and post-conditioning (one's complement) is performed
    within this function so it shouldn't be done by the application.
    Usage example:
 
diff --git a/zutil.c b/zutil.c
index 1a2e7ef..9fd4ecc 100644
--- a/zutil.c
+++ b/zutil.c
@@ -3,12 +3,14 @@
  * For conditions of distribution and use, see copyright notice in zlib.h 
  */
 
-/* $Id: zutil.c,v 1.3 1995/04/10 09:52:26 jloup Exp $ */
+/* $Id: zutil.c,v 1.5 1995/04/14 21:30:23 jloup Exp $ */
 
 #include <stdio.h>
 
 #include "zutil.h"
 
+extern void exit __P((int));
+
 char *zlib_version = ZLIB_VERSION;
 
 char *z_errmsg[] = {
@@ -136,7 +138,7 @@
 
 void  zcfree (voidp opaque, voidp ptr)
 {
-    return _hfree(ptr);
+    _hfree(ptr);
 }
 
 #  endif /* __TURBOC__ ? */
diff --git a/zutil.h b/zutil.h
index a1108e6..20b20f5 100644
--- a/zutil.h
+++ b/zutil.h
@@ -8,7 +8,7 @@
    subject to change. Applications should only use zlib.h.
  */
 
-/* $Id: zutil.h,v 1.4 1995/04/14 10:22:17 jloup Exp $ */
+/* $Id: zutil.h,v 1.5 1995/04/14 21:22:38 jloup Exp $ */
 
 #ifndef _Z_UTIL_H
 #define _Z_UTIL_H
@@ -20,6 +20,10 @@
 #else
     extern int errno;
 #endif
+#ifdef __STDC__
+#  include <string.h>
+#  include <memory.h>
+#endif
 
 #ifndef local
 #  define local static
@@ -154,13 +158,16 @@
 #endif
 
 
+typedef uLong (*check_func) __P((uLong check, Byte *buf, uInt len));
+
 extern void z_error    __P((char *m));
 
 voidp zcalloc __P((voidp opaque, unsigned items, unsigned size));
 void  zcfree  __P((voidp opaque, voidp ptr));
 
-#define ZALLOC(strm, items, size) (*strm->zalloc)(strm->opaque, items, size)
-#define ZFREE(strm, addr)         (*strm->zfree) (strm->opaque, (voidp)addr)
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidp)(addr))
 #define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
 
 #endif /* _Z_UTIL_H */