| Index: third_party/zlib/deflate.c
 | 
| ===================================================================
 | 
| --- third_party/zlib/deflate.c	(revision 113739)
 | 
| +++ third_party/zlib/deflate.c	(working copy)
 | 
| @@ -1,5 +1,5 @@
 | 
|  /* deflate.c -- compress data using the deflation algorithm
 | 
| - * Copyright (C) 1995-2005 Jean-loup Gailly.
 | 
| + * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
 | 
|   * For conditions of distribution and use, see copyright notice in zlib.h
 | 
|   */
 | 
|  
 | 
| @@ -47,12 +47,12 @@
 | 
|   *
 | 
|   */
 | 
|  
 | 
| -/* @(#) $Id: deflate.c,v 3.6 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */
 | 
| +/* @(#) $Id$ */
 | 
|  
 | 
|  #include "deflate.h"
 | 
|  
 | 
|  const char deflate_copyright[] =
 | 
| -   " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly ";
 | 
| +   " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and 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
 | 
| @@ -79,19 +79,18 @@
 | 
|  #ifndef FASTEST
 | 
|  local block_state deflate_slow   OF((deflate_state *s, int flush));
 | 
|  #endif
 | 
| +local block_state deflate_rle    OF((deflate_state *s, int flush));
 | 
| +local block_state deflate_huff   OF((deflate_state *s, int flush));
 | 
|  local void lm_init        OF((deflate_state *s));
 | 
|  local void putShortMSB    OF((deflate_state *s, uInt b));
 | 
|  local void flush_pending  OF((z_streamp strm));
 | 
|  local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
 | 
| -#ifndef FASTEST
 | 
|  #ifdef ASMV
 | 
|        void match_init OF((void)); /* asm code initialization */
 | 
|        uInt longest_match  OF((deflate_state *s, IPos cur_match));
 | 
|  #else
 | 
|  local uInt longest_match  OF((deflate_state *s, IPos cur_match));
 | 
|  #endif
 | 
| -#endif
 | 
| -local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
 | 
|  
 | 
|  #ifdef DEBUG
 | 
|  local  void check_match OF((deflate_state *s, IPos start, IPos match,
 | 
| @@ -110,11 +109,6 @@
 | 
|  #endif
 | 
|  /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
 | 
|  
 | 
| -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
 | 
| -/* Minimum amount of lookahead, except at the end of the input file.
 | 
| - * See deflate.c for comments about the MIN_MATCH+1.
 | 
| - */
 | 
| -
 | 
|  /* Values for max_lazy_match, good_match and max_chain_length, depending on
 | 
|   * the desired pack level (0..9). The values given below have been tuned to
 | 
|   * exclude worst case performance for pathological files. Better values may be
 | 
| @@ -288,6 +282,8 @@
 | 
|      s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
 | 
|      s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
 | 
|  
 | 
| +    s->high_water = 0;      /* nothing written to s->window yet */
 | 
| +
 | 
|      s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
 | 
|  
 | 
|      overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
 | 
| @@ -332,8 +328,8 @@
 | 
|          strm->adler = adler32(strm->adler, dictionary, dictLength);
 | 
|  
 | 
|      if (length < MIN_MATCH) return Z_OK;
 | 
| -    if (length > MAX_DIST(s)) {
 | 
| -        length = MAX_DIST(s);
 | 
| +    if (length > s->w_size) {
 | 
| +        length = s->w_size;
 | 
|          dictionary += dictLength - length; /* use the tail of the dictionary */
 | 
|      }
 | 
|      zmemcpy(s->window, dictionary, length);
 | 
| @@ -435,9 +431,10 @@
 | 
|      }
 | 
|      func = configuration_table[s->level].func;
 | 
|  
 | 
| -    if (func != configuration_table[level].func && strm->total_in != 0) {
 | 
| +    if ((strategy != s->strategy || func != configuration_table[level].func) &&
 | 
| +        strm->total_in != 0) {
 | 
|          /* Flush the last buffer: */
 | 
| -        err = deflate(strm, Z_PARTIAL_FLUSH);
 | 
| +        err = deflate(strm, Z_BLOCK);
 | 
|      }
 | 
|      if (s->level != level) {
 | 
|          s->level = level;
 | 
| @@ -481,33 +478,66 @@
 | 
|   * resulting from using fixed blocks instead of stored blocks, which deflate
 | 
|   * can emit on compressed data for some combinations of the parameters.
 | 
|   *
 | 
| - * This function could be more sophisticated to provide closer upper bounds
 | 
| - * for every combination of windowBits and memLevel, as well as wrap.
 | 
| - * But even the conservative upper bound of about 14% expansion does not
 | 
| - * seem onerous for output buffer allocation.
 | 
| + * This function could be more sophisticated to provide closer upper bounds for
 | 
| + * every combination of windowBits and memLevel.  But even the conservative
 | 
| + * upper bound of about 14% expansion does not seem onerous for output buffer
 | 
| + * allocation.
 | 
|   */
 | 
|  uLong ZEXPORT deflateBound(strm, sourceLen)
 | 
|      z_streamp strm;
 | 
|      uLong sourceLen;
 | 
|  {
 | 
|      deflate_state *s;
 | 
| -    uLong destLen;
 | 
| +    uLong complen, wraplen;
 | 
| +    Bytef *str;
 | 
|  
 | 
| -    /* conservative upper bound */
 | 
| -    destLen = sourceLen +
 | 
| -              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11;
 | 
| +    /* conservative upper bound for compressed data */
 | 
| +    complen = sourceLen +
 | 
| +              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
 | 
|  
 | 
| -    /* if can't get parameters, return conservative bound */
 | 
| +    /* if can't get parameters, return conservative bound plus zlib wrapper */
 | 
|      if (strm == Z_NULL || strm->state == Z_NULL)
 | 
| -        return destLen;
 | 
| +        return complen + 6;
 | 
|  
 | 
| +    /* compute wrapper length */
 | 
| +    s = strm->state;
 | 
| +    switch (s->wrap) {
 | 
| +    case 0:                                 /* raw deflate */
 | 
| +        wraplen = 0;
 | 
| +        break;
 | 
| +    case 1:                                 /* zlib wrapper */
 | 
| +        wraplen = 6 + (s->strstart ? 4 : 0);
 | 
| +        break;
 | 
| +    case 2:                                 /* gzip wrapper */
 | 
| +        wraplen = 18;
 | 
| +        if (s->gzhead != Z_NULL) {          /* user-supplied gzip header */
 | 
| +            if (s->gzhead->extra != Z_NULL)
 | 
| +                wraplen += 2 + s->gzhead->extra_len;
 | 
| +            str = s->gzhead->name;
 | 
| +            if (str != Z_NULL)
 | 
| +                do {
 | 
| +                    wraplen++;
 | 
| +                } while (*str++);
 | 
| +            str = s->gzhead->comment;
 | 
| +            if (str != Z_NULL)
 | 
| +                do {
 | 
| +                    wraplen++;
 | 
| +                } while (*str++);
 | 
| +            if (s->gzhead->hcrc)
 | 
| +                wraplen += 2;
 | 
| +        }
 | 
| +        break;
 | 
| +    default:                                /* for compiler happiness */
 | 
| +        wraplen = 6;
 | 
| +    }
 | 
| +
 | 
|      /* if not default parameters, return conservative bound */
 | 
| -    s = strm->state;
 | 
|      if (s->w_bits != 15 || s->hash_bits != 8 + 7)
 | 
| -        return destLen;
 | 
| +        return complen + wraplen;
 | 
|  
 | 
|      /* default settings: return tight bound for that case */
 | 
| -    return compressBound(sourceLen);
 | 
| +    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
 | 
| +           (sourceLen >> 25) + 13 - 6 + wraplen;
 | 
|  }
 | 
|  
 | 
|  /* =========================================================================
 | 
| @@ -557,7 +587,7 @@
 | 
|      deflate_state *s;
 | 
|  
 | 
|      if (strm == Z_NULL || strm->state == Z_NULL ||
 | 
| -        flush > Z_FINISH || flush < 0) {
 | 
| +        flush > Z_BLOCK || flush < 0) {
 | 
|          return Z_STREAM_ERROR;
 | 
|      }
 | 
|      s = strm->state;
 | 
| @@ -581,7 +611,7 @@
 | 
|              put_byte(s, 31);
 | 
|              put_byte(s, 139);
 | 
|              put_byte(s, 8);
 | 
| -            if (s->gzhead == NULL) {
 | 
| +            if (s->gzhead == Z_NULL) {
 | 
|                  put_byte(s, 0);
 | 
|                  put_byte(s, 0);
 | 
|                  put_byte(s, 0);
 | 
| @@ -608,7 +638,7 @@
 | 
|                              (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
 | 
|                               4 : 0));
 | 
|                  put_byte(s, s->gzhead->os & 0xff);
 | 
| -                if (s->gzhead->extra != NULL) {
 | 
| +                if (s->gzhead->extra != Z_NULL) {
 | 
|                      put_byte(s, s->gzhead->extra_len & 0xff);
 | 
|                      put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
 | 
|                  }
 | 
| @@ -650,7 +680,7 @@
 | 
|      }
 | 
|  #ifdef GZIP
 | 
|      if (s->status == EXTRA_STATE) {
 | 
| -        if (s->gzhead->extra != NULL) {
 | 
| +        if (s->gzhead->extra != Z_NULL) {
 | 
|              uInt beg = s->pending;  /* start of bytes to update crc */
 | 
|  
 | 
|              while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
 | 
| @@ -678,7 +708,7 @@
 | 
|              s->status = NAME_STATE;
 | 
|      }
 | 
|      if (s->status == NAME_STATE) {
 | 
| -        if (s->gzhead->name != NULL) {
 | 
| +        if (s->gzhead->name != Z_NULL) {
 | 
|              uInt beg = s->pending;  /* start of bytes to update crc */
 | 
|              int val;
 | 
|  
 | 
| @@ -709,7 +739,7 @@
 | 
|              s->status = COMMENT_STATE;
 | 
|      }
 | 
|      if (s->status == COMMENT_STATE) {
 | 
| -        if (s->gzhead->comment != NULL) {
 | 
| +        if (s->gzhead->comment != Z_NULL) {
 | 
|              uInt beg = s->pending;  /* start of bytes to update crc */
 | 
|              int val;
 | 
|  
 | 
| @@ -787,7 +817,9 @@
 | 
|          (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
 | 
|          block_state bstate;
 | 
|  
 | 
| -        bstate = (*(configuration_table[s->level].func))(s, flush);
 | 
| +        bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
 | 
| +                    (s->strategy == Z_RLE ? deflate_rle(s, flush) :
 | 
| +                        (*(configuration_table[s->level].func))(s, flush));
 | 
|  
 | 
|          if (bstate == finish_started || bstate == finish_done) {
 | 
|              s->status = FINISH_STATE;
 | 
| @@ -808,13 +840,17 @@
 | 
|          if (bstate == block_done) {
 | 
|              if (flush == Z_PARTIAL_FLUSH) {
 | 
|                  _tr_align(s);
 | 
| -            } else { /* FULL_FLUSH or SYNC_FLUSH */
 | 
| +            } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
 | 
|                  _tr_stored_block(s, (char*)0, 0L, 0);
 | 
|                  /* For a full flush, this empty block will be recognized
 | 
|                   * as a special marker by inflate_sync().
 | 
|                   */
 | 
|                  if (flush == Z_FULL_FLUSH) {
 | 
|                      CLEAR_HASH(s);             /* forget history */
 | 
| +                    if (s->lookahead == 0) {
 | 
| +                        s->strstart = 0;
 | 
| +                        s->block_start = 0L;
 | 
| +                    }
 | 
|                  }
 | 
|              }
 | 
|              flush_pending(strm);
 | 
| @@ -1167,12 +1203,13 @@
 | 
|      return s->lookahead;
 | 
|  }
 | 
|  #endif /* ASMV */
 | 
| -#endif /* FASTEST */
 | 
|  
 | 
| +#else /* FASTEST */
 | 
| +
 | 
|  /* ---------------------------------------------------------------------------
 | 
| - * Optimized version for level == 1 or strategy == Z_RLE only
 | 
| + * Optimized version for FASTEST only
 | 
|   */
 | 
| -local uInt longest_match_fast(s, cur_match)
 | 
| +local uInt longest_match(s, cur_match)
 | 
|      deflate_state *s;
 | 
|      IPos cur_match;                             /* current match */
 | 
|  {
 | 
| @@ -1225,6 +1262,8 @@
 | 
|      return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
 | 
|  }
 | 
|  
 | 
| +#endif /* FASTEST */
 | 
| +
 | 
|  #ifdef DEBUG
 | 
|  /* ===========================================================================
 | 
|   * Check that the match at match_start is indeed a match.
 | 
| @@ -1303,7 +1342,6 @@
 | 
|                 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 {
 | 
| @@ -1355,27 +1393,61 @@
 | 
|           */
 | 
|  
 | 
|      } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
 | 
| +
 | 
| +    /* If the WIN_INIT bytes after the end of the current data have never been
 | 
| +     * written, then zero those bytes in order to avoid memory check reports of
 | 
| +     * the use of uninitialized (or uninitialised as Julian writes) bytes by
 | 
| +     * the longest match routines.  Update the high water mark for the next
 | 
| +     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
 | 
| +     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
 | 
| +     */
 | 
| +    if (s->high_water < s->window_size) {
 | 
| +        ulg curr = s->strstart + (ulg)(s->lookahead);
 | 
| +        ulg init;
 | 
| +
 | 
| +        if (s->high_water < curr) {
 | 
| +            /* Previous high water mark below current data -- zero WIN_INIT
 | 
| +             * bytes or up to end of window, whichever is less.
 | 
| +             */
 | 
| +            init = s->window_size - curr;
 | 
| +            if (init > WIN_INIT)
 | 
| +                init = WIN_INIT;
 | 
| +            zmemzero(s->window + curr, (unsigned)init);
 | 
| +            s->high_water = curr + init;
 | 
| +        }
 | 
| +        else if (s->high_water < (ulg)curr + WIN_INIT) {
 | 
| +            /* High water mark at or above current data, but below current data
 | 
| +             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
 | 
| +             * to end of window, whichever is less.
 | 
| +             */
 | 
| +            init = (ulg)curr + WIN_INIT - s->high_water;
 | 
| +            if (init > s->window_size - s->high_water)
 | 
| +                init = s->window_size - s->high_water;
 | 
| +            zmemzero(s->window + s->high_water, (unsigned)init);
 | 
| +            s->high_water += init;
 | 
| +        }
 | 
| +    }
 | 
|  }
 | 
|  
 | 
|  /* ===========================================================================
 | 
|   * Flush the current block, with given end-of-file flag.
 | 
|   * IN assertion: strstart is set to the end of the current match.
 | 
|   */
 | 
| -#define FLUSH_BLOCK_ONLY(s, eof) { \
 | 
| +#define FLUSH_BLOCK_ONLY(s, last) { \
 | 
|     _tr_flush_block(s, (s->block_start >= 0L ? \
 | 
|                     (charf *)&s->window[(unsigned)s->block_start] : \
 | 
|                     (charf *)Z_NULL), \
 | 
|                  (ulg)((long)s->strstart - s->block_start), \
 | 
| -                (eof)); \
 | 
| +                (last)); \
 | 
|     s->block_start = s->strstart; \
 | 
|     flush_pending(s->strm); \
 | 
|     Tracev((stderr,"[FLUSH]")); \
 | 
|  }
 | 
|  
 | 
|  /* Same but force premature exit if necessary. */
 | 
| -#define FLUSH_BLOCK(s, eof) { \
 | 
| -   FLUSH_BLOCK_ONLY(s, eof); \
 | 
| -   if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
 | 
| +#define FLUSH_BLOCK(s, last) { \
 | 
| +   FLUSH_BLOCK_ONLY(s, last); \
 | 
| +   if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
 | 
|  }
 | 
|  
 | 
|  /* ===========================================================================
 | 
| @@ -1449,7 +1521,7 @@
 | 
|      deflate_state *s;
 | 
|      int flush;
 | 
|  {
 | 
| -    IPos hash_head = NIL; /* head of the hash chain */
 | 
| +    IPos hash_head;       /* head of the hash chain */
 | 
|      int bflush;           /* set if current block must be flushed */
 | 
|  
 | 
|      for (;;) {
 | 
| @@ -1469,6 +1541,7 @@
 | 
|          /* Insert the string window[strstart .. strstart+2] in the
 | 
|           * dictionary, and set hash_head to the head of the hash chain:
 | 
|           */
 | 
| +        hash_head = NIL;
 | 
|          if (s->lookahead >= MIN_MATCH) {
 | 
|              INSERT_STRING(s, s->strstart, hash_head);
 | 
|          }
 | 
| @@ -1481,19 +1554,8 @@
 | 
|               * of window index 0 (in particular we have to avoid a match
 | 
|               * of the string with itself at the start of the input file).
 | 
|               */
 | 
| -#ifdef FASTEST
 | 
| -            if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
 | 
| -                (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
 | 
| -                s->match_length = longest_match_fast (s, hash_head);
 | 
| -            }
 | 
| -#else
 | 
| -            if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
 | 
| -                s->match_length = longest_match (s, hash_head);
 | 
| -            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
 | 
| -                s->match_length = longest_match_fast (s, hash_head);
 | 
| -            }
 | 
| -#endif
 | 
| -            /* longest_match() or longest_match_fast() sets match_start */
 | 
| +            s->match_length = longest_match (s, hash_head);
 | 
| +            /* longest_match() sets match_start */
 | 
|          }
 | 
|          if (s->match_length >= MIN_MATCH) {
 | 
|              check_match(s, s->strstart, s->match_start, s->match_length);
 | 
| @@ -1555,7 +1617,7 @@
 | 
|      deflate_state *s;
 | 
|      int flush;
 | 
|  {
 | 
| -    IPos hash_head = NIL;    /* head of hash chain */
 | 
| +    IPos hash_head;          /* head of hash chain */
 | 
|      int bflush;              /* set if current block must be flushed */
 | 
|  
 | 
|      /* Process the input block. */
 | 
| @@ -1576,6 +1638,7 @@
 | 
|          /* Insert the string window[strstart .. strstart+2] in the
 | 
|           * dictionary, and set hash_head to the head of the hash chain:
 | 
|           */
 | 
| +        hash_head = NIL;
 | 
|          if (s->lookahead >= MIN_MATCH) {
 | 
|              INSERT_STRING(s, s->strstart, hash_head);
 | 
|          }
 | 
| @@ -1591,12 +1654,8 @@
 | 
|               * of window index 0 (in particular we have to avoid a match
 | 
|               * of the string with itself at the start of the input file).
 | 
|               */
 | 
| -            if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
 | 
| -                s->match_length = longest_match (s, hash_head);
 | 
| -            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
 | 
| -                s->match_length = longest_match_fast (s, hash_head);
 | 
| -            }
 | 
| -            /* longest_match() or longest_match_fast() sets match_start */
 | 
| +            s->match_length = longest_match (s, hash_head);
 | 
| +            /* longest_match() sets match_start */
 | 
|  
 | 
|              if (s->match_length <= 5 && (s->strategy == Z_FILTERED
 | 
|  #if TOO_FAR <= 32767
 | 
| @@ -1674,7 +1733,6 @@
 | 
|  }
 | 
|  #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
 | 
| @@ -1684,11 +1742,9 @@
 | 
|      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 */
 | 
| +    int bflush;             /* set if current block must be flushed */
 | 
| +    uInt prev;              /* byte at distance one to match */
 | 
| +    Bytef *scan, *strend;   /* scan goes up to strend for length of run */
 | 
|  
 | 
|      for (;;) {
 | 
|          /* Make sure that we always have enough lookahead, except
 | 
| @@ -1704,23 +1760,33 @@
 | 
|          }
 | 
|  
 | 
|          /* 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;
 | 
| +        s->match_length = 0;
 | 
| +        if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
 | 
|              scan = s->window + s->strstart - 1;
 | 
| -            prev = *scan++;
 | 
| -            do {
 | 
| -                if (*scan++ != prev)
 | 
| -                    break;
 | 
| -            } while (++run < max);
 | 
| +            prev = *scan;
 | 
| +            if (prev == *++scan && prev == *++scan && prev == *++scan) {
 | 
| +                strend = s->window + s->strstart + MAX_MATCH;
 | 
| +                do {
 | 
| +                } while (prev == *++scan && prev == *++scan &&
 | 
| +                         prev == *++scan && prev == *++scan &&
 | 
| +                         prev == *++scan && prev == *++scan &&
 | 
| +                         prev == *++scan && prev == *++scan &&
 | 
| +                         scan < strend);
 | 
| +                s->match_length = MAX_MATCH - (int)(strend - scan);
 | 
| +                if (s->match_length > s->lookahead)
 | 
| +                    s->match_length = s->lookahead;
 | 
| +            }
 | 
|          }
 | 
|  
 | 
|          /* 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;
 | 
| +        if (s->match_length >= MIN_MATCH) {
 | 
| +            check_match(s, s->strstart, s->strstart - 1, s->match_length);
 | 
| +
 | 
| +            _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
 | 
| +
 | 
| +            s->lookahead -= s->match_length;
 | 
| +            s->strstart += s->match_length;
 | 
| +            s->match_length = 0;
 | 
|          } else {
 | 
|              /* No match, output a literal byte */
 | 
|              Tracevv((stderr,"%c", s->window[s->strstart]));
 | 
| @@ -1733,4 +1799,36 @@
 | 
|      FLUSH_BLOCK(s, flush == Z_FINISH);
 | 
|      return flush == Z_FINISH ? finish_done : block_done;
 | 
|  }
 | 
| -#endif
 | 
| +
 | 
| +/* ===========================================================================
 | 
| + * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
 | 
| + * (It will be regenerated if this run of deflate switches away from Huffman.)
 | 
| + */
 | 
| +local block_state deflate_huff(s, flush)
 | 
| +    deflate_state *s;
 | 
| +    int flush;
 | 
| +{
 | 
| +    int bflush;             /* set if current block must be flushed */
 | 
| +
 | 
| +    for (;;) {
 | 
| +        /* Make sure that we have a literal to write. */
 | 
| +        if (s->lookahead == 0) {
 | 
| +            fill_window(s);
 | 
| +            if (s->lookahead == 0) {
 | 
| +                if (flush == Z_NO_FLUSH)
 | 
| +                    return need_more;
 | 
| +                break;      /* flush the current block */
 | 
| +            }
 | 
| +        }
 | 
| +
 | 
| +        /* Output a literal byte */
 | 
| +        s->match_length = 0;
 | 
| +        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;
 | 
| +}
 | 
| 
 |