home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / archiver / ncmp424s / compress.c < prev    next >
C/C++ Source or Header  |  1993-07-08  |  49KB  |  1,946 lines

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