gzip cleanup part #10
authorDenis Vlasenko <vda.linux@googlemail.com>
Sun, 7 Jan 2007 19:40:50 +0000 (19:40 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sun, 7 Jan 2007 19:40:50 +0000 (19:40 -0000)
archival/gzip.c

index c882a4a2a1036c2c7227a5d22f205add1a81c7d0..034bda005aca3ff83a4f4554195948e790ac6bb2 100644 (file)
@@ -201,7 +201,8 @@ typedef unsigned IPos;
        array = xzalloc((size_t)(((size)+1L)/2) * 2*sizeof(type)); \
 }
 
-#define FREE(array) { \
+#define FREE(array) \
+{ \
        free(array); \
        array = NULL; \
 }
@@ -272,21 +273,6 @@ enum {
 };
 
 
-/* ===========================================================================
- */
-static void fill_window(void);
-
-static int longest_match(IPos cur_match);
-
-#ifdef DEBUG
-static void check_match(IPos start, IPos match, int length);
-#endif
-
-
-/* from trees.c */
-static int ct_tally(int dist, int lc);
-static ulg flush_block(char *buf, ulg stored_len, int eof);
-
 /* global buffers */
 
 /* To save memory for 16 bit systems, some arrays are overlaid between
@@ -585,6 +571,65 @@ static void copy_block(char *buf, unsigned len, int header)
 }
 
 
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead, and sets eofile if end of input file.
+ * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0
+ * OUT assertions: at least one byte has been read, or eofile is set;
+ *    file reads are performed for at least two bytes (required for the
+ *    translate_eol option).
+ */
+static void fill_window(void)
+{
+       unsigned n, m;
+       unsigned more = WINDOW_SIZE - lookahead - strstart;
+       /* Amount of free space at the end of the window. */
+
+       /* If the window is almost full and there is insufficient lookahead,
+        * move the upper half to the lower one to make room in the upper half.
+        */
+       if (more == (unsigned) -1) {
+               /* Very unlikely, but possible on 16 bit machine if strstart == 0
+                * and lookahead == 1 (input done one byte at time)
+                */
+               more--;
+       } else if (strstart >= WSIZE + MAX_DIST) {
+               /* By the IN assertion, the window is not empty so we can't confuse
+                * more == 0 with more == 64K on a 16 bit machine.
+                */
+               Assert(WINDOW_SIZE == 2 * WSIZE, "no sliding with BIG_MEM");
+
+               memcpy(window, window + WSIZE, WSIZE);
+               match_start -= WSIZE;
+               strstart -= WSIZE;      /* we now have strstart >= MAX_DIST: */
+
+               block_start -= WSIZE;
+
+               for (n = 0; n < HASH_SIZE; n++) {
+                       m = head[n];
+                       head[n] = (Pos) (m >= WSIZE ? m - WSIZE : 0);
+               }
+               for (n = 0; n < WSIZE; n++) {
+                       m = prev[n];
+                       prev[n] = (Pos) (m >= WSIZE ? m - WSIZE : 0);
+                       /* If n is not on any hash chain, prev[n] is garbage but
+                        * its value will never be used.
+                        */
+               }
+               more += WSIZE;
+       }
+       /* At this point, more >= 2 */
+       if (!eofile) {
+               n = file_read(window + strstart + lookahead, more);
+               if (n == 0 || n == (unsigned) -1) {
+                       eofile = 1;
+               } else {
+                       lookahead += n;
+               }
+       }
+}
+
+
 /* ===========================================================================
  * Update a hash value with the given input byte
  * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
@@ -746,292 +791,92 @@ static void check_match(IPos start, IPos match, int length)
 #endif
 
 
-/* ===========================================================================
- * Fill the window when the lookahead becomes insufficient.
- * Updates strstart and lookahead, and sets eofile if end of input file.
- * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0
- * OUT assertions: at least one byte has been read, or eofile is set;
- *    file reads are performed for at least two bytes (required for the
- *    translate_eol option).
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
  */
-static void fill_window(void)
-{
-       unsigned n, m;
-       unsigned more = WINDOW_SIZE - lookahead - strstart;
-       /* Amount of free space at the end of the window. */
 
-       /* If the window is almost full and there is insufficient lookahead,
-        * move the upper half to the lower one to make room in the upper half.
-        */
-       if (more == (unsigned) -1) {
-               /* Very unlikely, but possible on 16 bit machine if strstart == 0
-                * and lookahead == 1 (input done one byte at time)
-                */
-               more--;
-       } else if (strstart >= WSIZE + MAX_DIST) {
-               /* By the IN assertion, the window is not empty so we can't confuse
-                * more == 0 with more == 64K on a 16 bit machine.
-                */
-               Assert(WINDOW_SIZE == 2 * WSIZE, "no sliding with BIG_MEM");
+/*  PURPOSE
+ *      Encode various sets of source values using variable-length
+ *      binary code trees.
+ *
+ *  DISCUSSION
+ *      The PKZIP "deflation" process uses several Huffman trees. The more
+ *      common source values are represented by shorter bit sequences.
+ *
+ *      Each code tree is stored in the ZIP file in a compressed form
+ *      which is itself a Huffman encoding of the lengths of
+ *      all the code strings (in ascending order by source values).
+ *      The actual code strings are reconstructed from the lengths in
+ *      the UNZIP process, as described in the "application note"
+ *      (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program.
+ *
+ *  REFERENCES
+ *      Lynch, Thomas J.
+ *          Data Compression:  Techniques and Applications, pp. 53-55.
+ *          Lifetime Learning Publications, 1985.  ISBN 0-534-03418-7.
+ *
+ *      Storer, James A.
+ *          Data Compression:  Methods and Theory, pp. 49-50.
+ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
+ *
+ *      Sedgewick, R.
+ *          Algorithms, p290.
+ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ *
+ *  INTERFACE
+ *      void ct_init(ush *attr, int *methodp)
+ *          Allocate the match buffer, initialize the various tables and save
+ *          the location of the internal file attribute (ascii/binary) and
+ *          method (DEFLATE/STORE)
+ *
+ *      void ct_tally(int dist, int lc);
+ *          Save the match info and tally the frequency counts.
+ *
+ *      long flush_block (char *buf, ulg stored_len, int eof)
+ *          Determine the best encoding for the current block: dynamic trees,
+ *          static trees or store, and output the encoded block to the zip
+ *          file. Returns the total compressed length for the file so far.
+ */
 
-               memcpy(window, window + WSIZE, WSIZE);
-               match_start -= WSIZE;
-               strstart -= WSIZE;      /* we now have strstart >= MAX_DIST: */
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
 
-               block_start -= WSIZE;
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
 
-               for (n = 0; n < HASH_SIZE; n++) {
-                       m = head[n];
-                       head[n] = (Pos) (m >= WSIZE ? m - WSIZE : 0);
-               }
-               for (n = 0; n < WSIZE; n++) {
-                       m = prev[n];
-                       prev[n] = (Pos) (m >= WSIZE ? m - WSIZE : 0);
-                       /* If n is not on any hash chain, prev[n] is garbage but
-                        * its value will never be used.
-                        */
-               }
-               more += WSIZE;
-       }
-       /* At this point, more >= 2 */
-       if (!eofile) {
-               n = file_read(window + strstart + lookahead, more);
-               if (n == 0 || n == (unsigned) -1) {
-                       eofile = 1;
-               } else {
-                       lookahead += n;
-               }
-       }
-}
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
 
+#define LITERALS  256
+/* number of literal bytes 0..255 */
 
-/* ===========================================================================
- * Same as above, but achieves better compression. We use a lazy
- * evaluation for matches: a match is finally adopted only if there is
- * no better match at the next window position.
- *
- * Processes a new input file and return its compressed length. Sets
- * the compressed length, crc, deflate flags and internal file
- * attributes.
- */
+#define END_BLOCK 256
+/* end of block literal code */
 
-/* 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(eof) \
-       flush_block( \
-               block_start >= 0L \
-                       ? (char*)&window[(unsigned)block_start] \
-                       : (char*)NULL, \
-               (long)strstart - block_start, \
-               (eof) \
-       )
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
 
-/* Insert string s in the dictionary and set match_head to the previous head
- * of the hash chain (the most recent string with same hash key). Return
- * the previous length of the hash chain.
- * IN  assertion: all calls to to INSERT_STRING are made with consecutive
- *    input characters and the first MIN_MATCH bytes of s are valid
- *    (except for the last MIN_MATCH-1 bytes of the input file). */
-#define INSERT_STRING(s, match_head) \
-{ \
-       UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]); \
-       prev[(s) & WMASK] = match_head = head[ins_h]; \
-       head[ins_h] = (s); \
-}
+#define D_CODES   30
+/* number of distance codes */
 
-static ulg deflate(void)
-{
-       IPos hash_head;         /* head of hash chain */
-       IPos prev_match;        /* previous match */
-       int flush;                      /* set if current block must be flushed */
-       int match_available = 0;        /* set if previous match exists */
-       unsigned match_length = MIN_MATCH - 1;  /* length of best match */
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
 
-       /* Process the input block. */
-       while (lookahead != 0) {
-               /* Insert the string window[strstart .. strstart+2] in the
-                * dictionary, and set hash_head to the head of the hash chain:
-                */
-               INSERT_STRING(strstart, hash_head);
+typedef uch extra_bits_t;
 
-               /* Find the longest match, discarding those <= prev_length.
-                */
-               prev_length = match_length, prev_match = match_start;
-               match_length = MIN_MATCH - 1;
+/* extra bits for each length code */
+static const extra_bits_t extra_lbits[LENGTH_CODES]= { 
+       0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
+       4, 4, 5, 5, 5, 5, 0
+};
 
-               if (hash_head != 0 && prev_length < max_lazy_match
-                && strstart - hash_head <= MAX_DIST
-               ) {
-                       /* To simplify the code, we prevent matches with the string
-                        * of window index 0 (in particular we have to avoid a match
-                        * of the string with itself at the start of the input file).
-                        */
-                       match_length = longest_match(hash_head);
-                       /* longest_match() sets match_start */
-                       if (match_length > lookahead)
-                               match_length = lookahead;
-
-                       /* Ignore a length 3 match if it is too distant: */
-                       if (match_length == MIN_MATCH && strstart - match_start > TOO_FAR) {
-                               /* If prev_match is also MIN_MATCH, match_start is garbage
-                                * but we will ignore the current match anyway.
-                                */
-                               match_length--;
-                       }
-               }
-               /* If there was a match at the previous step and the current
-                * match is not better, output the previous match:
-                */
-               if (prev_length >= MIN_MATCH && match_length <= prev_length) {
-                       check_match(strstart - 1, prev_match, prev_length);
-                       flush = ct_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
-
-                       /* Insert in hash table all strings up to the end of the match.
-                        * strstart-1 and strstart are already inserted.
-                        */
-                       lookahead -= prev_length - 1;
-                       prev_length -= 2;
-                       do {
-                               strstart++;
-                               INSERT_STRING(strstart, hash_head);
-                               /* strstart never exceeds WSIZE-MAX_MATCH, so there are
-                                * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
-                                * these bytes are garbage, but it does not matter since the
-                                * next lookahead bytes will always be emitted as literals.
-                                */
-                       } while (--prev_length != 0);
-                       match_available = 0;
-                       match_length = MIN_MATCH - 1;
-                       strstart++;
-                       if (flush) {
-                               FLUSH_BLOCK(0);
-                               block_start = strstart;
-                       }
-               } else if (match_available) {
-                       /* If there was no match at the previous position, output a
-                        * single literal. If there was a match but the current match
-                        * is longer, truncate the previous match to a single literal.
-                        */
-                       Tracevv((stderr, "%c", window[strstart - 1]));
-                       if (ct_tally(0, window[strstart - 1])) {
-                               FLUSH_BLOCK(0);
-                               block_start = strstart;
-                       }
-                       strstart++;
-                       lookahead--;
-               } else {
-                       /* There is no previous match to compare with, wait for
-                        * the next step to decide.
-                        */
-                       match_available = 1;
-                       strstart++;
-                       lookahead--;
-               }
-               Assert(strstart <= isize && lookahead <= isize, "a bit too far");
-
-               /* Make sure that we always have enough lookahead, except
-                * at the end of the input file. We need MAX_MATCH bytes
-                * for the next match, plus MIN_MATCH bytes to insert the
-                * string following the next match.
-                */
-               while (lookahead < MIN_LOOKAHEAD && !eofile)
-                       fill_window();
-       }
-       if (match_available)
-               ct_tally(0, window[strstart - 1]);
-
-       return FLUSH_BLOCK(1);  /* eof */
-}
-/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1992-1993 Jean-loup Gailly
- * This is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License, see the file COPYING.
- */
-
-/*  PURPOSE
- *      Encode various sets of source values using variable-length
- *      binary code trees.
- *
- *  DISCUSSION
- *      The PKZIP "deflation" process uses several Huffman trees. The more
- *      common source values are represented by shorter bit sequences.
- *
- *      Each code tree is stored in the ZIP file in a compressed form
- *      which is itself a Huffman encoding of the lengths of
- *      all the code strings (in ascending order by source values).
- *      The actual code strings are reconstructed from the lengths in
- *      the UNZIP process, as described in the "application note"
- *      (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program.
- *
- *  REFERENCES
- *      Lynch, Thomas J.
- *          Data Compression:  Techniques and Applications, pp. 53-55.
- *          Lifetime Learning Publications, 1985.  ISBN 0-534-03418-7.
- *
- *      Storer, James A.
- *          Data Compression:  Methods and Theory, pp. 49-50.
- *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
- *
- *      Sedgewick, R.
- *          Algorithms, p290.
- *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
- *
- *  INTERFACE
- *      void ct_init(ush *attr, int *methodp)
- *          Allocate the match buffer, initialize the various tables and save
- *          the location of the internal file attribute (ascii/binary) and
- *          method (DEFLATE/STORE)
- *
- *      void ct_tally(int dist, int lc);
- *          Save the match info and tally the frequency counts.
- *
- *      long flush_block (char *buf, ulg stored_len, int eof)
- *          Determine the best encoding for the current block: dynamic trees,
- *          static trees or store, and output the encoded block to the zip
- *          file. Returns the total compressed length for the file so far.
- */
-
-/* ===========================================================================
- * Constants
- */
-
-#define MAX_BITS 15
-/* All codes must not exceed MAX_BITS bits */
-
-#define MAX_BL_BITS 7
-/* Bit length codes must not exceed MAX_BL_BITS bits */
-
-#define LENGTH_CODES 29
-/* number of length codes, not counting the special END_BLOCK code */
-
-#define LITERALS  256
-/* number of literal bytes 0..255 */
-
-#define END_BLOCK 256
-/* end of block literal code */
-
-#define L_CODES (LITERALS+1+LENGTH_CODES)
-/* number of Literal or Length codes, including the END_BLOCK code */
-
-#define D_CODES   30
-/* number of distance codes */
-
-#define BL_CODES  19
-/* number of codes used to transfer the bit lengths */
-
-typedef uch extra_bits_t;
-
-/* extra bits for each length code */
-static const extra_bits_t extra_lbits[LENGTH_CODES]= { 
-       0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
-       4, 4, 5, 5, 5, 5, 0
-};
-
-/* extra bits for each distance code */
-static const extra_bits_t extra_dbits[D_CODES] = { 
-       0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
-       10, 10, 11, 11, 12, 12, 13, 13
-};
+/* extra bits for each distance code */
+static const extra_bits_t extra_dbits[D_CODES] = { 
+       0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
+       10, 10, 11, 11, 12, 12, 13, 13
+};
 
 /* extra bits for each bit length code */
 static const extra_bits_t extra_blbits[BL_CODES] = {
@@ -1087,9 +932,7 @@ static const extra_bits_t extra_blbits[BL_CODES] = {
 /* repeat a zero length 11-138 times  (7 bits of repeat count) */
 
 /* ===========================================================================
- * Local data
- */
-
+*/
 /* Data structure describing a single value and its code string. */
 typedef struct ct_data {
        union {
@@ -1231,8 +1074,6 @@ static int *file_method;  /* pointer to DEFLATE or STORE */
 
 /* ===========================================================================
  */
-static void init_block(void);
-static void gen_bitlen(tree_desc * desc);
 static void gen_codes(ct_data * tree, int max_code);
 static void build_tree(tree_desc * desc);
 static void scan_tree(ct_data * tree, int max_code);
@@ -1240,7 +1081,6 @@ static void send_tree(ct_data * tree, int max_code);
 static int build_bl_tree(void);
 static void send_all_trees(int lcodes, int dcodes, int blcodes);
 static void compress_block(ct_data * ltree, ct_data * dtree);
-static void set_file_type(void);
 
 
 #ifndef DEBUG
@@ -1259,9 +1099,31 @@ static void set_file_type(void);
 /* Mapping from a distance to a distance code. dist is the distance - 1 and
  * must not have side effects. dist_code[256] and dist_code[257] are never
  * used.
+ * The arguments must not have side effects.
+ */
+
+
+/* ===========================================================================
+ * Initialize a new block.
  */
+static void init_block(void)
+{
+       int n; /* iterates over tree elements */
+
+       /* Initialize the trees. */
+       for (n = 0; n < L_CODES; n++)
+               dyn_ltree[n].Freq = 0;
+       for (n = 0; n < D_CODES; n++)
+               dyn_dtree[n].Freq = 0;
+       for (n = 0; n < BL_CODES; n++)
+               bl_tree[n].Freq = 0;
 
-/* the arguments must not have side effects */
+       dyn_ltree[END_BLOCK].Freq = 1;
+       opt_len = static_len = 0L;
+       last_lit = last_dist = last_flags = 0;
+       flags = 0;
+       flag_bit = 1;
+}
 
 
 /* ===========================================================================
@@ -1289,7 +1151,7 @@ static void ct_init(ush * attr, int *methodp)
        for (code = 0; code < LENGTH_CODES - 1; code++) {
                base_length[code] = length;
                for (n = 0; n < (1 << extra_lbits[code]); n++) {
-                       length_code[length++] = (uch) code;
+                       length_code[length++] = code;
                }
        }
        Assert(length == 256, "ct_init: length != 256");
@@ -1297,7 +1159,7 @@ static void ct_init(ush * attr, int *methodp)
         * in two different ways: code 284 + 5 bits or code 285, so we
         * overwrite length_code[255] to use the best encoding:
         */
-       length_code[length - 1] = (uch) code;
+       length_code[length - 1] = code;
 
        /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
        dist = 0;
@@ -1355,29 +1217,6 @@ static void ct_init(ush * attr, int *methodp)
 }
 
 
-/* ===========================================================================
- * Initialize a new block.
- */
-static void init_block(void)
-{
-       int n; /* iterates over tree elements */
-
-       /* Initialize the trees. */
-       for (n = 0; n < L_CODES; n++)
-               dyn_ltree[n].Freq = 0;
-       for (n = 0; n < D_CODES; n++)
-               dyn_dtree[n].Freq = 0;
-       for (n = 0; n < BL_CODES; n++)
-               bl_tree[n].Freq = 0;
-
-       dyn_ltree[END_BLOCK].Freq = 1;
-       opt_len = static_len = 0L;
-       last_lit = last_dist = last_flags = 0;
-       flags = 0;
-       flag_bit = 1;
-}
-
-
 /* ===========================================================================
  * Restore the heap property by moving down the tree starting at node k,
  * exchanging a node with the smallest of its two sons if necessary, stopping
@@ -1470,7 +1309,7 @@ static void gen_bitlen(tree_desc * desc)
                opt_len += (ulg) f *(bits + xbits);
 
                if (stree)
-                       static_len += (ulg) f *(stree[n].Len + xbits);
+                       static_len += (ulg) f * (stree[n].Len + xbits);
        }
        if (overflow == 0)
                return;
@@ -1513,6 +1352,7 @@ static void gen_bitlen(tree_desc * desc)
        }
 }
 
+
 /* ===========================================================================
  * Generate the codes for a given tree and bit counts (which need not be
  * optimal).
@@ -1556,6 +1396,7 @@ static void gen_codes(ct_data * tree, int max_code)
        }
 }
 
+
 /* ===========================================================================
  * Construct one Huffman tree and assigns the code bit strings and lengths.
  * Update the total bit length for the current block.
@@ -1662,6 +1503,7 @@ static void build_tree(tree_desc * desc)
        gen_codes((ct_data *) tree, max_code);
 }
 
+
 /* ===========================================================================
  * Scan a literal or distance tree to determine the frequencies of the codes
  * in the bit length tree. Updates opt_len to take into account the repeat
@@ -1715,6 +1557,7 @@ static void scan_tree(ct_data * tree, int max_code)
        }
 }
 
+
 /* ===========================================================================
  * Send a literal or distance tree in compressed form, using the codes in
  * bl_tree.
@@ -1772,6 +1615,7 @@ static void send_tree(ct_data * tree, int max_code)
        }
 }
 
+
 /* ===========================================================================
  * Construct the Huffman tree for the bit lengths and return the index in
  * bl_order of the last bit length code to send.
@@ -1805,6 +1649,7 @@ static int build_bl_tree(void)
        return max_blindex;
 }
 
+
 /* ===========================================================================
  * Send the header for a block using dynamic Huffman trees: the counts, the
  * lengths of the bit length codes, the literal tree and the distance tree.
@@ -1834,99 +1679,31 @@ static void send_all_trees(int lcodes, int dcodes, int blcodes)
        Tracev((stderr, "\ndist tree: sent %ld", bits_sent));
 }
 
+
 /* ===========================================================================
- * Determine the best encoding for the current block: dynamic trees, static
- * trees or store, and output the encoded block to the zip file. This function
- * returns the total compressed length for the file so far.
+ * Set the file 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).
  */
-static ulg flush_block(char *buf, ulg stored_len, int eof)
+static void set_file_type(void)
 {
-       ulg opt_lenb, static_lenb;      /* opt_len and static_len in bytes */
-       int max_blindex;        /* index of last bit length code of non zero freq */
-
-       flag_buf[last_flags] = flags;   /* Save the flags for the last 8 items */
-
-       /* Check if the file is ascii or binary */
-       if (*file_type == (ush) UNKNOWN)
-               set_file_type();
+       int n = 0;
+       unsigned ascii_freq = 0;
+       unsigned bin_freq = 0;
 
-       /* Construct the literal and distance trees */
-       build_tree((tree_desc *) (&l_desc));
-       Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len));
+       while (n < 7)
+               bin_freq += dyn_ltree[n++].Freq;
+       while (n < 128)
+               ascii_freq += dyn_ltree[n++].Freq;
+       while (n < LITERALS)
+               bin_freq += dyn_ltree[n++].Freq;
+       *file_type = (bin_freq > (ascii_freq >> 2)) ? BINARY : ASCII;
+       if (*file_type == BINARY && translate_eol) {
+               bb_error_msg("-l used on binary file");
+       }
+}
 
-       build_tree((tree_desc *) (&d_desc));
-       Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len));
-       /* At this point, opt_len and static_len are the total bit lengths of
-        * the compressed block data, excluding the tree representations.
-        */
-
-       /* Build the bit length tree for the above two trees, and get the index
-        * in bl_order of the last bit length code to send.
-        */
-       max_blindex = build_bl_tree();
-
-       /* Determine the best encoding. Compute first the block length in bytes */
-       opt_lenb = (opt_len + 3 + 7) >> 3;
-       static_lenb = (static_len + 3 + 7) >> 3;
-
-       Trace((stderr,
-                  "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
-                  opt_lenb, opt_len, static_lenb, static_len, stored_len,
-                  last_lit, last_dist));
-
-       if (static_lenb <= opt_lenb)
-               opt_lenb = static_lenb;
-
-       /* If compression failed and this is the first and last block,
-        * and if the zip file can be seeked (to rewrite the local header),
-        * the whole file is transformed into a stored file:
-        */
-       if (stored_len <= opt_lenb && eof && compressed_len == 0L && seekable()) {
-               /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
-               if (buf == NULL)
-                       bb_error_msg("block vanished");
-
-               copy_block(buf, (unsigned) stored_len, 0);      /* without header */
-               compressed_len = stored_len << 3;
-               *file_method = STORED;
-
-       } else if (stored_len + 4 <= opt_lenb && buf != (char *) 0) {
-               /* 4: two words for the lengths */
-               /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
-                * Otherwise we can't have processed more than WSIZE input bytes since
-                * the last block flush, because compression would have been
-                * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
-                * transform a block into a stored block.
-                */
-               send_bits((STORED_BLOCK << 1) + eof, 3);        /* send block type */
-               compressed_len = (compressed_len + 3 + 7) & ~7L;
-               compressed_len += (stored_len + 4) << 3;
-
-               copy_block(buf, (unsigned) stored_len, 1);      /* with header */
-
-       } else if (static_lenb == opt_lenb) {
-               send_bits((STATIC_TREES << 1) + eof, 3);
-               compress_block((ct_data *) static_ltree, (ct_data *) static_dtree);
-               compressed_len += 3 + static_len;
-       } else {
-               send_bits((DYN_TREES << 1) + eof, 3);
-               send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1,
-                                          max_blindex + 1);
-               compress_block((ct_data *) dyn_ltree, (ct_data *) dyn_dtree);
-               compressed_len += 3 + opt_len;
-       }
-       Assert(compressed_len == bits_sent, "bad compressed size");
-       init_block();
-
-       if (eof) {
-               bi_windup();
-               compressed_len += 7;    /* align on byte boundary */
-       }
-       Tracev((stderr, "\ncomprlen %lu(%lu) ", compressed_len >> 3,
-                       compressed_len - 7 * eof));
-
-       return compressed_len >> 3;
-}
 
 /* ===========================================================================
  * Save the match info and tally the frequency counts. Return true if
@@ -2034,30 +1811,241 @@ static void compress_block(ct_data * ltree, ct_data * dtree)
        SEND_CODE(END_BLOCK, ltree);
 }
 
+
 /* ===========================================================================
- * Set the file 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).
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file. This function
+ * returns the total compressed length for the file so far.
  */
-static void set_file_type(void)
+static ulg flush_block(char *buf, ulg stored_len, int eof)
 {
-       int n = 0;
-       unsigned ascii_freq = 0;
-       unsigned bin_freq = 0;
+       ulg opt_lenb, static_lenb;      /* opt_len and static_len in bytes */
+       int max_blindex;        /* index of last bit length code of non zero freq */
 
-       while (n < 7)
-               bin_freq += dyn_ltree[n++].Freq;
-       while (n < 128)
-               ascii_freq += dyn_ltree[n++].Freq;
-       while (n < LITERALS)
-               bin_freq += dyn_ltree[n++].Freq;
-       *file_type = (bin_freq > (ascii_freq >> 2)) ? BINARY : ASCII;
-       if (*file_type == BINARY && translate_eol) {
-               bb_error_msg("-l used on binary file");
+       flag_buf[last_flags] = flags;   /* Save the flags for the last 8 items */
+
+       /* Check if the file is ascii or binary */
+       if (*file_type == (ush) UNKNOWN)
+               set_file_type();
+
+       /* Construct the literal and distance trees */
+       build_tree((tree_desc *) (&l_desc));
+       Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len));
+
+       build_tree((tree_desc *) (&d_desc));
+       Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len));
+       /* At this point, opt_len and static_len are the total bit lengths of
+        * the compressed block data, excluding the tree representations.
+        */
+
+       /* Build the bit length tree for the above two trees, and get the index
+        * in bl_order of the last bit length code to send.
+        */
+       max_blindex = build_bl_tree();
+
+       /* Determine the best encoding. Compute first the block length in bytes */
+       opt_lenb = (opt_len + 3 + 7) >> 3;
+       static_lenb = (static_len + 3 + 7) >> 3;
+
+       Trace((stderr,
+                  "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
+                  opt_lenb, opt_len, static_lenb, static_len, stored_len,
+                  last_lit, last_dist));
+
+       if (static_lenb <= opt_lenb)
+               opt_lenb = static_lenb;
+
+       /* If compression failed and this is the first and last block,
+        * and if the zip file can be seeked (to rewrite the local header),
+        * the whole file is transformed into a stored file:
+        */
+       if (stored_len <= opt_lenb && eof && compressed_len == 0L && seekable()) {
+               /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
+               if (buf == NULL)
+                       bb_error_msg("block vanished");
+
+               copy_block(buf, (unsigned) stored_len, 0);      /* without header */
+               compressed_len = stored_len << 3;
+               *file_method = STORED;
+
+       } else if (stored_len + 4 <= opt_lenb && buf != (char *) 0) {
+               /* 4: two words for the lengths */
+               /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+                * Otherwise we can't have processed more than WSIZE input bytes since
+                * the last block flush, because compression would have been
+                * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+                * transform a block into a stored block.
+                */
+               send_bits((STORED_BLOCK << 1) + eof, 3);        /* send block type */
+               compressed_len = (compressed_len + 3 + 7) & ~7L;
+               compressed_len += (stored_len + 4) << 3;
+
+               copy_block(buf, (unsigned) stored_len, 1);      /* with header */
+
+       } else if (static_lenb == opt_lenb) {
+               send_bits((STATIC_TREES << 1) + eof, 3);
+               compress_block((ct_data *) static_ltree, (ct_data *) static_dtree);
+               compressed_len += 3 + static_len;
+       } else {
+               send_bits((DYN_TREES << 1) + eof, 3);
+               send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1,
+                                          max_blindex + 1);
+               compress_block((ct_data *) dyn_ltree, (ct_data *) dyn_dtree);
+               compressed_len += 3 + opt_len;
+       }
+       Assert(compressed_len == bits_sent, "bad compressed size");
+       init_block();
+
+       if (eof) {
+               bi_windup();
+               compressed_len += 7;    /* align on byte boundary */
+       }
+       Tracev((stderr, "\ncomprlen %lu(%lu) ", compressed_len >> 3,
+                       compressed_len - 7 * eof));
+
+       return compressed_len >> 3;
+}
+
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ *
+ * Processes a new input file and return its compressed length. Sets
+ * the compressed length, crc, deflate flags and internal file
+ * attributes.
+ */
+
+/* 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(eof) \
+       flush_block( \
+               block_start >= 0L \
+                       ? (char*)&window[(unsigned)block_start] \
+                       : (char*)NULL, \
+               (long)strstart - block_start, \
+               (eof) \
+       )
+
+/* Insert string s in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
+ *    input characters and the first MIN_MATCH bytes of s are valid
+ *    (except for the last MIN_MATCH-1 bytes of the input file). */
+#define INSERT_STRING(s, match_head) \
+{ \
+       UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]); \
+       prev[(s) & WMASK] = match_head = head[ins_h]; \
+       head[ins_h] = (s); \
+}
+
+static ulg deflate(void)
+{
+       IPos hash_head;         /* head of hash chain */
+       IPos prev_match;        /* previous match */
+       int flush;                      /* set if current block must be flushed */
+       int match_available = 0;        /* set if previous match exists */
+       unsigned match_length = MIN_MATCH - 1;  /* length of best match */
+
+       /* Process the input block. */
+       while (lookahead != 0) {
+               /* Insert the string window[strstart .. strstart+2] in the
+                * dictionary, and set hash_head to the head of the hash chain:
+                */
+               INSERT_STRING(strstart, hash_head);
+
+               /* Find the longest match, discarding those <= prev_length.
+                */
+               prev_length = match_length, prev_match = match_start;
+               match_length = MIN_MATCH - 1;
+
+               if (hash_head != 0 && prev_length < max_lazy_match
+                && strstart - hash_head <= MAX_DIST
+               ) {
+                       /* To simplify the code, we prevent matches with the string
+                        * of window index 0 (in particular we have to avoid a match
+                        * of the string with itself at the start of the input file).
+                        */
+                       match_length = longest_match(hash_head);
+                       /* longest_match() sets match_start */
+                       if (match_length > lookahead)
+                               match_length = lookahead;
+
+                       /* Ignore a length 3 match if it is too distant: */
+                       if (match_length == MIN_MATCH && strstart - match_start > TOO_FAR) {
+                               /* If prev_match is also MIN_MATCH, match_start is garbage
+                                * but we will ignore the current match anyway.
+                                */
+                               match_length--;
+                       }
+               }
+               /* If there was a match at the previous step and the current
+                * match is not better, output the previous match:
+                */
+               if (prev_length >= MIN_MATCH && match_length <= prev_length) {
+                       check_match(strstart - 1, prev_match, prev_length);
+                       flush = ct_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
+
+                       /* Insert in hash table all strings up to the end of the match.
+                        * strstart-1 and strstart are already inserted.
+                        */
+                       lookahead -= prev_length - 1;
+                       prev_length -= 2;
+                       do {
+                               strstart++;
+                               INSERT_STRING(strstart, hash_head);
+                               /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                                * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
+                                * these bytes are garbage, but it does not matter since the
+                                * next lookahead bytes will always be emitted as literals.
+                                */
+                       } while (--prev_length != 0);
+                       match_available = 0;
+                       match_length = MIN_MATCH - 1;
+                       strstart++;
+                       if (flush) {
+                               FLUSH_BLOCK(0);
+                               block_start = strstart;
+                       }
+               } else if (match_available) {
+                       /* If there was no match at the previous position, output a
+                        * single literal. If there was a match but the current match
+                        * is longer, truncate the previous match to a single literal.
+                        */
+                       Tracevv((stderr, "%c", window[strstart - 1]));
+                       if (ct_tally(0, window[strstart - 1])) {
+                               FLUSH_BLOCK(0);
+                               block_start = strstart;
+                       }
+                       strstart++;
+                       lookahead--;
+               } else {
+                       /* There is no previous match to compare with, wait for
+                        * the next step to decide.
+                        */
+                       match_available = 1;
+                       strstart++;
+                       lookahead--;
+               }
+               Assert(strstart <= isize && lookahead <= isize, "a bit too far");
+
+               /* Make sure that we always have enough lookahead, except
+                * at the end of the input file. We need MAX_MATCH bytes
+                * for the next match, plus MIN_MATCH bytes to insert the
+                * string following the next match.
+                */
+               while (lookahead < MIN_LOOKAHEAD && !eofile)
+                       fill_window();
        }
+       if (match_available)
+               ct_tally(0, window[strstart - 1]);
+
+       return FLUSH_BLOCK(1);  /* eof */
 }
 
+
 /* ===========================================================================
  * Deflate in to out.
  * IN assertions: the input and output buffers are cleared.