[BusyBox] PATCH: busybox-0.60.0/gzip.c codespace reduction

rbrown64 at csc.com.au rbrown64 at csc.com.au
Sun Aug 19 02:51:49 UTC 2001


This 3rd version saves ~1.5kb of codespace savings on i586-pc-gnu-linu
against busybox-0.60.0 source.

Since gzip won't be changing it's CRC polynomial, initialize `e' to the
appropriate constant in updcrc rather than calculating it.
The value 0xedb88320L is mentioned in the comment and is the value
of crc_32_tab[128] in the master gzip source.
/* (MSB) Most Sig. Bit
 * 3322222222221111111111          |
 * 10987654321098765432109876543210|
 *                              LSB|
 *           1111111111222222222233|
 * 01234567890123456789012345678901|
 * 111 11 11 111   1     11  1     |
 *     +   +   +   +   +   +   +   |
 *    E   D   B   8   8   3   2   0|
 */

The main savings are from avoiding code for calls to  flush_outbuf
2 for each put_short call expansion, 4 for each put_long expansion.
put_short_when_full handles the uncommon case for put_short.
Since put_long is used only in the zip routine for one file,
packaging it as a function doesn't measurably slow things down.
put_short_function is to keep the put_long function small.
put_header_byte is to remove code for calls to flush_outbuf for
the first four bytes which will always fit within OUTBUFSIZE.

bash-2.03$ size gzip.o*
   text data   bss  dec  hex filename
   8903 100    12236     21239     52f7 gzip.o          # This is for a
prior version
  10007 100    12236     22343     5747 gzip.o.bu
bash-2.03$ size-busybox{,.bu}
   text data   bss  dec  hex filename
 148572 3800   33888     186260    2d794 busybox
 149804 3800   33888     187492    2dc64 busybox.bu
bash-2.03$ uname -a
Linux urtur 2.2.18 #4 Wed Dec 27 22:36:31 EST 2000 i586 unknown

Some testing of decompression and compression has been done - no problems
seen.

2001-08-15  Rodney Brown  <RDBrown at mira.net>
     * gzip.c(updcrc): Initialize `e' to the polynomial exclusive-or value.
       (put_long): Convert to function.
       (put_short_when_full, put_short_function, put_header_byte):
          Introduce to reduce codesize.
       Use xcalloc rather than the inline test.
       Declare the extra_bits constant arrays as uch rather than int.

--- gzip.c.orig     Mon Jul 30 14:48:50 2001
+++ gzip.c     Sun Aug 19 12:22:55 2001
@@ -108,12 +108,11 @@ static int method;                     /* compression met
 #endif

 #ifdef DYN_ALLOC
 #  define DECLARE(type, array, size)  static type * array
 #  define ALLOC(type, array, size) { \
-      array = (type*)calloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \
-      if (array == NULL) error_msg(memory_exhausted); \
+      array = (type*)xcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \
    }
 #  define FREE(array) {if (array != NULL) free(array), array=NULL;}
 #else
 #  define DECLARE(type, array, size)  static type array[size]
 #  define ALLOC(type, array, size)
@@ -179,20 +178,21 @@ typedef int file_t;                    /* Do not use std
 #define put_short(w) \
 { if (outcnt < OUTBUFSIZ-2) { \
     outbuf[outcnt++] = (uch) ((w) & 0xff); \
     outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \
   } else { \
-    put_byte((uch)((w) & 0xff)); \
-    put_byte((uch)((ush)(w) >> 8)); \
+    put_short_when_full(w); \
   } \
 }

 /* Output a 32 bit value to the bit stream, lsb first */
+#if 0
 #define put_long(n) { \
     put_short((n) & 0xffff); \
     put_short(((ulg)(n)) >> 16); \
 }
+#endif

 #define seekable()    0           /* force sequential output */
 #define translate_eol 0           /* no option -a yet */

 /* Diagnostic functions */
@@ -219,10 +219,12 @@ typedef int file_t;                    /* Do not use std
 #  define MAX_PATH_LEN   1024     /* max pathname length */
 #endif



+static void put_short_when_full (ush);
+
     /* from zip.c: */
 static int zip (int in, int out);
 static int file_read (char *buf, unsigned size);

     /* from gzip.c */
@@ -386,22 +388,16 @@ static ulg updcrc(uch *s, unsigned n)
     static ulg crc = (ulg) 0xffffffffL;      /* shift register contents */
     register ulg c;                     /* temporary variable */
     static unsigned long crc_32_tab[256];
     if (crc_table_empty) {
          unsigned long csr;      /* crc shift register */
-         unsigned long e=0;      /* polynomial exclusive-or pattern */
+         const unsigned long e = 0xedb88320L;
+                         /* polynomial exclusive-or pattern */
          int i;                /* counter for all possible eight bit values */
          int k;                /* byte being shifted into crc apparatus */

-         /* terms of polynomial defining this crc (except x^32): */
-         static const int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
-
-         /* Make exclusive-or pattern from polynomial (0xedb88320) */
-         for (i = 0; i < sizeof(p)/sizeof(int); i++)
-              e |= 1L << (31 - p[i]);
-
-         /* Compute and print table of CRC's, five per line */
+         /* Compute table of CRC's. */
          crc_32_tab[0] = 0x00000000L;
          for (i = 1; i < 256; i++) {
               csr = i;
             /* The idea to initialize the register with the byte instead of
               * zero was stolen from Haruhiko Okumura's ar002
@@ -1204,11 +1200,10 @@ static ulg deflate()

 typedef struct dirent dir_type;

 typedef RETSIGTYPE(*sig_type) (int);

-
 /* ======================================================================== */
 // int main (argc, argv)
 //    int argc;
 //    char **argv;
 int gzip_main(int argc, char **argv)
@@ -1289,15 +1284,14 @@ int gzip_main(int argc, char **argv)
          /* Open up the input file */
          strncpy(ifname, argv[optind], MAX_PATH_LEN);

          /* Open input file */
          inFileNum = open(ifname, O_RDONLY);
-         if (inFileNum < 0)
+         if (inFileNum < 0
+         || stat(ifname, &statBuf) < 0)
               perror_msg_and_die("%s", ifname);
          /* Get the time stamp on the input file. */
-         if (stat(ifname, &statBuf) < 0)
-              perror_msg_and_die("%s", ifname);
          time_stamp = statBuf.st_ctime;
          ifile_size = statBuf.st_size;
     }


@@ -1431,20 +1425,21 @@ int gzip_main(int argc, char **argv)
 /* number of distance codes */

 #define BL_CODES  19
 /* number of codes used to transfer the bit lengths */

+typedef uch extra_bits_t;

-static const int extra_lbits[LENGTH_CODES]   /* extra bits for each length code */
+static const extra_bits_t extra_lbits[LENGTH_CODES]    /* extra bits for each length code */
     = { 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 };

-static const int extra_dbits[D_CODES]   /* extra bits for each distance code */
+static const extra_bits_t extra_dbits[D_CODES]    /* extra bits for each distance code */
     = { 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 };

-static const int extra_blbits[BL_CODES]      /* extra bits for each bit length code */
+static const extra_bits_t extra_blbits[BL_CODES]  /* extra bits for each bit length code */
 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };

 #define STORED_BLOCK 0
 #define STATIC_TREES 1
 #define DYN_TREES    2
@@ -1535,11 +1530,11 @@ static ct_data bl_tree[2 * BL_CODES + 1]
 /* Huffman tree for the bit lengths */

 typedef struct tree_desc {
     ct_data *dyn_tree;       /* the dynamic tree */
     ct_data *static_tree;    /* corresponding static tree or NULL */
-    const int *extra_bits;        /* extra bits for each code or NULL */
+    const extra_bits_t *extra_bits;          /* extra bits for each code or NULL */
     int extra_base;                     /* base index for extra_bits */
     int elems;                          /* max number of elements in the tree */
     int max_length;                     /* max bit length for the codes */
     int max_code;                 /* largest code with non zero frequency */
 } tree_desc;
@@ -1832,11 +1827,11 @@ static void pqdownheap(ct_data *tree, in
  *     not null.
  */
 static void gen_bitlen(tree_desc *desc)
 {
     ct_data *tree = desc->dyn_tree;
-    const int *extra = desc->extra_bits;
+    const extra_bits_t *extra = desc->extra_bits;
     int base = desc->extra_base;
     int max_code = desc->max_code;
     int max_length = desc->max_length;
     ct_data *stree = desc->static_tree;
     int h;                              /* heap index */
@@ -2464,10 +2459,32 @@ static void set_file_type()


 static ulg crc;                         /* crc on uncompressed file data */
 static long header_bytes;                    /* number of bytes in gzip header */

+static void put_short_when_full(ush w)
+{
+    put_byte((uch)((w) & 0xff));
+    put_byte((uch)((ush)(w) >> 8));
+}
+
+static void put_short_function(ush n)
+{
+    put_short(n);
+}
+
+static void put_long(ulg n)
+{
+    put_short_function((n) & 0xffff);
+    put_short_function(((ulg)(n)) >> 16);
+}
+
+/* put_header_byte is used for the compressed output
+ * - for the initial 4 bytes that can't overflow the buffer.
+ */
+#define put_header_byte(c) {outbuf[outcnt++]=(uch)(c);}
+
 /* ===========================================================================
  * Deflate in to out.
  * IN assertions: the input and output buffers are cleared.
  *   The variables time_stamp and save_orig_name are initialized.
  */
@@ -2483,15 +2500,15 @@ static int zip(int in, int out)

     /* Write the header to the gzip file. See algorithm.doc for the format */


     method = DEFLATED;
-    put_byte(GZIP_MAGIC[0]); /* magic header */
-    put_byte(GZIP_MAGIC[1]);
-    put_byte(DEFLATED);           /* compression method */
+    put_header_byte(GZIP_MAGIC[0]);     /* magic header */
+    put_header_byte(GZIP_MAGIC[1]);
+    put_header_byte(DEFLATED);    /* compression method */

-    put_byte(my_flags);           /* general flags */
+    put_header_byte(my_flags);    /* general flags */
     put_long(time_stamp);

     /* Write deflated file to zip file */
     crc = updcrc(0, 0);







More information about the busybox mailing list