"Fossies" - the Fresh Open Source Software Archive

Member "ncompress-5.0/compress.c" (2 Feb 2021, 44489 Bytes) of package /linux/privat/ncompress-5.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "compress.c" see the Fossies "Dox" file reference documentation.

    1 /* (N)compress.c - File compression ala IEEE Computer, Mar 1992.
    2  *
    3  * Authors:
    4  *   Spencer W. Thomas   (decvax!harpo!utah-cs!utah-gr!thomas)
    5  *   Jim McKie           (decvax!mcvax!jim)
    6  *   Steve Davies        (decvax!vax135!petsd!peora!srd)
    7  *   Ken Turkowski       (decvax!decwrl!turtlevax!ken)
    8  *   James A. Woods      (decvax!ihnp4!ames!jaw)
    9  *   Joe Orost           (decvax!vax135!petsd!joe)
   10  *   Dave Mack           (csu@alembic.acs.com)
   11  *   Peter Jannesen, Network Communication Systems
   12  *                       (peter@ncs.nl)
   13  *   Mike Frysinger      (vapier@gmail.com)
   14  *
   15  * Revision 4.2.3  92/03/14 peter@ncs.nl
   16  *   Optimise compress and decompress function and a lot of cleanups.
   17  *   New fast hash algoritme added (if more than 800Kb available).
   18  *
   19  * Revision 4.1  91/05/26 csu@alembic.acs.com
   20  *   Modified to recursively compress directories ('r' flag). As a side
   21  *   effect, compress will no longer attempt to compress things that
   22  *   aren't "regular" files. See Changes.
   23  *
   24  * Revision 4.0  85/07/30  12:50:00  joe
   25  *   Removed ferror() calls in output routine on every output except first.
   26  *   Prepared for release to the world.
   27  * 
   28  * Revision 3.6  85/07/04  01:22:21  joe
   29  *   Remove much wasted storage by overlaying hash table with the tables
   30  *   used by decompress: tab_suffix[1<<BITS], stack[8000].  Updated USERMEM
   31  *   computations.  Fixed dump_tab() DEBUG routine.
   32  *
   33  * Revision 3.5  85/06/30  20:47:21  jaw
   34  *   Change hash function to use exclusive-or.  Rip out hash cache.  These
   35  *   speedups render the megamemory version defunct, for now.  Make decoder
   36  *   stack global.  Parts of the RCS trunks 2.7, 2.6, and 2.1 no longer apply.
   37  *
   38  * Revision 3.4  85/06/27  12:00:00  ken
   39  *   Get rid of all floating-point calculations by doing all compression ratio
   40  *   calculations in fixed point.
   41  *
   42  * Revision 3.3  85/06/24  21:53:24  joe
   43  *   Incorporate portability suggestion for M_XENIX.  Got rid of text on #else
   44  *   and #endif lines.  Cleaned up #ifdefs for vax and interdata.
   45  *
   46  * Revision 3.2  85/06/06  21:53:24  jaw
   47  *   Incorporate portability suggestions for Z8000, IBM PC/XT from mailing list.
   48  *   Default to "quiet" output (no compression statistics).
   49  *
   50  * Revision 3.1  85/05/12  18:56:13  jaw
   51  *   Integrate decompress() stack speedups (from early pointer mods by McKie).
   52  *   Repair multi-file USERMEM gaffe.  Unify 'force' flags to mimic semantics
   53  *   of SVR2 'pack'.  Streamline block-compress table clear logic.  Increase 
   54  *   output byte count by magic number size.
   55  * 
   56  * Revision 3.0   84/11/27  11:50:00  petsd!joe
   57  *   Set HSIZE depending on BITS.  Set BITS depending on USERMEM.  Unrolled
   58  *   loops in clear routines.  Added "-C" flag for 2.0 compatibility.  Used
   59  *   unsigned compares on Perkin-Elmer.  Fixed foreground check.
   60  *
   61  * Revision 2.7   84/11/16  19:35:39  ames!jaw
   62  *   Cache common hash codes based on input statistics; this improves
   63  *   performance for low-density raster images.  Pass on #ifdef bundle
   64  *   from Turkowski.
   65  *
   66  * Revision 2.6   84/11/05  19:18:21  ames!jaw
   67  *   Vary size of hash tables to reduce time for small files.
   68  *   Tune PDP-11 hash function.
   69  *
   70  * Revision 2.5   84/10/30  20:15:14  ames!jaw
   71  *   Junk chaining; replace with the simpler (and, on the VAX, faster)
   72  *   double hashing, discussed within.  Make block compression standard.
   73  *
   74  * Revision 2.4   84/10/16  11:11:11  ames!jaw
   75  *   Introduce adaptive reset for block compression, to boost the rate
   76  *   another several percent.  (See mailing list notes.)
   77  *
   78  * Revision 2.3   84/09/22  22:00:00  petsd!joe
   79  *   Implemented "-B" block compress.  Implemented REVERSE sorting of tab_next.
   80  *   Bug fix for last bits.  Changed fwrite to putchar loop everywhere.
   81  *
   82  * Revision 2.2   84/09/18  14:12:21  ames!jaw
   83  *   Fold in news changes, small machine typedef from thomas,
   84  *   #ifdef interdata from joe.
   85  *
   86  * Revision 2.1   84/09/10  12:34:56  ames!jaw
   87  *   Configured fast table lookup for 32-bit machines.
   88  *   This cuts user time in half for b <= FBITS, and is useful for news batching
   89  *   from VAX to PDP sites.  Also sped up decompress() [fwrite->putc] and
   90  *   added signal catcher [plus beef in write_error()] to delete effluvia.
   91  *
   92  * Revision 2.0   84/08/28  22:00:00  petsd!joe
   93  *   Add check for foreground before prompting user.  Insert maxbits into
   94  *   compressed file.  Force file being uncompressed to end with ".Z".
   95  *   Added "-c" flag and "zcat".  Prepared for release.
   96  *
   97  * Revision 1.10  84/08/24  18:28:00  turtlevax!ken
   98  *   Will only compress regular files (no directories), added a magic number
   99  *   header (plus an undocumented -n flag to handle old files without headers),
  100  *   added -f flag to force overwriting of possibly existing destination file,
  101  *   otherwise the user is prompted for a response.  Will tack on a .Z to a
  102  *   filename if it doesn't have one when decompressing.  Will only replace
  103  *   file if it was compressed.
  104  *
  105  * Revision 1.9  84/08/16  17:28:00  turtlevax!ken
  106  *   Removed scanargs(), getopt(), added .Z extension and unlimited number of
  107  *   filenames to compress.  Flags may be clustered (-Ddvb12) or separated
  108  *   (-D -d -v -b 12), or combination thereof.  Modes and other status is
  109  *   copied with copystat().  -O bug for 4.2 seems to have disappeared with
  110  *   1.8.
  111  *
  112  * Revision 1.8  84/08/09  23:15:00  joe
  113  *   Made it compatible with vax version, installed jim's fixes/enhancements
  114  *
  115  * Revision 1.6  84/08/01  22:08:00  joe
  116  *   Sped up algorithm significantly by sorting the compress chain.
  117  *
  118  * Revision 1.5  84/07/13  13:11:00  srd
  119  *   Added C version of vax asm routines.  Changed structure to arrays to
  120  *   save much memory.  Do unsigned compares where possible (faster on
  121  *   Perkin-Elmer)
  122  *
  123  * Revision 1.4  84/07/05  03:11:11  thomas
  124  *   Clean up the code a little and lint it.  (Lint complains about all
  125  *   the regs used in the asm, but I'm not going to "fix" this.)
  126  *
  127  * Revision 1.3  84/07/05  02:06:54  thomas
  128  *   Minor fixes.
  129  *
  130  * Revision 1.2  84/07/05  00:27:27  thomas
  131  *   Add variable bit length output.
  132  *
  133  */
  134 
  135 #ifdef _MSC_VER
  136 #   define  WINDOWS
  137 #endif
  138 
  139 #ifdef __MINGW32__
  140 #   define  MINGW
  141 #endif
  142 
  143 #include    <stdint.h>
  144 #include    <stdio.h>
  145 #include    <stdlib.h>
  146 #include    <string.h>
  147 #include    <fcntl.h>
  148 #include    <ctype.h>
  149 #include    <signal.h>
  150 #include    <sys/types.h>
  151 #include    <sys/stat.h>
  152 #include    <errno.h>
  153 
  154 #if !defined(DOS) && !defined(WINDOWS)
  155 #   include <dirent.h>
  156 #   define RECURSIVE 1
  157 #   include <unistd.h>
  158 #else
  159 #   include <io.h>
  160 #endif
  161 
  162 #ifdef UTIME_H
  163 #   include <utime.h>
  164 #else
  165     struct utimbuf {
  166         time_t actime;
  167         time_t modtime;
  168     };
  169 #endif
  170 
  171 #ifdef  __STDC__
  172 #   define  ARGS(a)             a
  173 #else
  174 #   define  ARGS(a)             ()
  175 #endif
  176 
  177 #ifndef SIG_TYPE
  178 #   define  SIG_TYPE    void (*)()
  179 #endif
  180 
  181 #if defined(AMIGA) || defined(DOS) || defined(MINGW) || defined(WINDOWS)
  182 #   define  chmod(pathname, mode) 0
  183 #   define  chown(pathname, owner, group) 0
  184 #   define  utime(pathname, times) 0
  185 #endif
  186 
  187 #if defined(MINGW) || defined(WINDOWS)
  188 #   define isatty(fd) 0
  189 #   define open _open
  190 #   define close _close
  191 #   define read _read
  192 #   define strdup _strdup
  193 #   define unlink _unlink
  194 #   define write _write
  195 #else
  196 /* NB: macOS has a setmode() that is different from Windows. */
  197 #   define setmode(fd, mode)
  198 #endif
  199 
  200 #ifndef LSTAT
  201 #   define  lstat   stat
  202 #endif
  203 
  204 #if defined(DOS) || defined(WINDOWS)
  205 #   define  F_OK    0
  206 static inline int access(const char *pathname, int mode)
  207 {
  208     struct stat st;
  209     return lstat(pathname, &st);
  210 }
  211 #endif
  212 
  213 #include "patchlevel.h"
  214 
  215 #undef  min
  216 #define min(a,b)    ((a>b) ? b : a)
  217 
  218 #ifndef IBUFSIZ
  219 #   define  IBUFSIZ BUFSIZ  /* Defailt input buffer size                            */
  220 #endif
  221 #ifndef OBUFSIZ
  222 #   define  OBUFSIZ BUFSIZ  /* Default output buffer size                           */
  223 #endif
  224 
  225                             /* Defines for third byte of header                     */
  226 #define MAGIC_1     (char_type)'\037'/* First byte of compressed file               */
  227 #define MAGIC_2     (char_type)'\235'/* Second byte of compressed file              */
  228 #define BIT_MASK    0x1f            /* Mask for 'number of compresssion bits'       */
  229                                     /* Masks 0x20 and 0x40 are free.                */
  230                                     /* I think 0x20 should mean that there is       */
  231                                     /* a fourth header byte (for expansion).        */
  232 #define BLOCK_MODE  0x80            /* Block compresssion if table is full and      */
  233                                     /* compression rate is dropping flush tables    */
  234 
  235             /* the next two codes should not be changed lightly, as they must not   */
  236             /* lie within the contiguous general code space.                        */
  237 #define FIRST   257                 /* first free entry                             */
  238 #define CLEAR   256                 /* table clear output code                      */
  239 
  240 #define INIT_BITS 9         /* initial number of bits/code */
  241 
  242 #ifndef SACREDMEM
  243     /*
  244      * SACREDMEM is the amount of physical memory saved for others; compress
  245      * will hog the rest.
  246      */
  247 #   define SACREDMEM    0
  248 #endif
  249 
  250 #ifndef USERMEM
  251     /*
  252      * Set USERMEM to the maximum amount of physical user memory available
  253      * in bytes.  USERMEM is used to determine the maximum BITS that can be used
  254      * for compression.
  255      */
  256 #   define USERMEM  450000  /* default user memory */
  257 #endif
  258 
  259 #ifndef BYTEORDER
  260 #   define  BYTEORDER   0000
  261 #endif
  262 
  263 /*
  264  * machine variants which require cc -Dmachine:  pdp11, z8000, DOS
  265  */
  266 
  267 #ifdef  DOS         /* PC/XT/AT (8088) processor                                    */
  268 #   define  BITS   16   /* 16-bits processor max 12 bits                            */
  269 #   if BITS == 16
  270 #       define  MAXSEG_64K
  271 #   endif
  272 #   undef   BYTEORDER
  273 #   define  BYTEORDER   4321
  274 #endif /* DOS */
  275 
  276 #ifndef O_BINARY
  277 #   define  O_BINARY    0   /* System has no binary mode                            */
  278 #endif
  279 
  280 #ifdef M_XENIX          /* Stupid compiler can't handle arrays with */
  281 #   if BITS == 16       /* more than 65535 bytes - so we fake it */
  282 #       define MAXSEG_64K
  283 #   else
  284 #   if BITS > 13            /* Code only handles BITS = 12, 13, or 16 */
  285 #       define BITS 13
  286 #   endif
  287 #   endif
  288 #endif
  289 
  290 #ifndef BITS        /* General processor calculate BITS                             */
  291 #   if USERMEM >= (800000+SACREDMEM)
  292 #       define FAST
  293 #   else
  294 #   if USERMEM >= (433484+SACREDMEM)
  295 #       define BITS 16
  296 #   else
  297 #   if USERMEM >= (229600+SACREDMEM)
  298 #       define BITS 15
  299 #   else
  300 #   if USERMEM >= (127536+SACREDMEM)
  301 #       define BITS 14
  302 #   else
  303 #   if USERMEM >= (73464+SACREDMEM)
  304 #       define BITS 13
  305 #   else
  306 #       define BITS 12
  307 #   endif
  308 #   endif
  309 #   endif
  310 #   endif
  311 #   endif
  312 #endif /* BITS */
  313 
  314 #ifdef FAST
  315 #   define  HBITS       17          /* 50% occupancy */
  316 #   define  HSIZE      (1<<HBITS)
  317 #   define  HMASK      (HSIZE-1)
  318 #   define  HPRIME       9941
  319 #   define  BITS           16
  320 #   undef   MAXSEG_64K
  321 #else
  322 #   if BITS == 16
  323 #       define HSIZE    69001       /* 95% occupancy */
  324 #   endif
  325 #   if BITS == 15
  326 #       define HSIZE    35023       /* 94% occupancy */
  327 #   endif
  328 #   if BITS == 14
  329 #       define HSIZE    18013       /* 91% occupancy */
  330 #   endif
  331 #   if BITS == 13
  332 #       define HSIZE    9001        /* 91% occupancy */
  333 #   endif
  334 #   if BITS <= 12
  335 #       define HSIZE    5003        /* 80% occupancy */
  336 #   endif
  337 #endif
  338 
  339 #define CHECK_GAP 10000
  340 
  341 typedef long int            code_int;
  342 
  343 #ifdef SIGNED_COMPARE_SLOW
  344     typedef unsigned long int   count_int;
  345     typedef unsigned short int  count_short;
  346     typedef unsigned long int   cmp_code_int;   /* Cast to make compare faster  */
  347 #else
  348     typedef long int            count_int;
  349     typedef long int            cmp_code_int;
  350 #endif
  351 
  352 typedef unsigned char   char_type;
  353 
  354 #define ARGVAL() (*++(*argv) || (--argc && *++argv))
  355 
  356 #define MAXCODE(n)  (1L << (n))
  357 
  358 union   bytes
  359 {
  360     long    word;
  361     struct
  362     {
  363 #if BYTEORDER == 4321
  364         char_type   b1;
  365         char_type   b2;
  366         char_type   b3;
  367         char_type   b4;
  368 #else
  369 #if BYTEORDER == 1234
  370         char_type   b4;
  371         char_type   b3;
  372         char_type   b2;
  373         char_type   b1;
  374 #else
  375 #   undef   BYTEORDER
  376         int             dummy;
  377 #endif
  378 #endif
  379     } bytes;
  380 } ;
  381 #ifdef BYTEORDER
  382 #define output(b,o,c,n) {   char_type   *p = &(b)[(o)>>3];                  \
  383                             union bytes i;                                  \
  384                             i.word = ((long)(c))<<((o)&0x7);                \
  385                             p[0] |= i.bytes.b1;                             \
  386                             p[1] |= i.bytes.b2;                             \
  387                             p[2] |= i.bytes.b3;                             \
  388                             (o) += (n);                                     \
  389                         }
  390 #else
  391 #define output(b,o,c,n) {   char_type   *p = &(b)[(o)>>3];                  \
  392                             long         i = ((long)(c))<<((o)&0x7);        \
  393                             p[0] |= (char_type)(i);                         \
  394                             p[1] |= (char_type)(i>>8);                      \
  395                             p[2] |= (char_type)(i>>16);                     \
  396                             (o) += (n);                                     \
  397                         }
  398 #endif
  399 #define input(b,o,c,n,m){   char_type       *p = &(b)[(o)>>3];              \
  400                             (c) = ((((long)(p[0]))|((long)(p[1])<<8)|       \
  401                                      ((long)(p[2])<<16))>>((o)&0x7))&(m);   \
  402                             (o) += (n);                                     \
  403                         }
  404 
  405 char            *progname;          /* Program name                                 */
  406 int             silent = 0;         /* don't tell me about errors                   */
  407 int             quiet = 1;          /* don't tell me about compression              */
  408 int             do_decomp = 0;      /* Decompress mode                              */
  409 int             force = 0;          /* Force overwrite of files and links           */
  410 int             keep = 0;           /* Keep input files                             */
  411 int             nomagic = 0;        /* Use a 3-byte magic number header,            */
  412                                     /* unless old file                              */
  413 int             maxbits = BITS;     /* user settable max # bits/code                */
  414 int             zcat_flg = 0;       /* Write output on stdout, suppress messages    */
  415 int             recursive = 0;      /* compress directories                         */
  416 int             exit_code = -1;     /* Exitcode of compress (-1 no file compressed) */
  417 
  418 char_type       inbuf[IBUFSIZ+64];  /* Input buffer                                 */
  419 char_type       outbuf[OBUFSIZ+2048];/* Output buffer                               */
  420 
  421 struct stat     infstat;            /* Input file status                            */
  422 char            *ifname;            /* Input filename                               */
  423 int             remove_ofname = 0;  /* Remove output file on a error                */
  424 char            *ofname = NULL;     /* Output filename                              */
  425 int             fgnd_flag = 0;      /* Running in background (SIGINT=SIGIGN)        */
  426 
  427 long            bytes_in;           /* Total number of byte from input              */
  428 long            bytes_out;          /* Total number of byte to output               */
  429 
  430 /*
  431  * 8086 & 80286 Has a problem with array bigger than 64K so fake the array
  432  * For processors with a limited address space and segments.
  433  */
  434 /*
  435  * To save much memory, we overlay the table used by compress() with those
  436  * used by decompress().  The tab_prefix table is the same size and type
  437  * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
  438  * get this from the beginning of htab.  The output stack uses the rest
  439  * of htab, and contains characters.  There is plenty of room for any
  440  * possible stack (stack used to be 8000 characters).
  441  */
  442 #ifdef MAXSEG_64K
  443     count_int htab0[8192];
  444     count_int htab1[8192];
  445     count_int htab2[8192];
  446     count_int htab3[8192];
  447     count_int htab4[8192];
  448     count_int htab5[8192];
  449     count_int htab6[8192];
  450     count_int htab7[8192];
  451     count_int htab8[HSIZE-65536];
  452     count_int * htab[9] = {htab0,htab1,htab2,htab3,htab4,htab5,htab6,htab7,htab8};
  453 
  454     unsigned short code0tab[16384];
  455     unsigned short code1tab[16384];
  456     unsigned short code2tab[16384];
  457     unsigned short code3tab[16384];
  458     unsigned short code4tab[16384];
  459     unsigned short * codetab[5] = {code0tab,code1tab,code2tab,code3tab,code4tab};
  460 
  461 #   define  htabof(i)           (htab[(i) >> 13][(i) & 0x1fff])
  462 #   define  codetabof(i)        (codetab[(i) >> 14][(i) & 0x3fff])
  463 #   define  tab_prefixof(i)     codetabof(i)
  464 #   define  tab_suffixof(i)     ((char_type *)htab[(i)>>15])[(i) & 0x7fff]
  465 #   define  de_stack            ((char_type *)(&htab2[8191]))
  466     void    clear_htab()
  467     {
  468         memset(htab0, -1, sizeof(htab0));
  469         memset(htab1, -1, sizeof(htab1));
  470         memset(htab2, -1, sizeof(htab2));
  471         memset(htab3, -1, sizeof(htab3));
  472         memset(htab4, -1, sizeof(htab4));
  473         memset(htab5, -1, sizeof(htab5));
  474         memset(htab6, -1, sizeof(htab6));
  475         memset(htab7, -1, sizeof(htab7));
  476         memset(htab8, -1, sizeof(htab8));
  477      }
  478 #   define  clear_tab_prefixof()    memset(code0tab, 0, 256);
  479 #else   /* Normal machine */
  480     count_int       htab[HSIZE];
  481     unsigned short  codetab[HSIZE];
  482 
  483 #   define  htabof(i)               htab[i]
  484 #   define  codetabof(i)            codetab[i]
  485 #   define  tab_prefixof(i)         codetabof(i)
  486 #   define  tab_suffixof(i)         ((char_type *)(htab))[i]
  487 #   define  de_stack                ((char_type *)&(htab[HSIZE-1]))
  488 #   define  clear_htab()            memset(htab, -1, sizeof(htab))
  489 #   define  clear_tab_prefixof()    memset(codetab, 0, 256);
  490 #endif  /* MAXSEG_64K */
  491 
  492 #ifdef FAST
  493     int primetab[256] =     /* Special secudary hash table.     */
  494     {
  495          1013, -1061, 1109, -1181, 1231, -1291, 1361, -1429,
  496          1481, -1531, 1583, -1627, 1699, -1759, 1831, -1889,
  497          1973, -2017, 2083, -2137, 2213, -2273, 2339, -2383,
  498          2441, -2531, 2593, -2663, 2707, -2753, 2819, -2887,
  499          2957, -3023, 3089, -3181, 3251, -3313, 3361, -3449,
  500          3511, -3557, 3617, -3677, 3739, -3821, 3881, -3931,
  501          4013, -4079, 4139, -4219, 4271, -4349, 4423, -4493,
  502          4561, -4639, 4691, -4783, 4831, -4931, 4973, -5023,
  503          5101, -5179, 5261, -5333, 5413, -5471, 5521, -5591,
  504          5659, -5737, 5807, -5857, 5923, -6029, 6089, -6151,
  505          6221, -6287, 6343, -6397, 6491, -6571, 6659, -6709,
  506          6791, -6857, 6917, -6983, 7043, -7129, 7213, -7297,
  507          7369, -7477, 7529, -7577, 7643, -7703, 7789, -7873,
  508          7933, -8017, 8093, -8171, 8237, -8297, 8387, -8461,
  509          8543, -8627, 8689, -8741, 8819, -8867, 8963, -9029,
  510          9109, -9181, 9241, -9323, 9397, -9439, 9511, -9613,
  511          9677, -9743, 9811, -9871, 9941,-10061,10111,-10177,
  512         10259,-10321,10399,-10477,10567,-10639,10711,-10789,
  513         10867,-10949,11047,-11113,11173,-11261,11329,-11423,
  514         11491,-11587,11681,-11777,11827,-11903,11959,-12041,
  515         12109,-12197,12263,-12343,12413,-12487,12541,-12611,
  516         12671,-12757,12829,-12917,12979,-13043,13127,-13187,
  517         13291,-13367,13451,-13523,13619,-13691,13751,-13829,
  518         13901,-13967,14057,-14153,14249,-14341,14419,-14489,
  519         14557,-14633,14717,-14767,14831,-14897,14983,-15083,
  520         15149,-15233,15289,-15359,15427,-15497,15583,-15649,
  521         15733,-15791,15881,-15937,16057,-16097,16189,-16267,
  522         16363,-16447,16529,-16619,16691,-16763,16879,-16937,
  523         17021,-17093,17183,-17257,17341,-17401,17477,-17551,
  524         17623,-17713,17791,-17891,17957,-18041,18097,-18169,
  525         18233,-18307,18379,-18451,18523,-18637,18731,-18803,
  526         18919,-19031,19121,-19211,19273,-19381,19429,-19477
  527     } ;
  528 #endif
  529 
  530 int     main            ARGS((int,char **));
  531 void    Usage           ARGS((int));
  532 void    comprexx        ARGS((const char *));
  533 void    compdir         ARGS((char *));
  534 void    compress        ARGS((int,int));
  535 void    decompress      ARGS((int,int));
  536 void    read_error      ARGS((void));
  537 void    write_error     ARGS((void));
  538 void    abort_compress  ARGS((void));
  539 void    prratio         ARGS((FILE *,long,long));
  540 void    about           ARGS((void));
  541 
  542 /*****************************************************************
  543  * TAG( main )
  544  *
  545  * Algorithm from "A Technique for High Performance Data Compression",
  546  * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
  547  *
  548  * Usage: compress [-dfvc] [-b bits] [file ...]
  549  * Inputs:
  550  *   -d:     If given, decompression is done instead.
  551  *
  552  *   -c:     Write output on stdout, don't remove original.
  553  *
  554  *   -b:     Parameter limits the max number of bits/code.
  555  *
  556  *   -f:     Forces output file to be generated, even if one already
  557  *           exists, and even if no space is saved by compressing.
  558  *           If -f is not used, the user will be prompted if stdin is
  559  *           a tty, otherwise, the output file will not be overwritten.
  560  *
  561  *   -v:     Write compression statistics
  562  *
  563  *   -r:     Recursive. If a filename is a directory, descend
  564  *           into it and compress everything in it.
  565  *
  566  * file ...:
  567  *           Files to be compressed.  If none specified, stdin is used.
  568  * Outputs:
  569  *   file.Z:     Compressed form of file with same mode, owner, and utimes
  570  *   or stdout   (if stdin used as input)
  571  *
  572  * Assumptions:
  573  *   When filenames are given, replaces with the compressed version
  574  *   (.Z suffix) only if the file decreases in size.
  575  *
  576  * Algorithm:
  577  *   Modified Lempel-Ziv method (LZW).  Basically finds common
  578  *   substrings and replaces them with a variable size code.  This is
  579  *   deterministic, and can be done on the fly.  Thus, the decompression
  580  *   procedure needs no input table, but tracks the way the table was built.
  581  */ 
  582 int
  583 main(argc, argv)
  584     int      argc;
  585     char    *argv[];
  586     {
  587         char **filelist;
  588         char **fileptr;
  589         int seen_double_dash = 0;
  590 
  591 #ifdef SIGINT
  592         if ((fgnd_flag = (signal(SIGINT, SIG_IGN)) != SIG_IGN))
  593             signal(SIGINT, (SIG_TYPE)abort_compress);
  594 #endif
  595 
  596 #ifdef SIGTERM
  597         signal(SIGTERM, (SIG_TYPE)abort_compress);
  598 #endif
  599 #ifdef SIGHUP
  600         signal(SIGHUP, (SIG_TYPE)abort_compress);
  601 #endif
  602 
  603 #ifdef COMPATIBLE
  604         nomagic = 1;    /* Original didn't have a magic number */
  605 #endif
  606 
  607         filelist = (char **)malloc(argc*sizeof(char *));
  608         if (filelist == NULL)
  609         {
  610             fprintf(stderr, "Cannot allocate memory for file list.\n");
  611             exit (1);
  612         }
  613         fileptr = filelist;
  614         *filelist = NULL;
  615 
  616         if((progname = strrchr(argv[0], '/')) != 0)
  617             progname++;
  618         else
  619             progname = argv[0];
  620 
  621         if (strcmp(progname, "uncompress") == 0)
  622             do_decomp = 1;
  623         else
  624         if (strcmp(progname, "zcat") == 0)
  625             do_decomp = zcat_flg = 1;
  626 
  627         /* Argument Processing
  628          * All flags are optional.
  629          * -V => print Version; debug verbose
  630          * -d => do_decomp
  631          * -v => unquiet
  632          * -f => force overwrite of output file
  633          * -k => keep input files
  634          * -n => no header: useful to uncompress old files
  635          * -b maxbits => maxbits.  If -b is specified, then maxbits MUST be given also.
  636          * -c => cat all output to stdout
  637          * -C => generate output compatible with compress 2.0.
  638          * -r => recursively compress directories
  639          * if a string is left, must be an input filename.
  640          */
  641 
  642         for (argc--, argv++; argc > 0; argc--, argv++)
  643         {
  644             if (strcmp(*argv, "--") == 0)
  645             {
  646                 seen_double_dash = 1;
  647                 continue;
  648             }
  649 
  650             if (seen_double_dash == 0 && **argv == '-')
  651             {/* A flag argument */
  652                 while (*++(*argv))
  653                 {/* Process all flags in this arg */
  654                     switch (**argv)
  655                     {
  656                     case 'V':
  657                         about();
  658                         break;
  659 
  660                     case 's':
  661                         silent = 1;
  662                         quiet = 1;
  663                         break;
  664 
  665                     case 'v':
  666                         silent = 0;
  667                         quiet = 0;
  668                         break;
  669 
  670                     case 'd':
  671                         do_decomp = 1;
  672                         break;
  673 
  674                     case 'k':
  675                         keep = 1;
  676                         break;
  677 
  678                     case 'f':
  679                     case 'F':
  680                         force = 1;
  681                         break;
  682 
  683                     case 'n':
  684                         nomagic = 1;
  685                         break;
  686 
  687                     case 'b':
  688                         if (!ARGVAL())
  689                         {
  690                             fprintf(stderr, "Missing maxbits\n");
  691                             Usage(1);
  692                         }
  693 
  694                         maxbits = atoi(*argv);
  695                         goto nextarg;
  696 
  697                     case 'c':
  698                         zcat_flg = 1;
  699                         break;
  700 
  701                     case 'q':
  702                         quiet = 1;
  703                         break;
  704                     case 'r':
  705                     case 'R':
  706 #ifdef  RECURSIVE
  707                         recursive = 1;
  708 #else
  709                         fprintf(stderr, "%s -r not available (due to missing directory functions)\n", *argv);
  710 #endif
  711                         break;
  712 
  713                     case 'h':
  714                         Usage(0);
  715                         break;
  716 
  717                     default:
  718                         fprintf(stderr, "Unknown flag: '%c'; ", **argv);
  719                         Usage(1);
  720                     }
  721                 }
  722             }
  723             else
  724             {
  725                 *fileptr++ = *argv; /* Build input file list */
  726                 *fileptr = NULL;
  727             }
  728 
  729 nextarg:    continue;
  730         }
  731 
  732         if (maxbits < INIT_BITS)    maxbits = INIT_BITS;
  733         if (maxbits > BITS)         maxbits = BITS;
  734 
  735         if (*filelist != NULL)
  736         {
  737             for (fileptr = filelist; *fileptr; fileptr++)
  738                 comprexx(*fileptr);
  739         }
  740         else
  741         {/* Standard input */
  742             ifname = "";
  743             exit_code = 0;
  744             remove_ofname = 0;
  745 
  746             setmode(0, O_BINARY);
  747             setmode(1, O_BINARY);
  748 
  749             if (do_decomp == 0)
  750             {
  751                 compress(0, 1);
  752 
  753                 if (zcat_flg == 0 && !quiet)
  754                 {
  755                     fprintf(stderr, "Compression: ");
  756                     prratio(stderr, bytes_in-bytes_out, bytes_in);
  757                     fprintf(stderr, "\n");
  758                 }
  759 
  760                 if (bytes_out >= bytes_in && !(force))
  761                     exit_code = 2;
  762             }
  763             else
  764                 decompress(0, 1);
  765         }
  766 
  767         if (recursive && exit_code == -1) {
  768             fprintf(stderr, "no files processed after recursive search\n");
  769         }
  770         exit((exit_code== -1) ? 1:exit_code);
  771     }
  772 
  773 void
  774 Usage(int status)
  775     {
  776         fprintf(status ? stderr : stdout, "\
  777 Usage: %s [-dfhvcVr] [-b maxbits] [--] [path ...]\n\
  778   --   Halt option processing and treat all remaining args as paths.\n\
  779   -d   If given, decompression is done instead.\n\
  780   -c   Write output on stdout, don't remove original.\n\
  781   -k   Keep input files (do not automatically remove).\n\
  782   -b   Parameter limits the max number of bits/code.\n\
  783   -f   Forces output file to be generated, even if one already.\n\
  784        exists, and even if no space is saved by compressing.\n\
  785        If -f is not used, the user will be prompted if stdin is.\n\
  786        a tty, otherwise, the output file will not be overwritten.\n\
  787   -h   This help output.\n\
  788   -v   Write compression statistics.\n\
  789   -V   Output version and compile options.\n\
  790   -r   Recursive. If a path is a directory, compress everything in it.\n",
  791             progname);
  792 
  793             exit(status);
  794     }
  795 
  796 void
  797 comprexx(fileptr)
  798     const char  *fileptr;
  799     {
  800         int              fdin = -1;
  801         int              fdout = -1;
  802         int              has_z_suffix;
  803         char            *tempname;
  804         unsigned long    namesize = strlen(fileptr);
  805 
  806         /* Create a temp buffer to add/remove the .Z suffix. */
  807         tempname = malloc(namesize + 3);
  808         if (tempname == NULL)
  809         {
  810             perror("malloc");
  811             goto error;
  812         }
  813 
  814         strcpy(tempname,fileptr);
  815         has_z_suffix = (namesize >= 2 && strcmp(&tempname[namesize - 2], ".Z") == 0);
  816         errno = 0;
  817 
  818         if (lstat(tempname,&infstat) == -1)
  819         {
  820             if (do_decomp)
  821             {
  822                 switch (errno)
  823                 {
  824                 case ENOENT:    /* file doesn't exist */
  825                     /*
  826                     ** if the given name doesn't end with .Z, try appending one
  827                     ** This is obviously the wrong thing to do if it's a 
  828                     ** directory, but it shouldn't do any harm.
  829                     */
  830                     if (!has_z_suffix)
  831                     {
  832                         memcpy(&tempname[namesize], ".Z", 3);
  833                         namesize += 2;
  834                         has_z_suffix = 1;
  835                         errno = 0;
  836                         if (lstat(tempname,&infstat) == -1)
  837                         {
  838                             perror(tempname);
  839                             goto error;
  840                         }
  841 
  842                         if ((infstat.st_mode & S_IFMT) != S_IFREG)
  843                         {
  844                             fprintf(stderr, "%s: Not a regular file.\n", tempname);
  845                             goto error;
  846                         }
  847                     }
  848                     else
  849                     {
  850                         perror(tempname);
  851                         goto error;
  852                     }
  853 
  854                     break;
  855 
  856                 default:
  857                     perror(tempname);
  858                     goto error;
  859                 }
  860             }
  861             else
  862             {
  863                 perror(tempname);
  864                 goto error;
  865             }
  866         }
  867 
  868         switch (infstat.st_mode & S_IFMT)
  869         {
  870         case S_IFDIR:   /* directory */
  871 #ifdef  RECURSIVE
  872             if (recursive)
  873                 compdir(tempname);
  874             else
  875 #endif
  876             if (!quiet)
  877                 fprintf(stderr,"%s is a directory -- ignored\n", tempname);
  878             break;
  879 
  880         case S_IFREG:   /* regular file */
  881             if (do_decomp != 0)
  882             {/* DECOMPRESSION */
  883                 if (!zcat_flg)
  884                 {
  885                     if (!has_z_suffix)
  886                     {
  887                         /* Ignore this scenario in recursive mode: while we
  888                          * decompress files in this dir, our readdir scan
  889                          * might turn up those new files.  There is no way
  890                          * to efficiently handle this on very large dirs,
  891                          * so we ignore it.  This also allows the user to
  892                          * easily resume partial decompressions.
  893                          */
  894                         if (recursive) {
  895                             free(tempname);
  896                             return;
  897                         }
  898 
  899                         if (!quiet)
  900                             fprintf(stderr,"%s - no .Z suffix\n",tempname);
  901 
  902                         goto error;
  903                     }
  904                 }
  905 
  906                 free(ofname);
  907                 ofname = strdup(tempname);
  908                 if (ofname == NULL)
  909                 {
  910                     perror("strdup");
  911                     goto error;
  912                 }
  913 
  914                 /* Strip of .Z suffix */
  915                 if (has_z_suffix)
  916                     ofname[namesize - 2] = '\0';
  917             }
  918             else
  919             {/* COMPRESSION */
  920                 if (!zcat_flg)
  921                 {
  922                     if (has_z_suffix)
  923                     {
  924                         /* Ignore this scenario in recursive mode.
  925                          * See comment above in the decompress path.
  926                          */
  927                         if (!recursive)
  928                             fprintf(stderr, "%s: already has .Z suffix -- no change\n", tempname);
  929                         free(tempname);
  930                         return;
  931                     }
  932 
  933                     if (infstat.st_nlink > 1 && (!force))
  934                     {
  935                         fprintf(stderr, "%s has %jd other links: unchanged\n",
  936                                         tempname, (intmax_t)(infstat.st_nlink - 1));
  937                         goto error;
  938                     }
  939                 }
  940 
  941                 ofname = malloc(namesize + 3);
  942                 if (ofname == NULL)
  943                 {
  944                     perror("malloc");
  945                     goto error;
  946                 }
  947                 memcpy(ofname, tempname, namesize);
  948                 strcpy(&ofname[namesize], ".Z");
  949             }
  950 
  951             if ((fdin = open(ifname = tempname, O_RDONLY|O_BINARY)) == -1)
  952             {
  953                 perror(tempname);
  954                 goto error;
  955             }
  956 
  957             if (zcat_flg == 0)
  958             {
  959                 if (access(ofname, F_OK) == 0)
  960                 {
  961                     if (!force)
  962                     {
  963                         inbuf[0] = 'n';
  964 
  965                         fprintf(stderr, "%s already exists.\n", ofname);
  966 
  967                         if (fgnd_flag && isatty(0))
  968                         {
  969                             fprintf(stderr, "Do you wish to overwrite %s (y or n)? ", ofname);
  970                             fflush(stderr);
  971     
  972                             if (read(0, inbuf, 1) > 0)
  973                             {
  974                                 if (inbuf[0] != '\n')
  975                                 {
  976                                     do
  977                                     {
  978                                         if (read(0, inbuf+1, 1) <= 0)
  979                                         {
  980                                             perror("stdin");
  981                                             break;
  982                                         }
  983                                     }
  984                                     while (inbuf[1] != '\n');
  985                                 }
  986                             }
  987                             else
  988                                 perror("stdin");
  989                         }
  990 
  991                         if (inbuf[0] != 'y')
  992                         {
  993                             fprintf(stderr, "%s not overwritten\n", ofname);
  994                             goto error;
  995                         }
  996                     }
  997 
  998                     if (unlink(ofname))
  999                     {
 1000                         fprintf(stderr, "Can't remove old output file\n");
 1001                         perror(ofname);
 1002                         goto error;
 1003                     }
 1004                 }
 1005 
 1006                 if ((fdout = open(ofname, O_WRONLY|O_CREAT|O_EXCL|O_BINARY,0600)) == -1)
 1007                 {
 1008                     perror(tempname);
 1009                     goto error;
 1010                 }
 1011 
 1012                 if(!quiet)
 1013                     fprintf(stderr, "%s: ", tempname);
 1014 
 1015                 remove_ofname = 1;
 1016             }
 1017             else
 1018             {
 1019                 fdout = 1;
 1020                 setmode(fdout, O_BINARY);
 1021                 remove_ofname = 0;
 1022             }
 1023 
 1024             if (do_decomp == 0)
 1025                 compress(fdin, fdout);
 1026             else
 1027                 decompress(fdin, fdout);
 1028 
 1029             close(fdin);
 1030 
 1031             if (fdout != 1 && close(fdout))
 1032                 write_error();
 1033 
 1034             if ( (bytes_in == 0) && (force == 0 ) )
 1035             {
 1036                 if (remove_ofname)
 1037                 {
 1038                     if(!quiet)
 1039                         fprintf(stderr, "No compression -- %s unchanged\n", ifname);
 1040                     if (unlink(ofname)) /* Remove input file */
 1041                     {
 1042                         fprintf(stderr, "\nunlink error (ignored) ");
 1043                         perror(ofname);
 1044                     }
 1045         
 1046                     remove_ofname = 0;
 1047                     exit_code = 2;
 1048                 }
 1049             }
 1050             else
 1051             if (zcat_flg == 0)
 1052             {
 1053                 struct utimbuf  timep;
 1054 
 1055                 if (!do_decomp && bytes_out >= bytes_in && (!force))
 1056                 {/* No compression: remove file.Z */
 1057                     if(!quiet)
 1058                         fprintf(stderr, "No compression -- %s unchanged\n", ifname);
 1059 
 1060                     if (unlink(ofname))
 1061                     {
 1062                         fprintf(stderr, "unlink error (ignored) ");
 1063                         perror(ofname);
 1064                     }
 1065 
 1066                     remove_ofname = 0;
 1067                     exit_code = 2;
 1068                 }
 1069                 else
 1070                 {/* ***** Successful Compression ***** */
 1071                     if(!quiet)
 1072                     {
 1073                         fprintf(stderr, " -- replaced with %s",ofname);
 1074 
 1075                         if (!do_decomp)
 1076                         {
 1077                             fprintf(stderr, " Compression: ");
 1078                             prratio(stderr, bytes_in-bytes_out, bytes_in);
 1079                         }
 1080 
 1081                         fprintf(stderr, "\n");
 1082                     }
 1083 
 1084                     timep.actime = infstat.st_atime;
 1085                     timep.modtime = infstat.st_mtime;
 1086 
 1087                     if (utime(ofname, &timep))
 1088                     {
 1089                         fprintf(stderr, "\nutime error (ignored) ");
 1090                         perror(ofname);
 1091                     }
 1092 
 1093                     if (chmod(ofname, infstat.st_mode & 07777))     /* Copy modes */
 1094                     {
 1095                         fprintf(stderr, "\nchmod error (ignored) ");
 1096                         perror(ofname);
 1097                     }
 1098 
 1099                     if (chown(ofname, infstat.st_uid, infstat.st_gid))  /* Copy ownership */
 1100                     {
 1101                         fprintf(stderr, "\nchown error (ignored) ");
 1102                         perror(ofname);
 1103                     }
 1104 
 1105                     remove_ofname = 0;
 1106 
 1107                     if (!keep && unlink(ifname))    /* Remove input file */
 1108                     {
 1109                         fprintf(stderr, "\nunlink error (ignored) ");
 1110                         perror(ifname);
 1111                     }
 1112                 }
 1113             }
 1114 
 1115             if (exit_code == -1)
 1116                 exit_code = 0;
 1117 
 1118             break;
 1119 
 1120         default:
 1121             fprintf(stderr,"%s is not a directory or a regular file - ignored\n",
 1122                     tempname);
 1123             break;
 1124         }
 1125 
 1126         free(tempname);
 1127         if (!remove_ofname)
 1128         {
 1129             free(ofname);
 1130             ofname = NULL;
 1131         }
 1132         return;
 1133 
 1134 error:
 1135         free(ofname);
 1136         ofname = NULL;
 1137         free(tempname);
 1138         exit_code = 1;
 1139         if (fdin != -1)
 1140             close(fdin);
 1141         if (fdout != -1)
 1142             close(fdout);
 1143     }
 1144 
 1145 #ifdef  RECURSIVE
 1146 void
 1147 compdir(dir)
 1148     char    *dir;
 1149     {
 1150         struct dirent *dp;
 1151         DIR *dirp;
 1152         char                    *nptr;
 1153         char                    *fptr;
 1154         unsigned long            dir_size = strlen(dir);
 1155         /* The +256 is a lazy optimization. We'll resize on demand. */
 1156         unsigned long            size = dir_size + 256;
 1157 
 1158         nptr = malloc(size);
 1159         if (nptr == NULL)
 1160         {
 1161             perror("malloc");
 1162             exit_code = 1;
 1163             return;
 1164         }
 1165         memcpy(nptr, dir, dir_size);
 1166         nptr[dir_size] = '/';
 1167         fptr = &nptr[dir_size + 1];
 1168 
 1169         dirp = opendir(dir);
 1170 
 1171         if (dirp == NULL)
 1172         {
 1173             free(nptr);
 1174             printf("%s unreadable\n", dir);     /* not stderr! */
 1175             return ;
 1176         }
 1177 
 1178         while ((dp = readdir(dirp)) != NULL)
 1179         {
 1180             if (dp->d_ino == 0)
 1181                 continue;
 1182 
 1183             if (strcmp(dp->d_name,".") == 0 || strcmp(dp->d_name,"..") == 0)
 1184                 continue;
 1185 
 1186             if (size < dir_size + strlen(dp->d_name) + 2)
 1187             {
 1188                 size = dir_size + strlen(dp->d_name) + 2;
 1189                 nptr = realloc(nptr, size);
 1190                 if (nptr == NULL)
 1191                 {
 1192                     perror("realloc");
 1193                     exit_code = 1;
 1194                     break;
 1195                 }
 1196                 fptr = &nptr[dir_size + 1];
 1197             }
 1198 
 1199             strcpy(fptr, dp->d_name);
 1200             comprexx(nptr);
 1201         }
 1202 
 1203         closedir(dirp);
 1204 
 1205         free(nptr);
 1206     }
 1207 #endif
 1208 /*
 1209  * compress fdin to fdout
 1210  *
 1211  * Algorithm:  use open addressing double hashing (no chaining) on the 
 1212  * prefix code / next character combination.  We do a variant of Knuth's
 1213  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
 1214  * secondary probe.  Here, the modular division first probe is gives way
 1215  * to a faster exclusive-or manipulation.  Also do block compression with
 1216  * an adaptive reset, whereby the code table is cleared when the compression
 1217  * ratio decreases, but after the table fills.  The variable-length output
 1218  * codes are re-sized at this point, and a special CLEAR code is generated
 1219  * for the decompressor.  Late addition:  construct the table according to
 1220  * file size for noticeable speed improvement on small files.  Please direct
 1221  * questions about this implementation to ames!jaw.
 1222  */
 1223 void
 1224 compress(fdin, fdout)
 1225     int     fdin;
 1226     int     fdout;
 1227     {
 1228         long hp;
 1229         int rpos;
 1230         long fc;
 1231         int outbits;
 1232         int rlop;
 1233         int rsize;
 1234         int stcode;
 1235         code_int free_ent;
 1236         int boff;
 1237         int n_bits;
 1238         int ratio;
 1239         long checkpoint;
 1240         code_int extcode;
 1241         union
 1242         {
 1243             long            code;
 1244             struct
 1245             {
 1246                 char_type       c;
 1247                 unsigned short  ent;
 1248             } e;
 1249         } fcode;
 1250 
 1251         ratio = 0;
 1252         checkpoint = CHECK_GAP;
 1253         extcode = MAXCODE(n_bits = INIT_BITS)+1;
 1254         stcode = 1;
 1255         free_ent = FIRST;
 1256 
 1257         memset(outbuf, 0, sizeof(outbuf));
 1258         bytes_out = 0; bytes_in = 0;
 1259         outbuf[0] = MAGIC_1;
 1260         outbuf[1] = MAGIC_2;
 1261         outbuf[2] = (char)(maxbits | BLOCK_MODE);
 1262         boff = outbits = (3<<3);
 1263         fcode.code = 0;
 1264 
 1265         clear_htab();
 1266 
 1267         while ((rsize = read(fdin, inbuf, IBUFSIZ)) > 0)
 1268         {
 1269             if (bytes_in == 0)
 1270             {
 1271                 fcode.e.ent = inbuf[0];
 1272                 rpos = 1;
 1273             }
 1274             else
 1275                 rpos = 0;
 1276 
 1277             rlop = 0;
 1278 
 1279             do
 1280             {
 1281                 if (free_ent >= extcode && fcode.e.ent < FIRST)
 1282                 {
 1283                     if (n_bits < maxbits)
 1284                     {
 1285                         boff = outbits = (outbits-1)+((n_bits<<3)-
 1286                                     ((outbits-boff-1+(n_bits<<3))%(n_bits<<3)));
 1287                         if (++n_bits < maxbits)
 1288                             extcode = MAXCODE(n_bits)+1;
 1289                         else
 1290                             extcode = MAXCODE(n_bits);
 1291                     }
 1292                     else
 1293                     {
 1294                         extcode = MAXCODE(16)+OBUFSIZ;
 1295                         stcode = 0;
 1296                     }
 1297                 }
 1298 
 1299                 if (!stcode && bytes_in >= checkpoint && fcode.e.ent < FIRST)
 1300                 {
 1301                     long int rat;
 1302 
 1303                     checkpoint = bytes_in + CHECK_GAP;
 1304 
 1305                     if (bytes_in > 0x007fffff)
 1306                     {                           /* shift will overflow */
 1307                         rat = (bytes_out+(outbits>>3)) >> 8;
 1308 
 1309                         if (rat == 0)               /* Don't divide by zero */
 1310                             rat = 0x7fffffff;
 1311                         else
 1312                             rat = bytes_in / rat;
 1313                     }
 1314                     else
 1315                         rat = (bytes_in << 8) / (bytes_out+(outbits>>3));   /* 8 fractional bits */
 1316                     if (rat >= ratio)
 1317                         ratio = (int)rat;
 1318                     else
 1319                     {
 1320                         ratio = 0;
 1321                         clear_htab();
 1322                         output(outbuf,outbits,CLEAR,n_bits);
 1323                         boff = outbits = (outbits-1)+((n_bits<<3)-
 1324                                     ((outbits-boff-1+(n_bits<<3))%(n_bits<<3)));
 1325                         extcode = MAXCODE(n_bits = INIT_BITS)+1;
 1326                         free_ent = FIRST;
 1327                         stcode = 1;
 1328                     }
 1329                 }
 1330 
 1331                 if (outbits >= (OBUFSIZ<<3))
 1332                 {
 1333                     if (write(fdout, outbuf, OBUFSIZ) != OBUFSIZ)
 1334                         write_error();
 1335 
 1336                     outbits -= (OBUFSIZ<<3);
 1337                     boff = -(((OBUFSIZ<<3)-boff)%(n_bits<<3));
 1338                     bytes_out += OBUFSIZ;
 1339 
 1340                     memcpy(outbuf, outbuf+OBUFSIZ, (outbits>>3)+1);
 1341                     memset(outbuf+(outbits>>3)+1, '\0', OBUFSIZ);
 1342                 }
 1343 
 1344                 {
 1345                     int i;
 1346 
 1347                     i = rsize-rlop;
 1348 
 1349                     if ((code_int)i > extcode-free_ent) i = (int)(extcode-free_ent);
 1350                     if (i > ((sizeof(outbuf) - 32)*8 - outbits)/n_bits)
 1351                         i = ((sizeof(outbuf) - 32)*8 - outbits)/n_bits;
 1352                     
 1353                     if (!stcode && (long)i > checkpoint-bytes_in)
 1354                         i = (int)(checkpoint-bytes_in);
 1355 
 1356                     rlop += i;
 1357                     bytes_in += i;
 1358                 }
 1359 
 1360                 goto next;
 1361 hfound:         fcode.e.ent = codetabof(hp);
 1362 next:           if (rpos >= rlop)
 1363                     goto endlop;
 1364 next2:          fcode.e.c = inbuf[rpos++];
 1365 #ifndef FAST
 1366                 {
 1367                     code_int i;
 1368                     fc = fcode.code;
 1369                     hp = (((long)(fcode.e.c)) << (BITS-8)) ^ (long)(fcode.e.ent);
 1370 
 1371                     if ((i = htabof(hp)) == fc)
 1372                         goto hfound;
 1373 
 1374                     if (i != -1)
 1375                     {
 1376                         long disp;
 1377 
 1378                         disp = (HSIZE - hp)-1;  /* secondary hash (after G. Knott) */
 1379 
 1380                         do
 1381                         {
 1382                             if ((hp -= disp) < 0)   hp += HSIZE;
 1383 
 1384                             if ((i = htabof(hp)) == fc)
 1385                                 goto hfound;
 1386                         }
 1387                         while (i != -1);
 1388                     }
 1389                 }
 1390 #else
 1391                 {
 1392                     long i;
 1393                     long p;
 1394                     fc = fcode.code;
 1395                     hp = ((((long)(fcode.e.c)) << (HBITS-8)) ^ (long)(fcode.e.ent));
 1396 
 1397                     if ((i = htabof(hp)) == fc) goto hfound;
 1398                     if (i == -1)                goto out;
 1399 
 1400                     p = primetab[fcode.e.c];
 1401 lookup:             hp = (hp+p)&HMASK;
 1402                     if ((i = htabof(hp)) == fc) goto hfound;
 1403                     if (i == -1)                goto out;
 1404                     hp = (hp+p)&HMASK;
 1405                     if ((i = htabof(hp)) == fc) goto hfound;
 1406                     if (i == -1)                goto out;
 1407                     hp = (hp+p)&HMASK;
 1408                     if ((i = htabof(hp)) == fc) goto hfound;
 1409                     if (i == -1)                goto out;
 1410                     goto lookup;
 1411                 }
 1412 out:            ;
 1413 #endif
 1414                 output(outbuf,outbits,fcode.e.ent,n_bits);
 1415 
 1416                 {
 1417                     long fc = fcode.code;
 1418                     fcode.e.ent = fcode.e.c;
 1419 
 1420                     if (stcode)
 1421                     {
 1422                         codetabof(hp) = (unsigned short)free_ent++;
 1423                         htabof(hp) = fc;
 1424                     }
 1425                 } 
 1426 
 1427                 goto next;
 1428 
 1429 endlop:         if (fcode.e.ent >= FIRST && rpos < rsize)
 1430                     goto next2;
 1431 
 1432                 if (rpos > rlop)
 1433                 {
 1434                     bytes_in += rpos-rlop;
 1435                     rlop = rpos;
 1436                 }
 1437             }
 1438             while (rlop < rsize);
 1439         }
 1440 
 1441         if (rsize < 0)
 1442             read_error();
 1443 
 1444         if (bytes_in > 0)
 1445             output(outbuf,outbits,fcode.e.ent,n_bits);
 1446 
 1447         if (write(fdout, outbuf, (outbits+7)>>3) != (outbits+7)>>3)
 1448             write_error();
 1449 
 1450         bytes_out += (outbits+7)>>3;
 1451 
 1452         return;
 1453     }
 1454 
 1455 /*
 1456  * Decompress stdin to stdout.  This routine adapts to the codes in the
 1457  * file building the "string" table on-the-fly; requiring no table to
 1458  * be stored in the compressed file.  The tables used herein are shared
 1459  * with those of the compress() routine.  See the definitions above.
 1460  */
 1461 
 1462 void
 1463 decompress(fdin, fdout)
 1464     int     fdin;
 1465     int     fdout;
 1466     {
 1467         char_type *stackp;
 1468         code_int code;
 1469         int finchar;
 1470         code_int oldcode;
 1471         code_int incode;
 1472         int inbits;
 1473         int posbits;
 1474         int outpos;
 1475         int insize;
 1476         int bitmask;
 1477         code_int free_ent;
 1478         code_int maxcode;
 1479         code_int maxmaxcode;
 1480         int n_bits;
 1481         int rsize;
 1482         int block_mode;
 1483 
 1484         bytes_in = 0;
 1485         bytes_out = 0;
 1486         insize = 0;
 1487 
 1488         while (insize < 3 && (rsize = read(fdin, inbuf+insize, IBUFSIZ)) > 0)
 1489             insize += rsize;
 1490 
 1491         if (insize < 3 || inbuf[0] != MAGIC_1 || inbuf[1] != MAGIC_2)
 1492         {
 1493             if (rsize < 0)
 1494                 read_error();
 1495 
 1496             if (insize > 0)
 1497             {
 1498                 fprintf(stderr, "%s: not in compressed format\n",
 1499                                     (ifname[0] != '\0'? ifname : "stdin"));
 1500                 exit_code = 1;
 1501             }
 1502 
 1503             return ;
 1504         }
 1505 
 1506         maxbits = inbuf[2] & BIT_MASK;
 1507         block_mode = inbuf[2] & BLOCK_MODE;
 1508 
 1509         if (maxbits > BITS)
 1510         {
 1511             fprintf(stderr,
 1512                     "%s: compressed with %d bits, can only handle %d bits\n",
 1513                     (*ifname != '\0' ? ifname : "stdin"), maxbits, BITS);
 1514             exit_code = 4;
 1515             return;
 1516         }
 1517 
 1518         maxmaxcode = MAXCODE(maxbits);
 1519 
 1520         bytes_in = insize;
 1521         maxcode = MAXCODE(n_bits = INIT_BITS)-1;
 1522         bitmask = (1<<n_bits)-1;
 1523         oldcode = -1;
 1524         finchar = 0;
 1525         outpos = 0;
 1526         posbits = 3<<3;
 1527 
 1528         free_ent = ((block_mode) ? FIRST : 256);
 1529 
 1530         clear_tab_prefixof();   /* As above, initialize the first
 1531                                    256 entries in the table. */
 1532 
 1533         for (code = 255 ; code >= 0 ; --code)
 1534             tab_suffixof(code) = (char_type)code;
 1535 
 1536         do
 1537         {
 1538 resetbuf:   ;
 1539             {
 1540                 int i;
 1541                 int e;
 1542                 int o;
 1543 
 1544                 o = posbits >> 3;
 1545                 e = o <= insize ? insize - o : 0;
 1546 
 1547                 for (i = 0 ; i < e ; ++i)
 1548                     inbuf[i] = inbuf[i+o];
 1549 
 1550                 insize = e;
 1551                 posbits = 0;
 1552             }
 1553 
 1554             if (insize < sizeof(inbuf)-IBUFSIZ)
 1555             {
 1556                 if ((rsize = read(fdin, inbuf+insize, IBUFSIZ)) < 0)
 1557                     read_error();
 1558 
 1559                 insize += rsize;
 1560             }
 1561 
 1562             inbits = ((rsize > 0) ? (insize - insize%n_bits)<<3 : 
 1563                                     (insize<<3)-(n_bits-1));
 1564 
 1565             while (inbits > posbits)
 1566             {
 1567                 if (free_ent > maxcode)
 1568                 {
 1569                     posbits = ((posbits-1) + ((n_bits<<3) -
 1570                                      (posbits-1+(n_bits<<3))%(n_bits<<3)));
 1571 
 1572                     ++n_bits;
 1573                     if (n_bits == maxbits)
 1574                         maxcode = maxmaxcode;
 1575                     else
 1576                         maxcode = MAXCODE(n_bits)-1;
 1577 
 1578                     bitmask = (1<<n_bits)-1;
 1579                     goto resetbuf;
 1580                 }
 1581 
 1582                 input(inbuf,posbits,code,n_bits,bitmask);
 1583 
 1584                 if (oldcode == -1)
 1585                 {
 1586                     if (code >= 256) {
 1587                         fprintf(stderr, "oldcode:-1 code:%i\n", (int)(code));
 1588                         fprintf(stderr, "uncompress: corrupt input\n");
 1589                         abort_compress();
 1590                     }
 1591                     outbuf[outpos++] = (char_type)(finchar = (int)(oldcode = code));
 1592                     continue;
 1593                 }
 1594 
 1595                 if (code == CLEAR && block_mode)
 1596                 {
 1597                     clear_tab_prefixof();
 1598                     free_ent = FIRST - 1;
 1599                     posbits = ((posbits-1) + ((n_bits<<3) -
 1600                                 (posbits-1+(n_bits<<3))%(n_bits<<3)));
 1601                     maxcode = MAXCODE(n_bits = INIT_BITS)-1;
 1602                     bitmask = (1<<n_bits)-1;
 1603                     goto resetbuf;
 1604                 }
 1605 
 1606                 incode = code;
 1607                 stackp = de_stack;
 1608 
 1609                 if (code >= free_ent)   /* Special case for KwKwK string.   */
 1610                 {
 1611                     if (code > free_ent)
 1612                     {
 1613                         char_type *p;
 1614 
 1615                         posbits -= n_bits;
 1616                         p = &inbuf[posbits>>3];
 1617 
 1618                         fprintf(stderr, "insize:%d posbits:%d inbuf:%02X %02X %02X %02X %02X (%d)\n", insize, posbits,
 1619                                 p[-1],p[0],p[1],p[2],p[3], (posbits&07));
 1620                         fprintf(stderr, "uncompress: corrupt input\n");
 1621                         abort_compress();
 1622                     }
 1623 
 1624                     *--stackp = (char_type)finchar;
 1625                     code = oldcode;
 1626                 }
 1627 
 1628                 while ((cmp_code_int)code >= (cmp_code_int)256)
 1629                 { /* Generate output characters in reverse order */
 1630                     *--stackp = tab_suffixof(code);
 1631                     code = tab_prefixof(code);
 1632                 }
 1633 
 1634                 *--stackp = (char_type)(finchar = tab_suffixof(code));
 1635 
 1636             /* And put them out in forward order */
 1637 
 1638                 {
 1639                     int i;
 1640 
 1641                     if (outpos+(i = (de_stack-stackp)) >= OBUFSIZ)
 1642                     {
 1643                         do
 1644                         {
 1645                             if (i > OBUFSIZ-outpos) i = OBUFSIZ-outpos;
 1646 
 1647                             if (i > 0)
 1648                             {
 1649                                 memcpy(outbuf+outpos, stackp, i);
 1650                                 outpos += i;
 1651                             }
 1652 
 1653                             if (outpos >= OBUFSIZ)
 1654                             {
 1655                                 if (write(fdout, outbuf, outpos) != outpos)
 1656                                     write_error();
 1657 
 1658                                 outpos = 0;
 1659                             }
 1660                             stackp+= i;
 1661                         }
 1662                         while ((i = (de_stack-stackp)) > 0);
 1663                     }
 1664                     else
 1665                     {
 1666                         memcpy(outbuf+outpos, stackp, i);
 1667                         outpos += i;
 1668                     }
 1669                 }
 1670 
 1671                 if ((code = free_ent) < maxmaxcode) /* Generate the new entry. */
 1672                 {
 1673                     tab_prefixof(code) = (unsigned short)oldcode;
 1674                     tab_suffixof(code) = (char_type)finchar;
 1675                     free_ent = code+1;
 1676                 } 
 1677 
 1678                 oldcode = incode;   /* Remember previous code.  */
 1679             }
 1680 
 1681             bytes_in += rsize;
 1682         }
 1683         while (rsize > 0);
 1684 
 1685         if (outpos > 0 && write(fdout, outbuf, outpos) != outpos)
 1686             write_error();
 1687     }
 1688 
 1689 void
 1690 read_error()
 1691     {
 1692         fprintf(stderr, "\nread error on");
 1693         perror((ifname[0] != '\0') ? ifname : "stdin");
 1694         abort_compress();
 1695     }
 1696 
 1697 void
 1698 write_error()
 1699     {
 1700         fprintf(stderr, "\nwrite error on");
 1701         perror(ofname ? ofname : "stdout");
 1702         abort_compress();
 1703     }
 1704 
 1705 void
 1706 abort_compress()
 1707     {
 1708         if (remove_ofname)
 1709             unlink(ofname);
 1710 
 1711         exit(1);
 1712     }
 1713 
 1714 void
 1715 prratio(stream, num, den)
 1716     FILE        *stream;
 1717     long int     num;
 1718     long int     den;
 1719     {
 1720         int q;          /* Doesn't need to be long */
 1721 
 1722         if (den > 0)
 1723         {
 1724             if (num > 214748L) 
 1725                 q = (int)(num/(den/10000L));    /* 2147483647/10000 */
 1726             else
 1727                 q = (int)(10000L*num/den);      /* Long calculations, though */
 1728         }
 1729         else
 1730             q = 10000;
 1731 
 1732         if (q < 0)
 1733         {
 1734             putc('-', stream);
 1735             q = -q;
 1736         }
 1737 
 1738         fprintf(stream, "%d.%02d%%", q / 100, q % 100);
 1739     }
 1740 
 1741 void
 1742 about()
 1743     {
 1744         printf("Compress version: %s\n", version_id);
 1745         printf("Compile options:\n        ");
 1746 #ifdef FAST
 1747         printf("FAST, ");
 1748 #endif
 1749 #ifdef SIGNED_COMPARE_SLOW
 1750         printf("SIGNED_COMPARE_SLOW, ");
 1751 #endif
 1752 #ifdef MAXSEG_64K
 1753         printf("MAXSEG_64K, ");
 1754 #endif
 1755 #ifdef DOS
 1756         printf("DOS, ");
 1757 #endif
 1758 #ifdef DEBUG
 1759         printf("DEBUG, ");
 1760 #endif
 1761 #ifdef LSTAT
 1762         printf("LSTAT, ");
 1763 #endif
 1764         printf("\n        IBUFSIZ=%d, OBUFSIZ=%d, BITS=%d\n",
 1765             IBUFSIZ, OBUFSIZ, BITS);
 1766 
 1767         printf("\n\
 1768 Author version 5.x (Modernization):\n\
 1769 Author version 4.2.4.x (Maintenance):\n\
 1770      Mike Frysinger  (vapier@gmail.com)\n\
 1771 \n\
 1772 Author version 4.2 (Speed improvement & source cleanup):\n\
 1773      Peter Jannesen  (peter@ncs.nl)\n\
 1774 \n\
 1775 Author version 4.1 (Added recursive directory compress):\n\
 1776      Dave Mack  (csu@alembic.acs.com)\n\
 1777 \n\
 1778 Authors version 4.0 (World release in 1985):\n\
 1779      Spencer W. Thomas, Jim McKie, Steve Davies,\n\
 1780      Ken Turkowski, James A. Woods, Joe Orost\n");
 1781 
 1782         exit(0);
 1783     }