[BACK]Return to zopen.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / compress

Diff for /src/usr.bin/compress/zopen.c between version 1.4 and 1.5

version 1.4, 1997/01/19 17:25:14 version 1.5, 1997/07/06 20:23:00
Line 78 
Line 78 
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <unistd.h>  #include <unistd.h>
   #include <fcntl.h>
   #include "compress.h"
   
 #define BITS            16              /* Default bits. */  #define BITS            16              /* Default bits. */
 #define HSIZE           69001           /* 95% occupancy */  #define HSIZE           69001           /* 95% occupancy */
Line 86 
Line 88 
 typedef long code_int;  typedef long code_int;
 typedef long count_int;  typedef long count_int;
   
 typedef u_char char_type;  static u_char z_magic[] =
 static char_type magic_header[] =  
         {'\037', '\235'};               /* 1F 9D */          {'\037', '\235'};               /* 1F 9D */
   
 #define BIT_MASK        0x1f            /* Defines for third byte of header. */  #define BIT_MASK        0x1f            /* Defines for third byte of header. */
Line 102 
Line 103 
 #define MAXCODE(n_bits) ((1 << (n_bits)) - 1)  #define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
   
 struct s_zstate {  struct s_zstate {
         FILE *zs_fp;                    /* File stream for I/O */          int zs_fd;                      /* File stream for I/O */
         char zs_mode;                   /* r or w */          char zs_mode;                   /* r or w */
         enum {          enum {
                 S_START, S_MIDDLE, S_EOF                  S_START, S_MIDDLE, S_EOF
Line 126 
Line 127 
         int zs_offset;          int zs_offset;
         long zs_in_count;               /* Length of input. */          long zs_in_count;               /* Length of input. */
         long zs_bytes_out;              /* Length of compressed output. */          long zs_bytes_out;              /* Length of compressed output. */
         long zs_out_count;              /* # of codes output (for debugging). */          long zs_out_count;              /* # of codes output (for debugging).*/
         char_type zs_buf[BITS];          u_char zs_buf[BITS];
         union {          union {
                 struct {                  struct {
                         long zs_fcode;                          long zs_fcode;
Line 136 
Line 137 
                         int zs_hshift;                          int zs_hshift;
                 } w;                    /* Write paramenters */                  } w;                    /* Write paramenters */
                 struct {                  struct {
                         char_type *zs_stackp;                          u_char *zs_stackp;
                         int zs_finchar;                          int zs_finchar;
                         code_int zs_code, zs_oldcode, zs_incode;                          code_int zs_code, zs_oldcode, zs_incode;
                         int zs_roffset, zs_size;                          int zs_roffset, zs_size;
                         char_type zs_gbuf[BITS];  
                 } r;                    /* Read parameters */                  } r;                    /* Read parameters */
         } u;          } u;
 };  };
   
 /* Definitions to retain old variable names */  /* Definitions to retain old variable names */
 #define fp              zs->zs_fp  #define zs_fcode        u.w.zs_fcode
 #define zmode           zs->zs_mode  #define zs_ent          u.w.zs_ent
 #define state           zs->zs_state  #define zs_hsize_reg    u.w.zs_hsize_reg
 #define n_bits          zs->zs_n_bits  #define zs_hshift       u.w.zs_hshift
 #define maxbits         zs->zs_maxbits  #define zs_stackp       u.r.zs_stackp
 #define maxcode         zs->zs_maxcode  #define zs_finchar      u.r.zs_finchar
 #define maxmaxcode      zs->zs_maxmaxcode  #define zs_code         u.r.zs_code
 #define htab            zs->zs_htab  #define zs_oldcode      u.r.zs_oldcode
 #define codetab         zs->zs_codetab  #define zs_incode       u.r.zs_incode
 #define hsize           zs->zs_hsize  #define zs_roffset      u.r.zs_roffset
 #define free_ent        zs->zs_free_ent  #define zs_size         u.r.zs_size
 #define block_compress  zs->zs_block_compress  
 #define clear_flg       zs->zs_clear_flg  
 #define ratio           zs->zs_ratio  
 #define checkpoint      zs->zs_checkpoint  
 #define offset          zs->zs_offset  
 #define in_count        zs->zs_in_count  
 #define bytes_out       zs->zs_bytes_out  
 #define out_count       zs->zs_out_count  
 #define buf             zs->zs_buf  
 #define fcode           zs->u.w.zs_fcode  
 #define hsize_reg       zs->u.w.zs_hsize_reg  
 #define ent             zs->u.w.zs_ent  
 #define hshift          zs->u.w.zs_hshift  
 #define stackp          zs->u.r.zs_stackp  
 #define finchar         zs->u.r.zs_finchar  
 #define code            zs->u.r.zs_code  
 #define oldcode         zs->u.r.zs_oldcode  
 #define incode          zs->u.r.zs_incode  
 #define roffset         zs->u.r.zs_roffset  
 #define size            zs->u.r.zs_size  
 #define gbuf            zs->u.r.zs_gbuf  
   
 /*  /*
  * To save much memory, we overlay the table used by compress() with those   * To save much memory, we overlay the table used by compress() with those
Line 188 
Line 167 
  * (stack used to be 8000 characters).   * (stack used to be 8000 characters).
  */   */
   
 #define htabof(i)       htab[i]  #define htabof(i)       zs->zs_htab[i]
 #define codetabof(i)    codetab[i]  #define codetabof(i)    zs->zs_codetab[i]
   
 #define tab_prefixof(i) codetabof(i)  #define tab_prefixof(i) codetabof(i)
 #define tab_suffixof(i) ((char_type *)(htab))[i]  #define tab_suffixof(i) ((u_char *)(zs->zs_htab))[i]
 #define de_stack        ((char_type *)&tab_suffixof(1 << BITS))  #define de_stack        ((u_char *)&tab_suffixof(1 << BITS))
   
 #define CHECK_GAP 10000         /* Ratio check interval. */  #define CHECK_GAP 10000         /* Ratio check interval. */
   
Line 204 
Line 183 
 #define FIRST   257             /* First free entry. */  #define FIRST   257             /* First free entry. */
 #define CLEAR   256             /* Table clear output code. */  #define CLEAR   256             /* Table clear output code. */
   
 static int      cl_block __P((struct s_zstate *));  static int      cl_block __P((register struct s_zstate *));
 static void     cl_hash __P((struct s_zstate *, count_int));  static void     cl_hash __P((register struct s_zstate *, register count_int));
 static code_int getcode __P((struct s_zstate *));  static code_int getcode __P((register struct s_zstate *));
 static int      output __P((struct s_zstate *, code_int));  static int      output __P((register struct s_zstate *, code_int));
 static int      zclose __P((void *));  
 static int      zread __P((void *, char *, int));  
 static int      zwrite __P((void *, const char *, int));  
   
 /*-  /*-
  * Algorithm from "A Technique for High Performance Data Compression",   * Algorithm from "A Technique for High Performance Data Compression",
Line 238 
Line 214 
  * file size for noticeable speed improvement on small files.  Please direct   * file size for noticeable speed improvement on small files.  Please direct
  * questions about this implementation to ames!jaw.   * questions about this implementation to ames!jaw.
  */   */
 static int  int
 zwrite(cookie, wbp, num)  zwrite(cookie, wbp, num)
         void *cookie;          void *cookie;
         const char *wbp;          const char *wbp;
Line 257 
Line 233 
         zs = cookie;          zs = cookie;
         count = num;          count = num;
         bp = (u_char *)wbp;          bp = (u_char *)wbp;
         if (state == S_MIDDLE)          if (zs->zs_state == S_MIDDLE)
                 goto middle;                  goto middle;
         state = S_MIDDLE;          zs->zs_state = S_MIDDLE;
   
         maxmaxcode = 1L << maxbits;          zs->zs_maxmaxcode = 1L << zs->zs_maxbits;
         if (fwrite(magic_header,          if (write(zs->zs_fd, z_magic, sizeof(z_magic)) != sizeof(z_magic))
             sizeof(char), sizeof(magic_header), fp) != sizeof(magic_header))  
                 return (-1);                  return (-1);
         tmp = (u_char)(maxbits | block_compress);          tmp = (u_char)(zs->zs_maxbits | zs->zs_block_compress);
         if (fwrite(&tmp, sizeof(char), sizeof(tmp), fp) != sizeof(tmp))          if (write(zs->zs_fd, &tmp, sizeof(tmp)) != sizeof(tmp))
                 return (-1);                  return (-1);
   
         offset = 0;          zs->zs_offset = 0;
         bytes_out = 3;          /* Includes 3-byte header mojo. */          zs->zs_bytes_out = 3;           /* Includes 3-byte header mojo. */
         out_count = 0;          zs->zs_out_count = 0;
         clear_flg = 0;          zs->zs_clear_flg = 0;
         ratio = 0;          zs->zs_ratio = 0;
         in_count = 1;          zs->zs_in_count = 1;
         checkpoint = CHECK_GAP;          zs->zs_checkpoint = CHECK_GAP;
         maxcode = MAXCODE(n_bits = INIT_BITS);          zs->zs_maxcode = MAXCODE(zs->zs_n_bits = INIT_BITS);
         free_ent = ((block_compress) ? FIRST : 256);          zs->zs_free_ent = ((zs->zs_block_compress) ? FIRST : 256);
   
         ent = *bp++;          zs->zs_ent = *bp++;
         --count;          --count;
   
         hshift = 0;          zs->zs_hshift = 0;
         for (fcode = (long)hsize; fcode < 65536L; fcode *= 2L)          for (zs->zs_fcode = (long)zs->zs_hsize; zs->zs_fcode < 65536L;
                 hshift++;               zs->zs_fcode *= 2L)
         hshift = 8 - hshift;    /* Set hash code range bound. */                  zs->zs_hshift++;
           zs->zs_hshift = 8 - zs->zs_hshift; /* Set hash code range bound. */
   
         hsize_reg = hsize;          zs->zs_hsize_reg = zs->zs_hsize;
         cl_hash(zs, (count_int)hsize_reg);      /* Clear hash table. */          cl_hash(zs, (count_int)zs->zs_hsize_reg);       /* Clear hash table. */
   
 middle: for (i = 0; count--;) {  middle: for (i = 0; count--;) {
                 c = *bp++;                  c = *bp++;
                 in_count++;                  zs->zs_in_count++;
                 fcode = (long)(((long)c << maxbits) + ent);                  zs->zs_fcode = (long)(((long)c << zs->zs_maxbits) +
                 i = ((c << hshift) ^ ent);      /* Xor hashing. */                                        zs->zs_ent);
                   i = ((c << zs->zs_hshift) ^ zs->zs_ent); /* Xor hashing. */
   
                 if (htabof(i) == fcode) {                  if (htabof(i) == zs->zs_fcode) {
                         ent = codetabof(i);                          zs->zs_ent = codetabof(i);
                         continue;                          continue;
                 } else if ((long)htabof(i) < 0) /* Empty slot. */                  } else if ((long)htabof(i) < 0) /* Empty slot. */
                         goto nomatch;                          goto nomatch;
                 disp = hsize_reg - i;   /* Secondary hash (after G. Knott). */                  /* Secondary hash (after G. Knott). */
                   disp = zs->zs_hsize_reg - i;
                 if (i == 0)                  if (i == 0)
                         disp = 1;                          disp = 1;
 probe:          if ((i -= disp) < 0)  probe:          if ((i -= disp) < 0)
                         i += hsize_reg;                          i += zs->zs_hsize_reg;
   
                 if (htabof(i) == fcode) {                  if (htabof(i) == zs->zs_fcode) {
                         ent = codetabof(i);                          zs->zs_ent = codetabof(i);
                         continue;                          continue;
                 }                  }
                 if ((long)htabof(i) >= 0)                  if ((long)htabof(i) >= 0)
                         goto probe;                          goto probe;
 nomatch:        if (output(zs, (code_int) ent) == -1)  nomatch:        if (output(zs, (code_int) zs->zs_ent) == -1)
                         return (-1);                          return (-1);
                 out_count++;                  zs->zs_out_count++;
                 ent = c;                  zs->zs_ent = c;
                 if (free_ent < maxmaxcode) {                  if (zs->zs_free_ent < zs->zs_maxmaxcode) {
                         codetabof(i) = free_ent++;      /* code -> hashtable */                          /* code -> hashtable */
                         htabof(i) = fcode;                          codetabof(i) = zs->zs_free_ent++;
                 } else if ((count_int)in_count >=                          htabof(i) = zs->zs_fcode;
                     checkpoint && block_compress) {                  } else if ((count_int)zs->zs_in_count >=
                       zs->zs_checkpoint && zs->zs_block_compress) {
                         if (cl_block(zs) == -1)                          if (cl_block(zs) == -1)
                                 return (-1);                                  return (-1);
                 }                  }
Line 329 
Line 308 
         return (num);          return (num);
 }  }
   
 static int  int
 zclose(cookie)  zclose(cookie)
         void *cookie;          void *cookie;
 {  {
Line 337 
Line 316 
         int rval;          int rval;
   
         zs = cookie;          zs = cookie;
         if (zmode == 'w') {             /* Put out the final code. */          if (zs->zs_mode == 'w') {               /* Put out the final code. */
                 if (output(zs, (code_int) ent) == -1) {                  if (output(zs, (code_int) zs->zs_ent) == -1) {
                         (void)fclose(fp);                          (void)close(zs->zs_fd);
                         free(zs);                          free(zs);
                         return (-1);                          return (-1);
                 }                  }
                 out_count++;                  zs->zs_out_count++;
                 if (output(zs, (code_int) - 1) == -1) {                  if (output(zs, (code_int) - 1) == -1) {
                         (void)fclose(fp);                          (void)close(zs->zs_fd);
                         free(zs);                          free(zs);
                         return (-1);                          return (-1);
                 }                  }
         }          }
         rval = fclose(fp) == EOF ? -1 : 0;          rval = close(zs->zs_fd);
         free(zs);          free(zs);
         return (rval);          return (rval);
 }  }
Line 370 
Line 349 
  * code in turn.  When the buffer fills up empty it and start over.   * code in turn.  When the buffer fills up empty it and start over.
  */   */
   
 static char_type lmask[9] =  static u_char lmask[9] =
         {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};          {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
 static char_type rmask[9] =  static u_char rmask[9] =
         {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};          {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
   
 static int  static int
 output(zs, ocode)  output(zs, ocode)
         struct s_zstate *zs;          register struct s_zstate *zs;
         code_int ocode;          code_int ocode;
 {  {
         register int bits, r_off;          register int bits, r_off;
         register char_type *bp;          register u_char *bp;
   
         r_off = offset;          r_off = zs->zs_offset;
         bits = n_bits;          bits = zs->zs_n_bits;
         bp = buf;          bp = zs->zs_buf;
         if (ocode >= 0) {          if (ocode >= 0) {
                 /* Get to the first byte. */                  /* Get to the first byte. */
                 bp += (r_off >> 3);                  bp += (r_off >> 3);
Line 398 
Line 377 
                 bp++;                  bp++;
                 bits -= (8 - r_off);                  bits -= (8 - r_off);
                 ocode >>= 8 - r_off;                  ocode >>= 8 - r_off;
                 /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */                  /* Get any 8 bit parts in the middle (<=1 for up to 16 bits) */
                 if (bits >= 8) {                  if (bits >= 8) {
                         *bp++ = ocode;                          *bp++ = ocode;
                         ocode >>= 8;                          ocode >>= 8;
Line 407 
Line 386 
                 /* Last bits. */                  /* Last bits. */
                 if (bits)                  if (bits)
                         *bp = ocode;                          *bp = ocode;
                 offset += n_bits;                  zs->zs_offset += zs->zs_n_bits;
                 if (offset == (n_bits << 3)) {                  if (zs->zs_offset == (zs->zs_n_bits << 3)) {
                         bp = buf;                          bp = zs->zs_buf;
                         bits = n_bits;                          bits = zs->zs_n_bits;
                         bytes_out += bits;                          zs->zs_bytes_out += bits;
                         if (fwrite(bp, sizeof(char), bits, fp) != bits)                          if (write(zs->zs_fd, bp, bits) != bits)
                                 return (-1);                                  return (-1);
                         bp += bits;                          bp += bits;
                         bits = 0;                          bits = 0;
                         offset = 0;                          zs->zs_offset = 0;
                 }                  }
                 /*                  /*
                  * If the next entry is going to be too big for the ocode size,                   * If the next entry is going to be too big for the ocode size,
                  * then increase it, if possible.                   * then increase it, if possible.
                  */                   */
                 if (free_ent > maxcode || (clear_flg > 0)) {                  if (zs->zs_free_ent > zs->zs_maxcode ||
                       (zs->zs_clear_flg > 0)) {
                        /*                         /*
                         * Write the whole buffer, because the input side won't                          * Write the whole buffer, because the input side won't
                         * discover the size increase until after it has read it.                          * discover the size increase until after it has read it
                         */                          */
                         if (offset > 0) {                          if (zs->zs_offset > 0) {
                                 if (fwrite(buf, 1, n_bits, fp) != n_bits)                                  if (write(zs->zs_fd, zs->zs_buf, zs->zs_n_bits)
                                       != zs->zs_n_bits)
                                         return (-1);                                          return (-1);
                                 bytes_out += n_bits;                                  zs->zs_bytes_out += zs->zs_n_bits;
                         }                          }
                         offset = 0;                          zs->zs_offset = 0;
   
                         if (clear_flg) {                          if (zs->zs_clear_flg) {
                                 maxcode = MAXCODE(n_bits = INIT_BITS);                                  zs->zs_maxcode =
                                 clear_flg = 0;                                          MAXCODE(zs->zs_n_bits = INIT_BITS);
                                   zs->zs_clear_flg = 0;
                         } else {                          } else {
                                 n_bits++;                                  zs->zs_n_bits++;
                                 if (n_bits == maxbits)                                  if (zs->zs_n_bits == zs->zs_maxbits)
                                         maxcode = maxmaxcode;                                          zs->zs_maxcode = zs->zs_maxmaxcode;
                                 else                                  else
                                         maxcode = MAXCODE(n_bits);                                          zs->zs_maxcode =
                                                   MAXCODE(zs->zs_n_bits);
                         }                          }
                 }                  }
         } else {          } else {
                 /* At EOF, write the rest of the buffer. */                  /* At EOF, write the rest of the buffer. */
                 if (offset > 0) {                  if (zs->zs_offset > 0) {
                         offset = (offset + 7) / 8;                          zs->zs_offset = (zs->zs_offset + 7) / 8;
                         if (fwrite(buf, 1, offset, fp) != offset)                          if (write(zs->zs_fd, zs->zs_buf, zs->zs_offset)
                               != zs->zs_offset)
                                 return (-1);                                  return (-1);
                         bytes_out += offset;                          zs->zs_bytes_out += zs->zs_offset;
                 }                  }
                 offset = 0;                  zs->zs_offset = 0;
         }          }
         return (0);          return (0);
 }  }
Line 464 
Line 448 
  * compressed file.  The tables used herein are shared with those of the   * compressed file.  The tables used herein are shared with those of the
  * compress() routine.  See the definitions above.   * compress() routine.  See the definitions above.
  */   */
 static int  int
 zread(cookie, rbp, num)  zread(cookie, rbp, num)
         void *cookie;          void *cookie;
         char *rbp;          char *rbp;
Line 480 
Line 464 
         zs = cookie;          zs = cookie;
         count = num;          count = num;
         bp = (u_char *)rbp;          bp = (u_char *)rbp;
         switch (state) {          switch (zs->zs_state) {
         case S_START:          case S_START:
                 state = S_MIDDLE;                  zs->zs_state = S_MIDDLE;
                 break;                  break;
         case S_MIDDLE:          case S_MIDDLE:
                 goto middle;                  goto middle;
Line 491 
Line 475 
         }          }
   
         /* Check the magic number */          /* Check the magic number */
         if (fread(header,          if (read(zs->zs_fd, header, sizeof(header)) != sizeof(header) ||
             sizeof(char), sizeof(header), fp) != sizeof(header) ||              memcmp(header, z_magic, sizeof(z_magic)) != 0) {
             memcmp(header, magic_header, sizeof(magic_header)) != 0) {  
                 errno = EFTYPE;                  errno = EFTYPE;
                 return (-1);                  return (-1);
         }          }
         maxbits = header[2];    /* Set -b from file. */          zs->zs_maxbits = header[2];     /* Set -b from file. */
         block_compress = maxbits & BLOCK_MASK;          zs->zs_block_compress = zs->zs_maxbits & BLOCK_MASK;
         maxbits &= BIT_MASK;          zs->zs_maxbits &= BIT_MASK;
         maxmaxcode = 1L << maxbits;          zs->zs_maxmaxcode = 1L << zs->zs_maxbits;
         if (maxbits > BITS) {          if (zs->zs_maxbits > BITS) {
                 errno = EFTYPE;                  errno = EFTYPE;
                 return (-1);                  return (-1);
         }          }
         /* As above, initialize the first 256 entries in the table. */          /* As above, initialize the first 256 entries in the table. */
         maxcode = MAXCODE(n_bits = INIT_BITS);          zs->zs_maxcode = MAXCODE(zs->zs_n_bits = INIT_BITS);
         for (code = 255; code >= 0; code--) {          for (zs->zs_code = 255; zs->zs_code >= 0; zs->zs_code--) {
                 tab_prefixof(code) = 0;                  tab_prefixof(zs->zs_code) = 0;
                 tab_suffixof(code) = (char_type) code;                  tab_suffixof(zs->zs_code) = (u_char) zs->zs_code;
         }          }
         free_ent = block_compress ? FIRST : 256;          zs->zs_free_ent = zs->zs_block_compress ? FIRST : 256;
   
         finchar = oldcode = getcode(zs);          zs->zs_finchar = zs->zs_oldcode = getcode(zs);
         if (oldcode == -1)      /* EOF already? */          if (zs->zs_oldcode == -1)       /* EOF already? */
                 return (0);     /* Get out of here */                  return (0);     /* Get out of here */
   
         /* First code must be 8 bits = char. */          /* First code must be 8 bits = char. */
         *bp++ = (u_char)finchar;          *bp++ = (u_char)zs->zs_finchar;
         count--;          count--;
         stackp = de_stack;          zs->zs_stackp = de_stack;
   
         while ((code = getcode(zs)) > -1) {          while ((zs->zs_code = getcode(zs)) > -1) {
   
                 if ((code == CLEAR) && block_compress) {                  if ((zs->zs_code == CLEAR) && zs->zs_block_compress) {
                         for (code = 255; code >= 0; code--)                          for (zs->zs_code = 255; zs->zs_code >= 0;
                                 tab_prefixof(code) = 0;                               zs->zs_code--)
                         clear_flg = 1;                                  tab_prefixof(zs->zs_code) = 0;
                         free_ent = FIRST - 1;                          zs->zs_clear_flg = 1;
                         if ((code = getcode(zs)) == -1) /* O, untimely death! */                          zs->zs_free_ent = FIRST - 1;
                           if ((zs->zs_code = getcode(zs)) == -1)  /* O, untimely death! */
                                 break;                                  break;
                 }                  }
                 incode = code;                  zs->zs_incode = zs->zs_code;
   
                 /* Special case for KwKwK string. */                  /* Special case for KwKwK string. */
                 if (code >= free_ent) {                  if (zs->zs_code >= zs->zs_free_ent) {
                         *stackp++ = finchar;                          *zs->zs_stackp++ = zs->zs_finchar;
                         code = oldcode;                          zs->zs_code = zs->zs_oldcode;
                 }                  }
   
                 /* Generate output characters in reverse order. */                  /* Generate output characters in reverse order. */
                 while (code >= 256) {                  while (zs->zs_code >= 256) {
                         *stackp++ = tab_suffixof(code);                          *zs->zs_stackp++ = tab_suffixof(zs->zs_code);
                         code = tab_prefixof(code);                          zs->zs_code = tab_prefixof(zs->zs_code);
                 }                  }
                 *stackp++ = finchar = tab_suffixof(code);                  *zs->zs_stackp++ = zs->zs_finchar = tab_suffixof(zs->zs_code);
   
                 /* And put them out in forward order.  */                  /* And put them out in forward order.  */
 middle:         do {  middle:         do {
                         if (count-- == 0)                          if (count-- == 0)
                                 return (num);                                  return (num);
                         *bp++ = *--stackp;                          *bp++ = *--zs->zs_stackp;
                 } while (stackp > de_stack);                  } while (zs->zs_stackp > de_stack);
   
                 /* Generate the new entry. */                  /* Generate the new entry. */
                 if ((code = free_ent) < maxmaxcode) {                  if ((zs->zs_code = zs->zs_free_ent) < zs->zs_maxmaxcode) {
                         tab_prefixof(code) = (u_short) oldcode;                          tab_prefixof(zs->zs_code) = (u_short) zs->zs_oldcode;
                         tab_suffixof(code) = finchar;                          tab_suffixof(zs->zs_code) = zs->zs_finchar;
                         free_ent = code + 1;                          zs->zs_free_ent = zs->zs_code + 1;
                 }                  }
   
                 /* Remember previous code. */                  /* Remember previous code. */
                 oldcode = incode;                  zs->zs_oldcode = zs->zs_incode;
         }          }
         state = S_EOF;          zs->zs_state = S_EOF;
 eof:    return (num - count);  eof:    return (num - count);
 }  }
   
Line 577 
Line 561 
  */   */
 static code_int  static code_int
 getcode(zs)  getcode(zs)
         struct s_zstate *zs;          register struct s_zstate *zs;
 {  {
         register code_int gcode;          register code_int gcode;
         register int r_off, bits;          register int r_off, bits;
         register char_type *bp;          register u_char *bp;
   
         bp = gbuf;          bp = zs->zs_buf;
         if (clear_flg > 0 || roffset >= size || free_ent > maxcode) {          if (zs->zs_clear_flg > 0 || zs->zs_roffset >= zs->zs_size ||
               zs->zs_free_ent > zs->zs_maxcode) {
                 /*                  /*
                  * If the next entry will be too big for the current gcode                   * If the next entry will be too big for the current gcode
                  * size, then we must increase the size.  This implies reading                   * size, then we must increase the size.  This implies reading
                  * a new buffer full, too.                   * a new buffer full, too.
                  */                   */
                 if (free_ent > maxcode) {                  if (zs->zs_free_ent > zs->zs_maxcode) {
                         n_bits++;                          zs->zs_n_bits++;
                         if (n_bits == maxbits)  /* Won't get any bigger now. */                          if (zs->zs_n_bits == zs->zs_maxbits)    /* Won't get any bigger now. */
                                 maxcode = maxmaxcode;                                  zs->zs_maxcode = zs->zs_maxmaxcode;
                         else                          else
                                 maxcode = MAXCODE(n_bits);                                  zs->zs_maxcode = MAXCODE(zs->zs_n_bits);
                 }                  }
                 if (clear_flg > 0) {                  if (zs->zs_clear_flg > 0) {
                         maxcode = MAXCODE(n_bits = INIT_BITS);                          zs->zs_maxcode = MAXCODE(zs->zs_n_bits = INIT_BITS);
                         clear_flg = 0;                          zs->zs_clear_flg = 0;
                 }                  }
                 size = fread(gbuf, 1, n_bits, fp);                  zs->zs_size = read(zs->zs_fd, zs->zs_buf, zs->zs_n_bits);
                 if (size <= 0)                  /* End of file. */                  if (zs->zs_size <= 0)                   /* End of file. */
                         return (-1);                          return (-1);
                 roffset = 0;                  zs->zs_roffset = 0;
                 /* Round size down to integral number of codes. */                  /* Round size down to integral number of codes. */
                 size = (size << 3) - (n_bits - 1);                  zs->zs_size = (zs->zs_size << 3) - (zs->zs_n_bits - 1);
         }          }
         r_off = roffset;          r_off = zs->zs_roffset;
         bits = n_bits;          bits = zs->zs_n_bits;
   
         /* Get to the first byte. */          /* Get to the first byte. */
         bp += (r_off >> 3);          bp += (r_off >> 3);
Line 629 
Line 614 
   
         /* High order bits. */          /* High order bits. */
         gcode |= (*bp & rmask[bits]) << r_off;          gcode |= (*bp & rmask[bits]) << r_off;
         roffset += n_bits;          zs->zs_roffset += zs->zs_n_bits;
   
         return (gcode);          return (gcode);
 }  }
   
 static int  static int
 cl_block(zs)                    /* Table clear for block compress. */  cl_block(zs)                    /* Table clear for block compress. */
         struct s_zstate *zs;          register struct s_zstate *zs;
 {  {
         register long rat;          register long rat;
   
         checkpoint = in_count + CHECK_GAP;          zs->zs_checkpoint = zs->zs_in_count + CHECK_GAP;
   
         if (in_count > 0x007fffff) {    /* Shift will overflow. */          if (zs->zs_in_count > 0x007fffff) {     /* Shift will overflow. */
                 rat = bytes_out >> 8;                  rat = zs->zs_bytes_out >> 8;
                 if (rat == 0)           /* Don't divide by zero. */                  if (rat == 0)           /* Don't divide by zero. */
                         rat = 0x7fffffff;                          rat = 0x7fffffff;
                 else                  else
                         rat = in_count / rat;                          rat = zs->zs_in_count / rat;
         } else          } else
                 rat = (in_count << 8) / bytes_out;      /* 8 fractional bits. */                  rat = (zs->zs_in_count << 8) / zs->zs_bytes_out;        /* 8 fractional bits. */
         if (rat > ratio)          if (rat > zs->zs_ratio)
                 ratio = rat;                  zs->zs_ratio = rat;
         else {          else {
                 ratio = 0;                  zs->zs_ratio = 0;
                 cl_hash(zs, (count_int) hsize);                  cl_hash(zs, (count_int) zs->zs_hsize);
                 free_ent = FIRST;                  zs->zs_free_ent = FIRST;
                 clear_flg = 1;                  zs->zs_clear_flg = 1;
                 if (output(zs, (code_int) CLEAR) == -1)                  if (output(zs, (code_int) CLEAR) == -1)
                         return (-1);                          return (-1);
         }          }
Line 665 
Line 650 
   
 static void  static void
 cl_hash(zs, cl_hsize)                   /* Reset code table. */  cl_hash(zs, cl_hsize)                   /* Reset code table. */
         struct s_zstate *zs;          register struct s_zstate *zs;
         register count_int cl_hsize;          register count_int cl_hsize;
 {  {
         register count_int *htab_p;          register count_int *htab_p;
         register long i, m1;          register long i, m1;
   
         m1 = -1;          m1 = -1;
         htab_p = htab + cl_hsize;          htab_p = zs->zs_htab + cl_hsize;
         i = cl_hsize - 16;          i = cl_hsize - 16;
         do {                    /* Might use Sys V memset(3) here. */          do {                    /* Might use Sys V memset(3) here. */
                 *(htab_p - 16) = m1;                  *(htab_p - 16) = m1;
Line 698 
Line 683 
 }  }
   
 FILE *  FILE *
 zdopen(fd, mode, bits)  zopen(name, mode, bits)
           const char *name;
           const char *mode;
           int bits;
   {
         int fd;          int fd;
           void *cookie;
           if ((fd = open(name, (*mode=='r'? O_RDONLY:O_WRONLY|O_CREAT),
                          S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1)
                   return NULL;
           if ((cookie = z_open(fd, mode, bits)) == NULL) {
                   close(fd);
                   return NULL;
           }
           return funopen(cookie, (*mode == 'r'?zread:NULL),
                          (*mode == 'w'?zwrite:NULL), NULL, zclose);
   }
   
   void *
   z_open(fd, mode, bits)
           int fd;
         const char *mode;          const char *mode;
         int bits;          int bits;
 {  {
         struct s_zstate *zs;          register struct s_zstate *zs;
   
         if ((mode[0] != 'r' && mode[0] != 'w') || mode[1] != '\0' ||          if ((mode[0] != 'r' && mode[0] != 'w') || mode[1] != '\0' ||
             bits < 0 || bits > BITS) {              bits < 0 || bits > BITS) {
Line 714 
Line 718 
         if ((zs = calloc(1, sizeof(struct s_zstate))) == NULL)          if ((zs = calloc(1, sizeof(struct s_zstate))) == NULL)
                 return (NULL);                  return (NULL);
   
         maxbits = bits ? bits : BITS;   /* User settable max # bits/code. */          /* User settable max # bits/code. */
         maxmaxcode = 1 << maxbits;      /* Should NEVER generate this code. */          zs->zs_maxbits = bits ? bits : BITS;
         hsize = HSIZE;                  /* For dynamic table sizing. */          /* Should NEVER generate this code. */
         free_ent = 0;                   /* First unused entry. */          zs->zs_maxmaxcode = 1 << zs->zs_maxbits;
         block_compress = BLOCK_MASK;          zs->zs_hsize = HSIZE;           /* For dynamic table sizing. */
         clear_flg = 0;          zs->zs_free_ent = 0;            /* First unused entry. */
         ratio = 0;          zs->zs_block_compress = BLOCK_MASK;
         checkpoint = CHECK_GAP;          zs->zs_clear_flg = 0;
         in_count = 1;                   /* Length of input. */          zs->zs_ratio = 0;
         out_count = 0;                  /* # of codes output (for debugging). */          zs->zs_checkpoint = CHECK_GAP;
         state = S_START;          zs->zs_in_count = 1;            /* Length of input. */
         roffset = 0;          zs->zs_out_count = 0;           /* # of codes output (for debugging).*/
         size = 0;          zs->zs_state = S_START;
           zs->zs_roffset = 0;
           zs->zs_size = 0;
           zs->zs_mode = mode[0];
   
         /*          zs->zs_fd = fd;
          * Layering compress on top of stdio in order to provide buffering,          return zs;
          * and ensure that reads and write work with the data specified.  
          */  
         if ((fp = fdopen(fd, mode)) == NULL) {  
                 free(zs);  
                 return (NULL);  
         }  
         switch (*mode) {  
         case 'r':  
                 zmode = 'r';  
                 return (funopen(zs, zread, NULL, NULL, zclose));  
         case 'w':  
                 zmode = 'w';  
                 return (funopen(zs, NULL, zwrite, NULL, zclose));  
         }  
         /* NOTREACHED */  
 }  }
   
 FILE *  int
 zopen(fname, mode, bits)  z_check_header(fd, sb, ofn)
         const char *fname, *mode;          int fd;
         int bits;          struct stat *sb;
           const char *ofn;
 {  {
         struct s_zstate *zs;          int f;
           u_char buf[sizeof(z_magic)];
           off_t off = lseek(fd, 0, SEEK_CUR);
   
         if ((mode[0] != 'r' && mode[0] != 'w') || mode[1] != '\0' ||          f = (read(fd, buf, sizeof(buf)) == sizeof(buf) &&
             bits < 0 || bits > BITS) {               !memcmp(buf, z_magic, sizeof(buf)));
                 errno = EINVAL;  
                 return (NULL);  
         }  
   
         if ((zs = calloc(1, sizeof(struct s_zstate))) == NULL)          lseek (fd, off, SEEK_SET);
                 return (NULL);  
   
         maxbits = bits ? bits : BITS;   /* User settable max # bits/code. */          return f;
         maxmaxcode = 1 << maxbits;      /* Should NEVER generate this code. */  
         hsize = HSIZE;                  /* For dynamic table sizing. */  
         free_ent = 0;                   /* First unused entry. */  
         block_compress = BLOCK_MASK;  
         clear_flg = 0;  
         ratio = 0;  
         checkpoint = CHECK_GAP;  
         in_count = 1;                   /* Length of input. */  
         out_count = 0;                  /* # of codes output (for debugging). */  
         state = S_START;  
         roffset = 0;  
         size = 0;  
   
         /*  
          * Layering compress on top of stdio in order to provide buffering,  
          * and ensure that reads and write work with the data specified.  
          */  
         if ((fp = fopen(fname, mode)) == NULL) {  
                 free(zs);  
                 return (NULL);  
         }  
         switch (*mode) {  
         case 'r':  
                 zmode = 'r';  
                 return (funopen(zs, zread, NULL, NULL, zclose));  
         case 'w':  
                 zmode = 'w';  
                 return (funopen(zs, NULL, zwrite, NULL, zclose));  
         }  
         /* NOTREACHED */  
 }  }

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5