home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / compre.zip / compress.c next >
C/C++ Source or Header  |  1991-02-12  |  38KB  |  1,349 lines

  1. /*
  2.  * Compress - data compression program
  3.  */
  4. static char rcs_ident[] =
  5.  "@(#) compress, v 4.2 (DOS, OS/2) 91/02/12 23:49:00 doug/kur Release $";
  6.  
  7. /*
  8.  * compress.c - File compression ala IEEE Computer, June 1984.
  9.  *
  10.  * Authors: Spencer W. Thomas    (decvax!harpo!utah-cs!utah-gr!thomas)
  11.  *          Jim McKie            (decvax!mcvax!jim)
  12.  *          Steve Davies         (decvax!vax135!petsd!peora!srd)
  13.  *          Ken Turkowski        (decvax!decwrl!turtlevax!ken)
  14.  *          James A. Woods       (decvax!ihnp4!ames!jaw)
  15.  *          Joe Orost            (decvax!vax135!petsd!joe)
  16.  *          Doug Graham          (uunet!mitel!sce!tsmith!graham)
  17.  *          Kai Uwe Rommel       (rommel@lan.informatik.tu-muenchen.dbp.de)
  18.  *
  19.  * Revision 4.2 (DOS, OS/2) 89/11/10 02:43:00 kur
  20.  * Ported to OS/2. Only the memory allocation and some usage().. stuff
  21.  * was changed, -k (keep) option added.
  22.  * Under OS/2 and if a family mode application is to build, the huge segment
  23.  * allocation functions of the DOS layer have to be used carefully instead
  24.  * of the MS C library routines for big segments.
  25.  * The system calls DosAllocHuge() and DosGetHugeShift() are used.
  26.  *
  27.  * Revision 4.1 (DOS) 89/11/10 02:43:00 doug
  28.  * Ported to MSDOS. Still works elsewhere, but maybe not as quickly.
  29.  * Removed as much long arithmetic as possible for speed on 16 bit machines.
  30.  * Use unsigned short's instead. Changed secondary hashing function to limit
  31.  * hash table size to 64K. This means table indexes can be 16 bit shorts.
  32.  * This compress will not generate codes from MAXMAXCODE (0xf000) thru
  33.  * 0xffff. Doesn't appear to hurt compression much. Removed speed hacks for
  34.  * other machines so I could understand the code. Added some for the i8088.
  35.  * Send CLEAR immediately when hash table fills instead of waiting for the
  36.  * compression ratio to drop. This is faster, and in some cases improves
  37.  * compression (but more often reduces it slightly). Junked the variable
  38.  * size hash table stuff because I am depending on 16 bit unsigned integer
  39.  * wrap around for indexing into hash table, so the table must have 2^16
  40.  * entries. Took out the XENIX_16 stuff. The DOS way ought to work on Xenix
  41.  * as well, and should be faster, but I don't have access to Xenix in order
  42.  * to find out. Added some extra error checking on decompression to try to
  43.  * avoid blowing the machine out of the water when decompressing a corrupt
  44.  * file. Add "okunlink" to avoid the problem of losing the output file as
  45.  * well as the input file if ^C is hit at the wrong time. Lot's of other
  46.  * cosmetic changes.
  47.  *
  48.  * Revision 4.0  85/07/30  12:50:00  joe
  49.  * Removed ferror() calls in output routine on every output except first.
  50.  * Prepared for release to the world.
  51.  *
  52.  * Revision 3.6  85/07/04  01:22:21  joe
  53.  * Remove much wasted storage by overlaying hash table with the tables
  54.  * used by decompress: tab_suffix[1<<BITS], stack[8000].  Updated USERMEM
  55.  * computations.  Fixed dump_tab() DEBUG routine.
  56.  *
  57.  * Revision 3.5  85/06/30  20:47:21  jaw
  58.  * Change hash function to use exclusive-or.  Rip out hash cache.  These
  59.  * speedups render the megamemory version defunct, for now.  Make decoder
  60.  * stack global.  Parts of the RCS trunks 2.7, 2.6, and 2.1 no longer apply.
  61.  *
  62.  * Revision 3.4  85/06/27  12:00:00  ken
  63.  * Get rid of all floating-point calculations by doing all compression ratio
  64.  * calculations in fixed point.
  65.  *
  66.  * Revision 3.3  85/06/24  21:53:24  joe
  67.  * Incorporate portability suggestion for M_XENIX.  Got rid of text on #else
  68.  * and #endif lines.  Cleaned up #ifdefs for vax and interdata.
  69.  *
  70.  * Revision 3.2  85/06/06  21:53:24  jaw
  71.  * Incorporate portability suggestions for Z8000, IBM PC/XT from mailing list.
  72.  * Default to "quiet" output (no compression statistics).
  73.  *
  74.  * Revision 3.1  85/05/12  18:56:13  jaw
  75.  * Integrate decompress() stack speedups (from early pointer mods by McKie).
  76.  * Repair multi-file USERMEM gaffe.  Unify 'force' flags to mimic semantics
  77.  * of SVR2 'pack'.  Streamline block-compress table clear logic.  Increase
  78.  * output byte count by magic number size.
  79.  *
  80.  * Revision 3.0   84/11/27  11:50:00  petsd!joe
  81.  * Set HSIZE depending on BITS.  Set BITS depending on USERMEM.  Unrolled
  82.  * loops in clear routines.  Added "-C" flag for 2.0 compatibility.  Used
  83.  * unsigned compares on Perkin-Elmer.  Fixed foreground check.
  84.  *
  85.  * Revision 2.7   84/11/16  19:35:39  ames!jaw
  86.  * Cache common hash codes based on input statistics; this improves
  87.  * performance for low-density raster images.  Pass on #ifdef bundle
  88.  * from Turkowski.
  89.  *
  90.  * Revision 2.6   84/11/05  19:18:21  ames!jaw
  91.  * Vary size of hash tables to reduce time for small files.
  92.  * Tune PDP-11 hash function.
  93.  *
  94.  * Revision 2.5   84/10/30  20:15:14  ames!jaw
  95.  * Junk chaining; replace with the simpler (and, on the VAX, faster)
  96.  * double hashing, discussed within.  Make block compression standard.
  97.  *
  98.  * Revision 2.4   84/10/16  11:11:11  ames!jaw
  99.  * Introduce adaptive reset for block compression, to boost the rate
  100.  * another several percent.  (See mailing list notes.)
  101.  *
  102.  * Revision 2.3   84/09/22  22:00:00  petsd!joe
  103.  * Implemented "-B" block compress.  Implemented REVERSE sorting of tab_next.
  104.  * Bug fix for last bits.  Changed fwrite to putchar loop everywhere.
  105.  *
  106.  * Revision 2.2   84/09/18  14:12:21  ames!jaw
  107.  * Fold in news changes, small machine typedef from thomas,
  108.  * #ifdef interdata from joe.
  109.  *
  110.  * Revision 2.1   84/09/10  12:34:56  ames!jaw
  111.  * Configured fast table lookup for 32-bit machines.
  112.  * This cuts user time in half for b <= FBITS, and is useful for news batching
  113.  * from VAX to PDP sites.  Also sped up decompress() [fwrite->putc] and
  114.  * added signal catcher [plus beef in writeerr()] to delete effluvia.
  115.  *
  116.  * Revision 2.0   84/08/28  22:00:00  petsd!joe
  117.  * Add check for foreground before prompting user.  Insert maxbits into
  118.  * compressed file.  Force file being uncompressed to end with ".Z".
  119.  * Added "-c" flag and "zcat".  Prepared for release.
  120.  *
  121.  * Revision 1.10  84/08/24  18:28:00  turtlevax!ken
  122.  * Will only compress regular files (no directories), added a magic number
  123.  * header (plus an undocumented -n flag to handle old files without headers),
  124.  * added -f flag to force overwriting of possibly existing destination file,
  125.  * otherwise the user is prompted for a response.  Will tack on a .Z to a
  126.  * filename if it doesn't have one when decompressing.  Will only replace
  127.  * file if it was compressed.
  128.  *
  129.  * Revision 1.9  84/08/16  17:28:00  turtlevax!ken
  130.  * Removed scanargs(), getopt(), added .Z extension and unlimited number of
  131.  * filenames to compress.  Flags may be clustered (-Ddvb12) or separated
  132.  * (-D -d -v -b 12), or combination thereof.  Modes and other status is
  133.  * copied with copystat().  -O bug for 4.2 seems to have disappeared with
  134.  * 1.8.
  135.  *
  136.  * Revision 1.8  84/08/09  23:15:00  joe
  137.  * Made it compatible with vax version, installed jim's fixes/enhancements
  138.  *
  139.  * Revision 1.6  84/08/01  22:08:00  joe
  140.  * Sped up algorithm significantly by sorting the compress chain.
  141.  *
  142.  * Revision 1.5  84/07/13  13:11:00  srd
  143.  * Added C version of vax asm routines.  Changed structure to arrays to
  144.  * save much memory.  Do unsigned compares where possible (faster on
  145.  * Perkin-Elmer)
  146.  *
  147.  * Revision 1.4  84/07/05  03:11:11  thomas
  148.  * Clean up the code a little and lint it.  (Lint complains about all
  149.  * the regs used in the asm, but I'm not going to "fix" this.)
  150.  *
  151.  * Revision 1.3  84/07/05  02:06:54  thomas
  152.  * Minor fixes.
  153.  *
  154.  * Revision 1.2  84/07/05  00:27:27  thomas
  155.  * Add variable bit length output.
  156.  *
  157.  */
  158.  
  159. #include <stdio.h>
  160. #include <ctype.h>
  161. #include <signal.h>
  162. #include <sys/types.h>
  163. #include <sys/stat.h>
  164. #ifndef __ZTC__
  165. #include <malloc.h>
  166. #endif
  167. #ifndef BSD4_2
  168. #include <stdlib.h>
  169. #include <io.h>
  170. #endif
  171. #include <string.h>
  172. #include <fcntl.h>
  173. #ifdef MSDOS
  174. #ifdef OS2
  175. #define INCL_NOPM
  176. #define INCL_DOSMEMMGR
  177. #include <os2.h>
  178. int IsFileNameValid(char *name);
  179. #else
  180. #include <dos.h>
  181. #endif
  182. #endif
  183.  
  184. #ifdef PROTO
  185. /*
  186.  * Zortech appears to be missing this prototype, and MSC uses some
  187.  * silly structure as the second arg. Turbo C doesn't support this
  188.  * call at all.
  189.  */
  190. extern int utime(char *path, time_t times[]);
  191. #endif
  192.  
  193. #define BITS        16        /* max number of bits/code */
  194. #define INIT_BITS    9        /* initial number of bits/code */
  195.  
  196. #define MAXCODE(n_bits)        ((code_t)((1L << (n_bits)) - 1))
  197.  
  198. /*
  199.  * Magic numbers which should appear at the beginning of a compressed file.
  200.  */
  201. #define MAGIC0    0x1f
  202. #define MAGIC1    0x9d
  203.  
  204. /*
  205.  * Defines for third byte of header
  206.  */
  207. #define BIT_MASK    0x1f
  208. #define BLOCK_MASK    0x80
  209.  
  210. #if 0
  211. #define CHECK_GAP    10000        /* ratio check interval */
  212. #endif
  213.  
  214. /*
  215.  * the next two codes should not be changed lightly, as they must not
  216.  * lie within the contiguous general code space.
  217.  */
  218. #define FIRST    257        /* first free entry */
  219. #define    CLEAR    256        /* table clear output code */
  220.  
  221. #define DE_STACKLEN    8192    /* Size of decoder stack */
  222.  
  223. #define HSIZE    (1L << 16)    /* Size of the hash table. Don't change this */
  224.  
  225. typedef unsigned char    uchar;
  226. typedef unsigned long    ulong;
  227. typedef unsigned short    code_t;
  228. typedef    unsigned short    hash_t;
  229.  
  230. #ifdef PROTO
  231. #define ARGS(x)    x
  232. #else
  233. #define ARGS(x)    ()
  234. #endif
  235.  
  236. void        main ARGS((int argc, char **argv));
  237. void        Usage ARGS((void));
  238. void        version ARGS((void));
  239. void        compress ARGS((void));
  240. void        decompress ARGS((void));
  241. void        copystat ARGS((void));
  242. void        writeerr ARGS((void));
  243. void        cl_hash ARGS((void));
  244. void        putcode ARGS((code_t code));
  245. void        prratio ARGS((long num, long den));
  246. int        ofopen ARGS((char *filename));
  247. int        ifopen ARGS((char *filename));
  248. int        check_magic ARGS((void));
  249. int        need_clear ARGS((void));
  250. void            onintr ARGS((void));
  251. void            oops ARGS((void));
  252. int        taballoc ARGS((void));
  253. void        clearhash ARGS((void));
  254.  
  255. /*
  256.  * block compression parameters -- after all codes are used up,
  257.  * and compression rate changes, start over.
  258.  */
  259. int        block_compress = BLOCK_MASK;
  260.  
  261. int        maxbits = BITS;        /* user settable max # bits/code */
  262. int        magic = 1;        /* 3-byte magic number header */
  263. int        zcat_flg = 0;        /* Output on stdout */
  264. int        verbose = 0;        /* don't tell me about compression */
  265. int        force = 0;        /* Force overwrite of output file */
  266. int        do_decomp = 0;        /* Decompress rather than compress. */
  267. char        ofname[100];        /* Output file name */
  268. int        foreground;        /* Running in foreground? */
  269. int        exit_stat = 0;        /* Exit status */
  270. uchar        bitbuf[BITS+2];        /* For (dis)assembling code bytes */
  271. int        okunlink;        /* OK for sig handler to unlink output file */
  272. int             keep = 0;               /* keep input files ? */
  273. char        *ifname;
  274.  
  275. #ifdef i8088
  276.  
  277. uchar        *de_stack;
  278. uchar far    *charptr1;
  279. uchar far    *codeptrs1[2];
  280. uchar far    *codeptrs2[2];
  281.  
  282. #define de_suffixof(i)    charptr1[i]
  283. #define de_prefixof(i)    (*(code_t far *)&codeptrs1[i&1][i&~1])
  284.  
  285. #define en_hashchar(i)    charptr1[i]
  286. #define en_hashent(i)    (*(code_t far *)&codeptrs1[i&1][i&~1])
  287. #define en_hashcode(i)    (*(code_t far *)&codeptrs2[i&1][i&~1])
  288.  
  289. #ifndef MK_FP
  290. #define MK_FP(seg, ofs) \
  291.     ((void far *)(((ulong)(seg) << 16) | (unsigned)(ofs)))
  292. #endif
  293.  
  294. #define    PARA    16        /* Size of a paragraph */
  295.  
  296. /*
  297.  * Return a segment address which is the segment part of the normalized
  298.  * version of "fp" rounded upwards.
  299.  * I use this on the far pointers returned by "farmalloc". While
  300.  * they are probably already normalized, I have never seen this
  301.  * stated anywhere in the doc's.
  302.  *
  303.  * There is a lot of junk below which would be unecessary if only
  304.  * there were a reasonably compiler independent way of allocating
  305.  * a given number of PARAGRAPHS (like TC's allocmem). I can't find
  306.  * one though.
  307.  */
  308.  
  309. #define FP_SEGCEIL(fp)   (FP_SEG(fp) + (FP_OFF(fp) + PARA - 1) / PARA)
  310.  
  311. /*
  312.  * Allocate space for the tables used in {en,de}coding. These tables
  313.  * reside in the far heap. It may seem inefficient to be using far pointers
  314.  * for the base of these tables, because the offset portion will always be zero.
  315.  * We could just keep the segment address of the base, and then do something
  316.  * like:
  317.  *         *MK_FP(baseseg, offset) = blahblah;
  318.  *
  319.  * whenever we need to access the table. This SHOULD be more efficient,
  320.  * but the compilers do not appear to generate very efficient code in this
  321.  * case. Huge pointers are not used, because they are slow, and because
  322.  * Zortech does not support them.
  323.  */
  324.  
  325. #ifdef MSC
  326. #define farmalloc(n)    halloc(n, 1)
  327. #endif
  328.  
  329. int taballoc()
  330. {
  331. #ifdef OS2
  332.         ULONG size;
  333.         USHORT shift;
  334.         SEL sel;
  335.  
  336.         DosGetHugeShift(&shift);
  337. #else
  338.     char far *X;
  339. #endif
  340.  
  341.     if (do_decomp) {
  342.         if ((de_stack = malloc(DE_STACKLEN)) == 0)
  343.             return (0);
  344.     }
  345.     else {
  346. #ifdef OS2
  347.                 size = HSIZE * sizeof(code_t);
  348.  
  349.                 if ( DosAllocHuge(HIUSHORT(size), LOUSHORT(size),
  350.                                   &sel, 0, SEG_NONSHARED) )
  351.                         return (0);
  352.  
  353.                 codeptrs2[0] = MAKEP(sel, 0);
  354.                 codeptrs2[1] = MAKEP(sel + (1 << shift), 0);
  355. #else
  356.         if ((X = farmalloc((HSIZE + PARA) * sizeof(code_t))) == 0)
  357.                         return (0);
  358.  
  359.         codeptrs2[0] = MK_FP(FP_SEGCEIL(X), 0);
  360.                 codeptrs2[1] = MK_FP(FP_SEGCEIL(X) + HSIZE/PARA, 0);
  361. #endif
  362.     }
  363.  
  364. #ifdef OS2
  365.         size = HSIZE * sizeof(char);
  366.  
  367.         if ( DosAllocHuge(HIUSHORT(size), LOUSHORT(size),
  368.                           &sel, 0, SEG_NONSHARED) )
  369.                 return (0);
  370.  
  371.         charptr1 = MAKEP(sel, 0);
  372. #else
  373.     if ((X = farmalloc((HSIZE + PARA) * sizeof(char))) == 0)
  374.                 return (0);
  375.  
  376.     charptr1 = MK_FP(FP_SEGCEIL(X), 0);
  377. #endif
  378.  
  379. #ifdef OS2
  380.         size = HSIZE * sizeof(code_t);
  381.  
  382.         if ( DosAllocHuge(HIUSHORT(size), LOUSHORT(size),
  383.                           &sel, 0, SEG_NONSHARED) )
  384.                 return (0);
  385.  
  386.         codeptrs1[0] = MAKEP(sel, 0);
  387.         codeptrs1[1] = MAKEP(sel + (1 << shift), 0);
  388. #else
  389.     if ((X = farmalloc((HSIZE + PARA) * sizeof(code_t))) == 0)
  390.                 return (0);
  391.  
  392.     codeptrs1[0] = MK_FP(FP_SEGCEIL(X), 0);
  393.     codeptrs1[1] = MK_FP(FP_SEGCEIL(X) + HSIZE/PARA, 0);
  394. #endif
  395.  
  396.     return (1);
  397. }
  398.  
  399. #else
  400.  
  401. uchar    chartab1[HSIZE];
  402. code_t    codetab1[HSIZE];
  403. code_t    codetab2[HSIZE];
  404.  
  405. #define de_suffixof(i)    chartab1[i]
  406. #define de_prefixof(i)    codetab1[i]
  407. #define de_stack    (uchar *)codetab2
  408.  
  409. #define en_hashchar(i)    chartab1[i]
  410. #define en_hashent(i)    codetab1[i]
  411. #define en_hashcode(i)    codetab2[i]
  412.  
  413. #endif
  414.  
  415. void Usage()
  416. {
  417.   printf("\nUsage: COMPRESS [-dfvcVnC] [-b maxbits] [file ...]\n\n");
  418.   printf("  -V   print Version\n");
  419.   printf("  -h   print usage\n");
  420.   printf("  -v   verbose\n");
  421.   printf("  -q   quiet (default)\n");
  422.   printf("  -d   decompress\n");
  423.   printf("  -c   cat all output to stdout\n");
  424.   printf("  -k   keep input files\n");
  425.   printf("  -f   force overwrite of output files\n");
  426.   printf("  -n   no header: useful to uncompress old files\n");
  427.   printf("  -C   generate output compatible with compress 2.0.\n");
  428.   printf("  -b maxbits   maxbits. Default %d\n", BITS);
  429. }
  430.  
  431. /*****************************************************************
  432.  * TAG( main )
  433.  *
  434.  * Algorithm from "A Technique for High Performance Data Compression",
  435.  * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
  436.  *
  437.  * Usage: compress [-dfvc] [-b bits] [file ...]
  438.  * Inputs:
  439.  *    -d:        If given, decompression is done instead.
  440.  *
  441.  *      -c:         Write output on stdout, don't remove original.
  442.  *
  443.  *      -b:         Parameter limits the max number of bits/code.
  444.  *
  445.  *    -f:        Forces output file to be generated, even if one already
  446.  *            exists, and even if no space is saved by compressing.
  447.  *            If -f is not used, the user will be prompted if stdin is
  448.  *            a tty, otherwise, the output file will not be overwritten.
  449.  *
  450.  *      -v:        Write compression statistics
  451.  *
  452.  *     file ...:   Files to be compressed.  If none specified, stdin
  453.  *            is used.
  454.  * Outputs:
  455.  *    file.Z:        Compressed form of file with same mode, owner, and utimes
  456.  *     or stdout   (if stdin used as input)
  457.  *
  458.  * Assumptions:
  459.  *    When filenames are given, replaces with the compressed version
  460.  *    (.Z suffix) only if the file decreases in size.
  461.  * Algorithm:
  462.  *     Modified Lempel-Ziv method (LZW).  Basically finds common
  463.  * substrings and replaces them with a variable size code.  This is
  464.  * deterministic, and can be done on the fly.  Thus, the decompression
  465.  * procedure needs no input table, but tracks the way the table was built.
  466.  */
  467.  
  468. #ifdef __ZTC__
  469. #include <int.h>
  470. int silly_nonsense(struct INT_DATA *foo) {raise(SIGINT); return 1;}
  471. #endif
  472.  
  473. #define ARGVAL() (*++(*argv) || (--argc && *++argv))
  474.  
  475. void main(argc, argv)
  476. int argc;
  477. char **argv;
  478. {
  479.     char tempname[100], *cp;
  480.  
  481.     if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
  482.         signal(SIGINT, onintr);
  483. #ifdef __ZTC__
  484.         /*
  485.          * The "signal" call above isn't good enough for Zortech
  486.          */
  487.         int_intercept(0x23, silly_nonsense, 256);
  488. #endif
  489. #ifdef SIGSEGV
  490.         signal(SIGSEGV, oops);
  491. #endif
  492.         if (isatty(2))
  493.             foreground = 1;
  494.     }
  495.  
  496. #ifndef MSDOS
  497.     if ((cp = strrchr(argv[0], '/')) != 0)
  498.         cp++;
  499.     else
  500.         cp = argv[0];
  501. #else
  502.     for (cp = argv[0]; *cp; cp++)
  503.         if (*cp == '/' || *cp == '\\')
  504.             argv[0] = cp + 1;
  505.     cp = strlwr(argv[0]);
  506. #endif
  507.     /* Limited to 8 char filenames under DOS */
  508.     if (strncmp(cp, "uncompress", 8) == 0)
  509.         do_decomp = 1;
  510.     else if (strncmp(cp, "zcat", 4) == 0) {
  511.         do_decomp = 1;
  512.         zcat_flg = 1;
  513.     }
  514.  
  515. #ifdef BSD4_2
  516.     /* 4.2BSD dependent - take it out if not */
  517.     setlinebuf(stderr);
  518. #endif /* BSD4_2 */
  519.  
  520.     for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
  521.         while (*++(*argv)) {    /* Process all flags in this arg */
  522.             switch (**argv) {
  523.             case 'V':
  524.                                 version();
  525.                 break;
  526.             case 'v':
  527.                 verbose = 1;
  528.                 break;
  529.             case 'd':
  530.                 do_decomp = 1;
  531.                 break;
  532.             case 'f':
  533.             case 'F':
  534.                 force = 1;
  535.                 break;
  536.             case 'n':
  537.                 magic = 0;
  538.                 break;
  539.             case 'C':
  540.                 block_compress = 0;
  541.                 break;
  542.             case 'b':
  543.                 if (!ARGVAL()) {
  544.                     fprintf(stderr, "Missing maxbits\n");
  545.                     Usage();
  546.                     exit(1);
  547.                 }
  548.                 maxbits = atoi(*argv);
  549.                 goto nextarg;
  550.             case 'c':
  551.                 zcat_flg = 1;
  552.                 break;
  553.             case 'q':
  554.                 verbose = 0;
  555.                                 break;
  556.                         case 'k':
  557.                                 keep = 1;
  558.                 break;
  559.                         case 'h':
  560.                                 Usage();
  561.                 exit(1);
  562.             default:
  563.                 fprintf(stderr, "Unknown flag: '%c'; ", **argv);
  564.                 Usage();
  565.                 exit(1);
  566.             }
  567.         }
  568. nextarg:;
  569.     }
  570.  
  571. #ifdef i8088
  572.     if (! taballoc()) {
  573.         fprintf(stderr, "compress: out of memory\n");
  574.         exit(1);
  575.     }
  576. #endif
  577.     /*
  578.      * If no filename args, do standard input.
  579.      */
  580.         if (argc <= 0) {
  581.                 if ( isatty(fileno(stdin)) )
  582.                 {
  583.                   version();
  584.                   Usage();
  585.                   exit(1);
  586.                 }
  587.  
  588.         if (! ifopen((char *)0) || ! ofopen((char *)0))
  589.             exit(1);
  590.  
  591.         ifname = "stdin";
  592.  
  593.         if (do_decomp) {
  594.             if (!check_magic())
  595.                 exit(1);
  596.             decompress();
  597.         }
  598.         else {
  599.             compress();
  600.             if (verbose)
  601.                 putc('\n', stderr);
  602.         }
  603.         exit(exit_stat);
  604.     }
  605.  
  606.     while (--argc >= 0) {
  607.         char *suf;
  608.  
  609.         ifname = *argv++;
  610.         suf = strrchr(ifname, '.');
  611.  
  612.         exit_stat = 0;
  613.         okunlink = 0;
  614.  
  615.         if (do_decomp) {        /* DECOMPRESSION */
  616.             if (!suf || (strcmp(suf, ".Z") && strcmp(suf, ".z"))) {
  617.                                 strcpy(tempname, ifname);
  618.                 strcat(tempname, ".Z");
  619. #ifdef MSDOS
  620. #ifdef OS2
  621.                                 if ( !IsFileNameValid(tempname) )
  622. #endif
  623.                                 {
  624.                                   strcpy(tempname, ifname);
  625.                                   if ( suf = strrchr(tempname, '.') )
  626.                                     if ( suf > strrchr(tempname, '\\') )
  627.                                       *suf = 0;
  628.                   strcat(tempname, ".Z");
  629.                                 }
  630. #endif
  631.                 ifname = tempname;
  632.             }
  633.             if (! ifopen(ifname) || !check_magic())
  634.                 continue;
  635.             if (zcat_flg)
  636.                 ofname[0] = '\0';
  637.             else {
  638.                 strcpy(ofname, ifname);
  639.                 ofname[strlen(ifname) - 2] = '\0';
  640.             }
  641.             if (!ofopen(ofname))
  642.                 continue;
  643.             if (!zcat_flg && verbose)
  644.                 fprintf(stderr, "%s: ", ifname);
  645.             decompress();
  646.         }
  647.         else {                /* COMPRESSION */
  648.             if (suf && (!strcmp(suf, ".Z") || !strcmp(suf, ".z"))) {
  649.                 fprintf(stderr, "%s: already has .Z suffix -- no change\n",
  650.                     ifname);
  651.                 continue;
  652.             }
  653.             if (! ifopen(ifname))
  654.                 continue;
  655.             if (zcat_flg)
  656.                 ofname[0] = 0;
  657.             else {
  658.                 strcpy(ofname, ifname);
  659. #ifdef MSDOS
  660.                 strcat(ofname, ".Z");
  661.  
  662. #ifdef OS2
  663.                                 if ( !IsFileNameValid(ofname) )
  664. #endif
  665.                                 {
  666.                                   strcpy(ofname, ifname);
  667.  
  668.                                   if ( suf = strrchr(ofname, '.') )
  669.                                     if ( suf > strrchr(ofname, '\\') )
  670.                                       *suf = 0;
  671.  
  672.                     strcat(ofname, ".Z");
  673.                                 }
  674. #else       /* We'll let ofopen do the complaining */
  675. #ifndef BSD4_2
  676.                 if ((cp = strrchr(ofname, '/')) != NULL)
  677.                     cp++;
  678.                 else
  679.                     cp = ofname;
  680.                 if (strlen(cp) > 12) {
  681.                     fprintf(stderr,"%s: filename too long to tack on .Z\n",cp);
  682.                     continue;
  683.                 }
  684. #endif
  685.                 strcat(ofname, ".Z");
  686. #endif
  687.             }
  688.             if (! ofopen(ofname))
  689.                 continue;
  690.             if (! zcat_flg && verbose)
  691.                 fprintf(stderr, "%s: ", ifname);
  692.             compress();
  693.         }
  694.  
  695.         if (! zcat_flg) {
  696.             copystat();
  697.             if ((exit_stat == 1) || verbose)
  698.                 putc('\n', stderr);
  699.         }
  700.     }
  701.     exit(exit_stat);
  702. }
  703.  
  704. /*
  705.  * compress stdin to stdout
  706.  *
  707.  * Algorithm:  use open addressing double hashing (no chaining) on the
  708.  * prefix code / next character combination.  We do a variant of Knuth's
  709.  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  710.  * secondary probe.  Here, the modular division first probe is gives way
  711.  * to a faster exclusive-or manipulation.  Also do block compression with
  712.  * an adaptive reset, whereby the code table is cleared when the compression
  713.  * ratio decreases, but after the table fills.  The variable-length output
  714.  * codes are re-sized at this point, and a special CLEAR code is generated
  715.  * for the decompressor.  Late addition:  construct the table according to
  716.  * file size for noticeable speed improvement on small files.  Please direct
  717.  * questions about this implementation to ames!jaw.
  718.  *
  719.  * Secondary hash function changed slightly for DOS. Hash table used to be
  720.  * > 64K. This is slow on a 16 bit machine because it means long arithmetic,
  721.  * and more complicated addressing of tables in the far address space.
  722.  * We now restrict the table size to 64K, and, so that the table does
  723.  * not overfill, restrict the codes that we will generate to MAXMAXCODE.
  724.  * This causes slightly poorer compression in some cases, but, interestingly
  725.  * enough, also causes better compression ratios in certain other cases.
  726.  * Yes, this is all compatible with other compresses.
  727.  */
  728. static long    in_count;        /* length of input */
  729. static long    out_count;        /* length of compressed output */
  730. static long    ratio;            /* in_count/out_count * 256 */
  731. static int    n_bits;            /* number of bits/code */
  732. static int    n_bits8;        /* bits/code times 8 */
  733. static int    bitoffset;        /* Offset into bitbuf */
  734.  
  735. #define NOENT        ((code_t)0xffff)
  736. #define MAXMAXCODE    ((code_t)0xf000)
  737.  
  738. /*
  739.  * Clear out the hash table. We try to do this as quickly as possible, because
  740.  * it's running time dominates for small files. For big files, it doesn't matter
  741.  * much because it doesn't get called often. Now I understand why the original
  742.  * had a variable size hash table.
  743.  */
  744. void clearhash()
  745. {
  746. #ifdef i8088
  747.     register unsigned i;
  748.     code_t far *hp;
  749.  
  750.     hp = (code_t far *)codeptrs1[0];
  751.     i = (unsigned)(HSIZE/2);
  752.     do
  753.         *hp++ = NOENT;
  754.     while (--i > 0);
  755.  
  756.     hp = (code_t far *)codeptrs1[1];
  757.     i = (unsigned)(HSIZE/2);
  758.     do
  759.         *hp++ = NOENT;
  760.     while (--i > 0);
  761. #else
  762.     /*
  763.      * WARNING: assumes that NOENT == 0xffff
  764.      */
  765.     memset((char *)codetab1, 0xff, HSIZE*sizeof(code_t));
  766. #endif
  767. }
  768.  
  769. /*
  770.  * Compress stdin to stdout.
  771.  */
  772. void compress()
  773. {
  774.     register hash_t    i;
  775.     register code_t    ent;
  776.     hash_t        disp;
  777.     int        c;
  778.     code_t        freecode;    /* first unused entry */
  779.     code_t        maxcode;    /* maximum code, given n_bits */
  780.     code_t        maxmaxcode;
  781.     code_t        k;
  782. #ifdef CHECK_GAP
  783.     long        checkpoint = 0;
  784. #endif
  785.  
  786.     if (maxbits < INIT_BITS)
  787.         maxbits = INIT_BITS;
  788.     if (maxbits > BITS)
  789.         maxbits = BITS;
  790.  
  791.     if (magic) {
  792.         putchar(MAGIC0); putchar(MAGIC1);
  793.         putchar(maxbits | block_compress);
  794.         if (ferror(stdout))
  795.             writeerr();
  796.     }
  797.  
  798.     bitbuf[bitoffset = 0] = 0;
  799.     out_count = 3;            /* includes 3-byte header mojo */
  800.     ratio = 0;
  801.     in_count = 1;
  802.  
  803.     n_bits = INIT_BITS;
  804.     n_bits8 = INIT_BITS << 3;
  805.     maxcode = MAXCODE(INIT_BITS);
  806.     maxmaxcode = MAXCODE(maxbits);
  807.     if (maxmaxcode > MAXMAXCODE)
  808.         maxmaxcode = MAXMAXCODE;
  809.  
  810.     freecode = ((block_compress) ? FIRST : 256);
  811.  
  812.     clearhash();
  813.  
  814.     ent = getchar();
  815.  
  816.     while ((c = getchar()) != EOF) {
  817.         in_count++;
  818.  
  819.         i = (hash_t)(c << 8) ^ ent;        /* xor hashing */
  820.  
  821.         if ((k = en_hashent(i)) == ent && en_hashchar(i) == (uchar)c) {
  822.             ent = en_hashcode(i);
  823.             goto Continue;
  824.         }
  825.  
  826.         if (k != NOENT) {
  827.             /*
  828.              * New secondary hash for 64K table.
  829.              * Experiment shows that the shift by 6 works well.
  830.              * Beats me why. "disp" must be relatively
  831.              * prime to the table size. Since the table size is a
  832.              * power of 2, this means "disp" must be odd.
  833.              *
  834.              * Note that we do not do a range check before doing
  835.              * "i -= disp". It is assumed that the hash table size
  836.              * (HSIZE) is 64K, and that the type "hash_t" (which
  837.              * is unsigned short) is 16 bits. Thus it is impossible
  838.              * for "i" to be out of range. On a machine with something
  839.              * other than 16 bit shorts, this would have to change.
  840.              */
  841.             disp = ((hash_t)(c << 6) ^ ent) | 1;
  842.             do {
  843.                 i -= disp;
  844.                 if ((k = en_hashent(i)) == ent &&
  845.                     en_hashchar(i) == (uchar)c) {
  846.                     ent = en_hashcode(i);
  847.                     goto Continue;
  848.                 }
  849.             } while (k != NOENT);
  850.         }
  851.  
  852.         putcode(ent);
  853.  
  854.         if (freecode <= maxmaxcode) {
  855.             /*
  856.              * Add the new entry.
  857.              */
  858.             en_hashchar(i) = (uchar)c;
  859.             en_hashent(i) = ent;
  860.             en_hashcode(i) = freecode;
  861.  
  862.             /*
  863.              * If the next entry is going to be too big for the
  864.              * code size, then increase it, if possible.
  865.              */
  866.             if (freecode++ > maxcode) {
  867.                 while (bitoffset)
  868.                     putcode(0);
  869.                 ++n_bits;
  870.                 n_bits8 += 8;
  871.                 maxcode = MAXCODE(n_bits);
  872.             }
  873.         }
  874. #ifdef CHECK_GAP
  875.         else if (in_count >= checkpoint && block_compress) {
  876.             checkpoint = in_count + CHECK_GAP;
  877.             if (need_clear()) {
  878. #else
  879.         else if (block_compress) {
  880.             if (1) {
  881. #endif
  882.                 putcode(CLEAR);
  883.                 while (bitoffset > 0)
  884.                     putcode(0);
  885.                 clearhash();
  886.                 freecode = FIRST;
  887.                 maxcode = MAXCODE(INIT_BITS);
  888.                 n_bits = INIT_BITS;
  889.                 n_bits8 = n_bits << 3;
  890.             }
  891.         }
  892.         ent = c;
  893. Continue:;
  894.     }
  895.     /*
  896.      * Put out the final code.
  897.      */
  898.     putcode(ent);
  899.  
  900.     /*
  901.      * At EOF, write the rest of the buffer.
  902.      */
  903.     if (bitoffset > 0)
  904.         fwrite(bitbuf, 1, (bitoffset + 7) / 8, stdout);
  905.     out_count += (bitoffset + 7) / 8;
  906.     fflush(stdout);
  907.     if (ferror(stdout))
  908.         writeerr();
  909.  
  910.     /*
  911.      * Print out stats on stderr
  912.      */
  913.     if (! zcat_flg && verbose) {
  914.         fprintf(stderr, "Compression: ");
  915.         prratio(in_count - out_count, in_count);
  916.     }
  917.     if (out_count > in_count)    /* exit(2) if no savings */
  918.         exit_stat = 2;
  919. }
  920.  
  921. /*
  922.  * Output the given code. Assumes that chars are 8 bits.
  923.  * "n_bits" output bytes (containing 8 codes) are assembled
  924.  * in in "bitbuf", and then written out.
  925.  */
  926. void putcode(code)
  927. code_t code;
  928. {
  929.     register int i;
  930.     register uchar *bp;
  931.  
  932.     bp = &bitbuf[(bitoffset >> 3)];
  933.     i = bitoffset & 7;
  934.     bp[0] |= (uchar)(code << i);
  935.     bp[1] = (uchar)(code >>= (8 - i));
  936.     bp[2] = (uchar)(code >> 8);
  937.  
  938.     if ((bitoffset += n_bits) == n_bits8) {
  939.         bp = bitbuf;
  940.         i = n_bits;
  941.         out_count += i;
  942.         do
  943.             putchar(*bp++);
  944.         while (--i);
  945.         bitbuf[bitoffset = 0] = 0;
  946.     }
  947. }
  948.  
  949. #ifdef CHECK_GAP
  950. /*
  951.  * Compute the current compression ratio, and return non-zero if
  952.  * it is has decreased since the last we checked.
  953.  *
  954.  * Don't use this anymore. Whenever the hash table fills,
  955.  * we send a CLEAR immediately (if block_compress). This is faster,
  956.  * and doesn't appear to affect the compression ratio much.
  957.  */
  958. int need_clear()
  959. {
  960.     long rat;
  961.  
  962.     if (in_count > 0x007fffffL) {        /* shift will overflow */
  963.         rat = out_count >> 8;
  964.         if (rat == 0)                 /* Don't divide by zero */
  965.             rat = 0x7fffffffL;
  966.         else
  967.             rat = in_count / rat;
  968.     } else
  969.         rat = (in_count << 8) / out_count;
  970.  
  971.     if (rat > ratio) {
  972.         ratio = rat;
  973.         return (0);
  974.     }
  975.     else {
  976.         ratio = 0;
  977.         return (1);
  978.     }
  979. }
  980. #endif
  981.  
  982. /*
  983.  * Decompress stdin to stdout. This code assumes that chars are 8 bits.
  984.  */
  985. void decompress()
  986. {
  987.     register uchar    *stackp;
  988.     register code_t    code;
  989.     code_t        oldcode, incode;
  990.     code_t        codemask;
  991.     code_t        freecode;        /* first unused entry */
  992.     code_t        maxcode;        /* maximum code, given n_bits */
  993.     code_t        maxmaxcode;
  994.     int        finchar;
  995.     int        size;            /* #bits in bitbuf */
  996.     int        bitoff;            /* Offset into bitbuf */
  997.     int        n_bits;            /* number of bits/code */
  998. #ifndef i8088
  999.     register uchar    *bp;
  1000. #endif
  1001.  
  1002.     n_bits = INIT_BITS;
  1003.     maxcode = MAXCODE(INIT_BITS) - 1;
  1004.     codemask = MAXCODE(INIT_BITS);
  1005.     freecode = ((block_compress) ? FIRST : 256) - 1;
  1006.     maxmaxcode = MAXCODE(maxbits);
  1007.  
  1008.     /*
  1009.      * Read the first code into "oldcode"
  1010.      */
  1011.     if ((size = fread(bitbuf, 1, n_bits, stdin)) <= 0)
  1012.         return;
  1013.     size = (size << 3) - (n_bits - 1);
  1014.     oldcode = (bitbuf[0] | (bitbuf[1] << 8)) & codemask;
  1015.     bitoff = n_bits;
  1016.  
  1017.     /*
  1018.      * First code must be 8 bits == char. Write it, and die
  1019.      * if it can't be written.
  1020.      */
  1021.     putchar(finchar = oldcode);
  1022.     if (ferror(stdout))
  1023.         writeerr();
  1024.  
  1025.     stackp = de_stack;
  1026.  
  1027.     for ( ; ; ) {
  1028.         if (bitoff >= size) {
  1029.             if ((size = fread(bitbuf, 1, n_bits, stdin)) <= 0)
  1030.                 break;
  1031.             /* Round size down to integral number of codes */
  1032.             size = (size << 3) - (n_bits - 1);
  1033.             bitoff = 0;
  1034.         }
  1035.         /*
  1036.          * Read the next code into "code". On the 8088,
  1037.          * a slight speedup is possible because it has the right byte
  1038.          * order, and no alignment restrictions.
  1039.          */
  1040. #ifdef i8088
  1041.         code = ((code_t)(*(long *)&bitbuf[(bitoff >> 3)] >>
  1042.              (bitoff&7))) & codemask;
  1043. #else
  1044.         bp = &bitbuf[(bitoff >> 3)];
  1045.         code = (code_t)(((bp[0] | (code_t)bp[1] << 8) |
  1046.              (ulong)bp[2] << 16) >> (bitoff & 7)) & codemask;
  1047. #endif
  1048.         bitoff += n_bits;
  1049.  
  1050.         if ((code == CLEAR) && block_compress) {
  1051.             n_bits = INIT_BITS;
  1052.                 maxcode = MAXCODE(INIT_BITS) - 1;
  1053.             codemask = MAXCODE(INIT_BITS);
  1054.             freecode = (FIRST - 1) - 1;
  1055.             size = 0;
  1056.             continue;
  1057.         }
  1058.         incode = code;
  1059.  
  1060.         /*
  1061.          * Special case for KwKwK string.
  1062.          */
  1063.         if (code > freecode) {
  1064.             if (code != freecode + 1)
  1065.                 oops();
  1066.                 *stackp++ = (uchar)finchar;
  1067.             code = oldcode;
  1068.         }
  1069.  
  1070.         /*
  1071.          * Generate output characters in reverse order
  1072.          */
  1073.         while (code >= 256) {
  1074.             *stackp++ = de_suffixof(code);
  1075.             code = de_prefixof(code);
  1076.         }
  1077.  
  1078.         /*
  1079.          * And write them out in the forward order.
  1080.          */
  1081.         putchar(finchar = code);
  1082.         for (code = (stackp - de_stack) + 1; --code != 0; )
  1083.             putchar(*--stackp);
  1084.  
  1085.         /*
  1086.          * Generate the new entry.
  1087.          */
  1088.         if (freecode < maxmaxcode) {
  1089.             if (++freecode > maxcode) {
  1090.                 if (++n_bits == maxbits)
  1091.                     maxcode = maxmaxcode;
  1092.                 else
  1093.                     maxcode = MAXCODE(n_bits) - 1;
  1094.                 size = 0;
  1095.                 codemask = MAXCODE(n_bits);
  1096.             }
  1097.             de_prefixof(freecode) = oldcode;
  1098.             de_suffixof(freecode) = (uchar)finchar;
  1099.         }
  1100.         /*
  1101.          * Remember previous code.
  1102.          */
  1103.         oldcode = incode;
  1104.     }
  1105.     fflush(stdout);
  1106.     if (ferror(stdout))
  1107.         writeerr();
  1108. }
  1109.  
  1110. /*
  1111.  * Check a compressed file to make sure it has the proper magic number
  1112.  * at the beginning. Also read the third byte to determine "maxbits",
  1113.  * and "block_compress".
  1114.  */
  1115. int check_magic()
  1116. {
  1117.     if (! magic)
  1118.         return (1);
  1119.     if ((getchar() != MAGIC0) || (getchar() != MAGIC1)) {
  1120.         fprintf(stderr, "%s: not in compressed format\n", ifname);
  1121.         return (0);
  1122.     }
  1123.     maxbits = getchar();    /* set -b from file */
  1124.     block_compress = maxbits & BLOCK_MASK;
  1125.     maxbits &= BIT_MASK;
  1126.     if (maxbits > BITS) {
  1127.         fprintf(stderr,
  1128.            "%s: compressed with %d bits, can only handle %d bits\n",
  1129.             ifname, maxbits, BITS);
  1130.         return (0);
  1131.     }
  1132.     return (1);
  1133. }
  1134.  
  1135. void writeerr()
  1136. {
  1137.     perror(ofname);
  1138.     fclose(stdout);
  1139.     unlink(ofname);
  1140.     exit(1);
  1141. }
  1142.  
  1143. /*
  1144.  * Copy the permissions and file times from the input file to the
  1145.  * output.
  1146.  */
  1147. void copystat()
  1148. {
  1149.     struct stat statbuf;
  1150.     int mode;
  1151.     void (* ss)();
  1152. #ifndef __TURBOC__
  1153.     time_t timep[2];
  1154. #else
  1155.     struct ftime filetime;
  1156.     int fd;
  1157. #endif
  1158.  
  1159.     fclose(stdout);
  1160.     if (stat(ifname, &statbuf)) {        /* Get stat on input file */
  1161.         perror(ifname);
  1162.         return;
  1163.     }
  1164.     if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
  1165.         if (! verbose)
  1166.                 fprintf(stderr, "%s: ", ifname);
  1167.         fprintf(stderr, " -- not a regular file: unchanged");
  1168.         exit_stat = 1;
  1169.     }
  1170.     else if (statbuf.st_nlink > 1) {
  1171.         if (! verbose)
  1172.             fprintf(stderr, "%s: ", ifname);
  1173.         fprintf(stderr, " -- has %d other links: unchanged",
  1174.             statbuf.st_nlink - 1);
  1175.         exit_stat = 1;
  1176.     }
  1177.     else if (exit_stat == 2 && !force) { /* No compression: remove file.Z */
  1178.         if (verbose)
  1179.             fprintf(stderr, " -- file unchanged");
  1180.     }
  1181.     else {            /* ***** Successful Compression ***** */
  1182.         exit_stat = 0;
  1183.         mode = statbuf.st_mode & 07777;
  1184. #ifndef __ZTC__
  1185.         if (chmod(ofname, mode))        /* Copy modes */
  1186.             perror(ofname);
  1187. #endif
  1188. #ifndef MSDOS
  1189.         chown(ofname, statbuf.st_uid, statbuf.st_gid);    /* Copy ownership */
  1190. #endif
  1191. #ifndef __TURBOC__
  1192.         timep[0] = statbuf.st_atime;
  1193.         timep[1] = statbuf.st_mtime;
  1194.         utime(ofname, timep);
  1195. #else
  1196.         if ((fd = open(ofname, O_RDONLY)) >= 0) {
  1197.             if (getftime(fileno(stdin), &filetime) == 0)
  1198.                 setftime(fd, &filetime);
  1199.             close(fd);
  1200.         }
  1201. #endif
  1202.         fclose(stdin);
  1203.         ss = signal(SIGINT, SIG_IGN);
  1204.         okunlink = 0;
  1205.                 /* ^C here would leave both input, and output files around */
  1206.                 if ( !keep )
  1207.                 {
  1208.                   if (unlink(ifname))     /* Remove input file */
  1209.                           perror(ifname);
  1210.                   signal(SIGINT, ss);
  1211.                   if (verbose)
  1212.                           fprintf(stderr, " -- replaced with %s", ofname);
  1213.                 }
  1214.         return;        /* Successful return */
  1215.     }
  1216.  
  1217.     /* Unsuccessful return -- one of the tests failed */
  1218.  
  1219.     if (unlink(ofname))
  1220.         perror(ofname);
  1221. }
  1222.  
  1223. void onintr(void)
  1224. {
  1225.     fclose(stdout);
  1226.     if (okunlink)
  1227.         unlink(ofname);
  1228.     exit(1);
  1229. }
  1230.  
  1231. void oops(void)     /* wild pointer -- assume bad input */
  1232. {
  1233.     if (do_decomp)
  1234.         fprintf (stderr, "uncompress: %s is corrupt.\n", ifname);
  1235.     fclose(stdout);
  1236.     if (okunlink)
  1237.         unlink(ofname);
  1238.     exit(1);
  1239. }
  1240.  
  1241. void prratio(num, den)
  1242. long int num, den;
  1243. {
  1244.     register int q;                /* Doesn't need to be long */
  1245.  
  1246.     if (num > 214748L)            /* 2147483647/10000 */
  1247.         q = (int)(num / (den / 10000L));
  1248.     else
  1249.         q = (int)(10000L * num / den);    /* Long calculations, though */
  1250.     if (q < 0) {
  1251.         putc('-', stderr);
  1252.         q = -q;
  1253.     }
  1254.     fprintf(stderr, "%d.%02d%%", q / 100, q % 100);
  1255. }
  1256.  
  1257. void version()
  1258. {
  1259.         static shown = 0;
  1260.  
  1261.         if ( shown == 0 )
  1262.         {
  1263.           fprintf(stderr, "\n%s\n", rcs_ident + 5);
  1264.           fprintf(stderr, "BITS = %d\n", BITS);
  1265.           shown = 1;
  1266.         }
  1267. }
  1268.  
  1269. /*
  1270.  * Open the file "ofname" for binary output with possible check
  1271.  * for overwrite. If all goes well, return non-zero, else zero.
  1272.  */
  1273. int ofopen(filename)
  1274. char *filename;
  1275. {
  1276.     static char IOoutbuf[8192];
  1277.     struct stat statbuf;
  1278.  
  1279.     if (filename && !*filename)
  1280.         filename = 0;
  1281.  
  1282.     /*
  1283.      * Check for overwrite of existing file
  1284.      */
  1285.     if (filename && !force && stat(filename, &statbuf) == 0) {
  1286.         char response[2];
  1287.         response[0] = 'n';
  1288.         fprintf(stderr, "%s already exists;", filename);
  1289.         if (foreground) {
  1290.             fprintf(stderr, " do you wish to overwrite %s (y or n)? ", filename);
  1291.             fflush(stderr);
  1292.             read(2, response, 2);
  1293.             while (response[1] != '\n') {
  1294.                 if (read(2, response+1, 1) < 0)    { /* Ack! */
  1295.                     perror("stderr");
  1296.                     break;
  1297.                 }
  1298.             }
  1299.         }
  1300.         if (response[0] != 'y') {
  1301.             fprintf(stderr, "\tnot overwritten\n");
  1302.             return (0);
  1303.         }
  1304.     }
  1305.  
  1306.     okunlink = 1;
  1307.     /*
  1308.      * Open the output file.
  1309.      */
  1310.     if (filename && !freopen(filename, "wb", stdout)) {
  1311.         perror(filename);
  1312.         return (0);
  1313.     }
  1314. #ifdef O_BINARY
  1315.     setmode(fileno(stdout), O_BINARY);
  1316. #else
  1317. #ifdef __ZTC__
  1318.     /*
  1319.      * I'm sure there must be a better way in Zortech C to change the
  1320.      * mode of an already opened file, but I can't find it. It doesn't
  1321.      * have a "setmode" call it seems.
  1322.      */
  1323.     stdout->_flag &= ~_IOTRAN;
  1324. #endif
  1325. #endif
  1326.     setvbuf(stdout, IOoutbuf, _IOFBF, sizeof(IOoutbuf));
  1327.     return (1);
  1328. }
  1329.  
  1330. ifopen(filename)
  1331. char *filename;
  1332. {
  1333.     static char IOinbuf[8192];
  1334.  
  1335.     if (filename && !freopen(filename, "rb", stdin)) {
  1336.         perror(filename);
  1337.         return (0);
  1338.     }
  1339. #ifdef O_BINARY
  1340.     setmode(fileno(stdin), O_BINARY);
  1341. #else
  1342. #ifdef __ZTC__
  1343.     stdin->_flag &= ~_IOTRAN;
  1344. #endif
  1345. #endif
  1346.     setvbuf(stdin, IOinbuf, _IOFBF, sizeof(IOinbuf));
  1347.     return (1);
  1348. }
  1349.