home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / COMPRES.ZIP / COMPRESS.C next >
C/C++ Source or Header  |  1990-11-10  |  36KB  |  1,331 lines

  1. /*
  2.  * Compress - data compression program
  3.  */
  4. static char rcs_ident[] =
  5.  "@(#) compress, v 4.2 (DOS, OS/2) 90/02/27 15:40: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. #else
  179. #include <dos.h>
  180. #endif
  181. #endif
  182.  
  183. #ifdef PROTO
  184. /*
  185.  * Zortech appears to be missing this prototype, and MSC uses some
  186.  * silly structure as the second arg. Turbo C doesn't support this
  187.  * call at all.
  188.  */
  189. extern int utime(char *path, time_t times[]);
  190. #endif
  191.  
  192. #define BITS        16        /* max number of bits/code */
  193. #define INIT_BITS    9        /* initial number of bits/code */
  194.  
  195. #define MAXCODE(n_bits)        ((code_t)((1L << (n_bits)) - 1))
  196.  
  197. /*
  198.  * Magic numbers which should appear at the beginning of a compressed file.
  199.  */
  200. #define MAGIC0    0x1f
  201. #define MAGIC1    0x9d
  202.  
  203. /*
  204.  * Defines for third byte of header
  205.  */
  206. #define BIT_MASK    0x1f
  207. #define BLOCK_MASK    0x80
  208.  
  209. #if 0
  210. #define CHECK_GAP    10000        /* ratio check interval */
  211. #endif
  212.  
  213. /*
  214.  * the next two codes should not be changed lightly, as they must not
  215.  * lie within the contiguous general code space.
  216.  */
  217. #define FIRST    257        /* first free entry */
  218. #define    CLEAR    256        /* table clear output code */
  219.  
  220. #define DE_STACKLEN    8192    /* Size of decoder stack */
  221.  
  222. #define HSIZE    (1L << 16)    /* Size of the hash table. Don't change this */
  223.  
  224. typedef unsigned char    uchar;
  225. typedef unsigned long    ulong;
  226. typedef unsigned short    code_t;
  227. typedef    unsigned short    hash_t;
  228.  
  229. #ifdef PROTO
  230. #define ARGS(x)    x
  231. #else
  232. #define ARGS(x)    ()
  233. #endif
  234.  
  235. void        main ARGS((int argc, char **argv));
  236. void        Usage ARGS((void));
  237. void        version ARGS((void));
  238. void        compress ARGS((void));
  239. void        decompress ARGS((void));
  240. void        copystat ARGS((void));
  241. void        writeerr ARGS((void));
  242. void        cl_hash ARGS((void));
  243. void        putcode ARGS((code_t code));
  244. void        prratio ARGS((long num, long den));
  245. int        ofopen ARGS((char *filename));
  246. int        ifopen ARGS((char *filename));
  247. int        check_magic ARGS((void));
  248. int        need_clear ARGS((void));
  249. void            onintr ARGS((void));
  250. void            oops ARGS((void));
  251. int        taballoc ARGS((void));
  252. void        clearhash ARGS((void));
  253.  
  254. /*
  255.  * block compression parameters -- after all codes are used up,
  256.  * and compression rate changes, start over.
  257.  */
  258. int        block_compress = BLOCK_MASK;
  259.  
  260. int        maxbits = BITS;        /* user settable max # bits/code */
  261. int        magic = 1;        /* 3-byte magic number header */
  262. int        zcat_flg = 0;        /* Output on stdout */
  263. int        verbose = 0;        /* don't tell me about compression */
  264. int        force = 0;        /* Force overwrite of output file */
  265. int        do_decomp = 0;        /* Decompress rather than compress. */
  266. char        ofname[100];        /* Output file name */
  267. int        foreground;        /* Running in foreground? */
  268. int        exit_stat = 0;        /* Exit status */
  269. uchar        bitbuf[BITS+2];        /* For (dis)assembling code bytes */
  270. int        okunlink;        /* OK for sig handler to unlink output file */
  271. int             keep = 0;               /* keep input files ? */
  272. char        *ifname;
  273.  
  274. #ifdef i8088
  275.  
  276. uchar        *de_stack;
  277. uchar far    *charptr1;
  278. uchar far    *codeptrs1[2];
  279. uchar far    *codeptrs2[2];
  280.  
  281. #define de_suffixof(i)    charptr1[i]
  282. #define de_prefixof(i)    (*(code_t far *)&codeptrs1[i&1][i&~1])
  283.  
  284. #define en_hashchar(i)    charptr1[i]
  285. #define en_hashent(i)    (*(code_t far *)&codeptrs1[i&1][i&~1])
  286. #define en_hashcode(i)    (*(code_t far *)&codeptrs2[i&1][i&~1])
  287.  
  288. #ifndef MK_FP
  289. #define MK_FP(seg, ofs) \
  290.     ((void far *)(((ulong)(seg) << 16) | (unsigned)(ofs)))
  291. #endif
  292.  
  293. #define    PARA    16        /* Size of a paragraph */
  294.  
  295. /*
  296.  * Return a segment address which is the segment part of the normalized
  297.  * version of "fp" rounded upwards.
  298.  * I use this on the far pointers returned by "farmalloc". While
  299.  * they are probably already normalized, I have never seen this
  300.  * stated anywhere in the doc's.
  301.  *
  302.  * There is a lot of junk below which would be unecessary if only
  303.  * there were a reasonably compiler independent way of allocating
  304.  * a given number of PARAGRAPHS (like TC's allocmem). I can't find
  305.  * one though.
  306.  */
  307.  
  308. #define FP_SEGCEIL(fp)   (FP_SEG(fp) + (FP_OFF(fp) + PARA - 1) / PARA)
  309.  
  310. /*
  311.  * Allocate space for the tables used in {en,de}coding. These tables
  312.  * reside in the far heap. It may seem inefficient to be using far pointers
  313.  * for the base of these tables, because the offset portion will always be zero.
  314.  * We could just keep the segment address of the base, and then do something
  315.  * like:
  316.  *         *MK_FP(baseseg, offset) = blahblah;
  317.  *
  318.  * whenever we need to access the table. This SHOULD be more efficient,
  319.  * but the compilers do not appear to generate very efficient code in this
  320.  * case. Huge pointers are not used, because they are slow, and because
  321.  * Zortech does not support them.
  322.  */
  323.  
  324. #ifdef MSC
  325. #define farmalloc(n)    halloc(n, 1)
  326. #endif
  327.  
  328. int taballoc()
  329. {
  330. #ifdef OS2
  331.         ULONG size;
  332.         USHORT shift;
  333.         SEL sel;
  334.  
  335.         DosGetHugeShift(&shift);
  336. #else
  337.     char far *X;
  338. #endif
  339.  
  340.     if (do_decomp) {
  341.         if ((de_stack = malloc(DE_STACKLEN)) == 0)
  342.             return (0);
  343.     }
  344.     else {
  345. #ifdef OS2
  346.                 size = HSIZE * sizeof(code_t);
  347.  
  348.                 if ( DosAllocHuge(HIUSHORT(size), LOUSHORT(size),
  349.                                   &sel, 0, SEG_NONSHARED) )
  350.                         return (0);
  351.  
  352.                 codeptrs2[0] = MAKEP(sel, 0);
  353.                 codeptrs2[1] = MAKEP(sel + (1 << shift), 0);
  354. #else
  355.         if ((X = farmalloc((HSIZE + PARA) * sizeof(code_t))) == 0)
  356.                         return (0);
  357.  
  358.         codeptrs2[0] = MK_FP(FP_SEGCEIL(X), 0);
  359.                 codeptrs2[1] = MK_FP(FP_SEGCEIL(X) + HSIZE/PARA, 0);
  360. #endif
  361.     }
  362.  
  363. #ifdef OS2
  364.         size = HSIZE * sizeof(char);
  365.  
  366.         if ( DosAllocHuge(HIUSHORT(size), LOUSHORT(size),
  367.                           &sel, 0, SEG_NONSHARED) )
  368.                 return (0);
  369.  
  370.         charptr1 = MAKEP(sel, 0);
  371. #else
  372.     if ((X = farmalloc((HSIZE + PARA) * sizeof(char))) == 0)
  373.                 return (0);
  374.  
  375.     charptr1 = MK_FP(FP_SEGCEIL(X), 0);
  376. #endif
  377.  
  378. #ifdef OS2
  379.         size = HSIZE * sizeof(code_t);
  380.  
  381.         if ( DosAllocHuge(HIUSHORT(size), LOUSHORT(size),
  382.                           &sel, 0, SEG_NONSHARED) )
  383.                 return (0);
  384.  
  385.         codeptrs1[0] = MAKEP(sel, 0);
  386.         codeptrs1[1] = MAKEP(sel + (1 << shift), 0);
  387. #else
  388.     if ((X = farmalloc((HSIZE + PARA) * sizeof(code_t))) == 0)
  389.                 return (0);
  390.  
  391.     codeptrs1[0] = MK_FP(FP_SEGCEIL(X), 0);
  392.     codeptrs1[1] = MK_FP(FP_SEGCEIL(X) + HSIZE/PARA, 0);
  393. #endif
  394.  
  395.     return (1);
  396. }
  397.  
  398. #else
  399.  
  400. uchar    chartab1[HSIZE];
  401. code_t    codetab1[HSIZE];
  402. code_t    codetab2[HSIZE];
  403.  
  404. #define de_suffixof(i)    chartab1[i]
  405. #define de_prefixof(i)    codetab1[i]
  406. #define de_stack    (uchar *)codetab2
  407.  
  408. #define en_hashchar(i)    chartab1[i]
  409. #define en_hashent(i)    codetab1[i]
  410. #define en_hashcode(i)    codetab2[i]
  411.  
  412. #endif
  413.  
  414. void Usage()
  415. {
  416.   printf("\nUsage: COMPRESS [-dfvcVnC] [-b maxbits] [file ...]\n\n");
  417.   printf("  -V   print Version\n");
  418.   printf("  -h   print usage\n");
  419.   printf("  -v   verbose\n");
  420.   printf("  -q   quiet (default)\n");
  421.   printf("  -d   decompress\n");
  422.   printf("  -c   cat all output to stdout\n");
  423.   printf("  -k   keep input files\n");
  424.   printf("  -f   force overwrite of output files\n");
  425.   printf("  -n   no header: useful to uncompress old files\n");
  426.   printf("  -C   generate output compatible with compress 2.0.\n");
  427.   printf("  -b maxbits   maxbits. Default %d\n", BITS);
  428. }
  429.  
  430. /*****************************************************************
  431.  * TAG( main )
  432.  *
  433.  * Algorithm from "A Technique for High Performance Data Compression",
  434.  * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
  435.  *
  436.  * Usage: compress [-dfvc] [-b bits] [file ...]
  437.  * Inputs:
  438.  *    -d:        If given, decompression is done instead.
  439.  *
  440.  *      -c:         Write output on stdout, don't remove original.
  441.  *
  442.  *      -b:         Parameter limits the max number of bits/code.
  443.  *
  444.  *    -f:        Forces output file to be generated, even if one already
  445.  *            exists, and even if no space is saved by compressing.
  446.  *            If -f is not used, the user will be prompted if stdin is
  447.  *            a tty, otherwise, the output file will not be overwritten.
  448.  *
  449.  *      -v:        Write compression statistics
  450.  *
  451.  *     file ...:   Files to be compressed.  If none specified, stdin
  452.  *            is used.
  453.  * Outputs:
  454.  *    file.Z:        Compressed form of file with same mode, owner, and utimes
  455.  *     or stdout   (if stdin used as input)
  456.  *
  457.  * Assumptions:
  458.  *    When filenames are given, replaces with the compressed version
  459.  *    (.Z suffix) only if the file decreases in size.
  460.  * Algorithm:
  461.  *     Modified Lempel-Ziv method (LZW).  Basically finds common
  462.  * substrings and replaces them with a variable size code.  This is
  463.  * deterministic, and can be done on the fly.  Thus, the decompression
  464.  * procedure needs no input table, but tracks the way the table was built.
  465.  */
  466.  
  467. #ifdef __ZTC__
  468. #include <int.h>
  469. int silly_nonsense(struct INT_DATA *foo) {raise(SIGINT); return 1;}
  470. #endif
  471.  
  472. #define ARGVAL() (*++(*argv) || (--argc && *++argv))
  473.  
  474. void main(argc, argv)
  475. int argc;
  476. char **argv;
  477. {
  478.     char tempname[100], *cp;
  479.  
  480.     if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
  481.         signal(SIGINT, onintr);
  482. #ifdef __ZTC__
  483.         /*
  484.          * The "signal" call above isn't good enough for Zortech
  485.          */
  486.         int_intercept(0x23, silly_nonsense, 256);
  487. #endif
  488. #ifdef SIGSEGV
  489.         signal(SIGSEGV, oops);
  490. #endif
  491.         if (isatty(2))
  492.             foreground = 1;
  493.     }
  494.  
  495. #ifndef MSDOS
  496.     if ((cp = strrchr(argv[0], '/')) != 0)
  497.         cp++;
  498.     else
  499.         cp = argv[0];
  500. #else
  501.     for (cp = argv[0]; *cp; cp++)
  502.         if (*cp == '/' || *cp == '\\')
  503.             argv[0] = cp + 1;
  504.     cp = strlwr(argv[0]);
  505. #endif
  506.     /* Limited to 8 char filenames under DOS */
  507.     if (strncmp(cp, "uncompress", 8) == 0)
  508.         do_decomp = 1;
  509.     else if (strncmp(cp, "zcat", 4) == 0) {
  510.         do_decomp = 1;
  511.         zcat_flg = 1;
  512.     }
  513.  
  514. #ifdef BSD4_2
  515.     /* 4.2BSD dependent - take it out if not */
  516.     setlinebuf(stderr);
  517. #endif /* BSD4_2 */
  518.  
  519.     for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
  520.         while (*++(*argv)) {    /* Process all flags in this arg */
  521.             switch (**argv) {
  522.             case 'V':
  523.                                 version();
  524.                 break;
  525.             case 'v':
  526.                 verbose = 1;
  527.                 break;
  528.             case 'd':
  529.                 do_decomp = 1;
  530.                 break;
  531.             case 'f':
  532.             case 'F':
  533.                 force = 1;
  534.                 break;
  535.             case 'n':
  536.                 magic = 0;
  537.                 break;
  538.             case 'C':
  539.                 block_compress = 0;
  540.                 break;
  541.             case 'b':
  542.                 if (!ARGVAL()) {
  543.                     fprintf(stderr, "Missing maxbits\n");
  544.                     Usage();
  545.                     exit(1);
  546.                 }
  547.                 maxbits = atoi(*argv);
  548.                 goto nextarg;
  549.             case 'c':
  550.                 zcat_flg = 1;
  551.                 break;
  552.             case 'q':
  553.                 verbose = 0;
  554.                                 break;
  555.                         case 'k':
  556.                                 keep = 1;
  557.                 break;
  558.                         case 'h':
  559.                                 Usage();
  560.                 exit(1);
  561.             default:
  562.                 fprintf(stderr, "Unknown flag: '%c'; ", **argv);
  563.                 Usage();
  564.                 exit(1);
  565.             }
  566.         }
  567. nextarg:;
  568.     }
  569.  
  570. #ifdef i8088
  571.     if (! taballoc()) {
  572.         fprintf(stderr, "compress: out of memory\n");
  573.         exit(1);
  574.     }
  575. #endif
  576.     /*
  577.      * If no filename args, do standard input.
  578.      */
  579.         if (argc <= 0) {
  580.                 if ( isatty(fileno(stdin)) )
  581.                 {
  582.                   version();
  583.                   Usage();
  584.                   exit(1);
  585.                 }
  586.  
  587.         if (! ifopen((char *)0) || ! ofopen((char *)0))
  588.             exit(1);
  589.  
  590.         ifname = "stdin";
  591.  
  592.         if (do_decomp) {
  593.             if (!check_magic())
  594.                 exit(1);
  595.             decompress();
  596.         }
  597.         else {
  598.             compress();
  599.             if (verbose)
  600.                 putc('\n', stderr);
  601.         }
  602.         exit(exit_stat);
  603.     }
  604.  
  605.     while (--argc >= 0) {
  606.         char *suf;
  607.  
  608.         ifname = *argv++;
  609.         suf = strrchr(ifname, '.');
  610.  
  611.         exit_stat = 0;
  612.         okunlink = 0;
  613.  
  614.         if (do_decomp) {        /* DECOMPRESSION */
  615.             if (!suf || (strcmp(suf, ".Z") && strcmp(suf, ".z"))) {
  616.                                 strcpy(tempname, ifname);
  617. #ifdef MSDOS
  618.                                 if ( suf = strrchr(tempname, '.') )
  619.                                   if ( suf > strrchr(tempname, '\\') )
  620.                                     *suf = 0;
  621. #endif
  622.                 strcat(tempname, ".Z");
  623.                 ifname = tempname;
  624.             }
  625.             if (! ifopen(ifname) || !check_magic())
  626.                 continue;
  627.             if (zcat_flg)
  628.                 ofname[0] = '\0';
  629.             else {
  630.                 strcpy(ofname, ifname);
  631.                 ofname[strlen(ifname) - 2] = '\0';
  632.             }
  633.             if (!ofopen(ofname))
  634.                 continue;
  635.             if (!zcat_flg && verbose)
  636.                 fprintf(stderr, "%s: ", ifname);
  637.             decompress();
  638.         }
  639.         else {                /* COMPRESSION */
  640.             if (suf && (!strcmp(suf, ".Z") || !strcmp(suf, ".z"))) {
  641.                 fprintf(stderr, "%s: already has .Z suffix -- no change\n",
  642.                     ifname);
  643.                 continue;
  644.             }
  645.             if (! ifopen(ifname))
  646.                 continue;
  647.             if (zcat_flg)
  648.                 ofname[0] = 0;
  649.             else {
  650.                 strcpy(ofname, ifname);
  651. #ifdef MSDOS
  652.                                 if ( suf = strrchr(ofname, '.') )
  653.                                   if ( suf > strrchr(ofname, '\\') )
  654.                                     *suf = 0;
  655. #endif
  656. #ifndef MSDOS    /* We'll let ofopen do the complaining */
  657. #ifndef BSD4_2
  658.                 if ((cp = strrchr(ofname, '/')) != NULL)
  659.                     cp++;
  660.                 else
  661.                     cp = ofname;
  662.                 if (strlen(cp) > 12) {
  663.                     fprintf(stderr,"%s: filename too long to tack on .Z\n",cp);
  664.                     continue;
  665.                 }
  666. #endif
  667. #endif
  668.                 strcat(ofname, ".Z");
  669.             }
  670.             if (! ofopen(ofname))
  671.                 continue;
  672.             if (! zcat_flg && verbose)
  673.                 fprintf(stderr, "%s: ", ifname);
  674.             compress();
  675.         }
  676.  
  677.         if (! zcat_flg) {
  678.             copystat();
  679.             if ((exit_stat == 1) || verbose)
  680.                 putc('\n', stderr);
  681.         }
  682.     }
  683.     exit(exit_stat);
  684. }
  685.  
  686. /*
  687.  * compress stdin to stdout
  688.  *
  689.  * Algorithm:  use open addressing double hashing (no chaining) on the
  690.  * prefix code / next character combination.  We do a variant of Knuth's
  691.  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  692.  * secondary probe.  Here, the modular division first probe is gives way
  693.  * to a faster exclusive-or manipulation.  Also do block compression with
  694.  * an adaptive reset, whereby the code table is cleared when the compression
  695.  * ratio decreases, but after the table fills.  The variable-length output
  696.  * codes are re-sized at this point, and a special CLEAR code is generated
  697.  * for the decompressor.  Late addition:  construct the table according to
  698.  * file size for noticeable speed improvement on small files.  Please direct
  699.  * questions about this implementation to ames!jaw.
  700.  *
  701.  * Secondary hash function changed slightly for DOS. Hash table used to be
  702.  * > 64K. This is slow on a 16 bit machine because it means long arithmetic,
  703.  * and more complicated addressing of tables in the far address space.
  704.  * We now restrict the table size to 64K, and, so that the table does
  705.  * not overfill, restrict the codes that we will generate to MAXMAXCODE.
  706.  * This causes slightly poorer compression in some cases, but, interestingly
  707.  * enough, also causes better compression ratios in certain other cases.
  708.  * Yes, this is all compatible with other compresses.
  709.  */
  710. static long    in_count;        /* length of input */
  711. static long    out_count;        /* length of compressed output */
  712. static long    ratio;            /* in_count/out_count * 256 */
  713. static int    n_bits;            /* number of bits/code */
  714. static int    n_bits8;        /* bits/code times 8 */
  715. static int    bitoffset;        /* Offset into bitbuf */
  716.  
  717. #define NOENT        ((code_t)0xffff)
  718. #define MAXMAXCODE    ((code_t)0xf000)
  719.  
  720. /*
  721.  * Clear out the hash table. We try to do this as quickly as possible, because
  722.  * it's running time dominates for small files. For big files, it doesn't matter
  723.  * much because it doesn't get called often. Now I understand why the original
  724.  * had a variable size hash table.
  725.  */
  726. void clearhash()
  727. {
  728. #ifdef i8088
  729.     register unsigned i;
  730.     code_t far *hp;
  731.  
  732.     hp = (code_t far *)codeptrs1[0];
  733.     i = (unsigned)(HSIZE/2);
  734.     do
  735.         *hp++ = NOENT;
  736.     while (--i > 0);
  737.  
  738.     hp = (code_t far *)codeptrs1[1];
  739.     i = (unsigned)(HSIZE/2);
  740.     do
  741.         *hp++ = NOENT;
  742.     while (--i > 0);
  743. #else
  744.     /*
  745.      * WARNING: assumes that NOENT == 0xffff
  746.      */
  747.     memset((char *)codetab1, 0xff, HSIZE*sizeof(code_t));
  748. #endif
  749. }
  750.  
  751. /*
  752.  * Compress stdin to stdout.
  753.  */
  754. void compress()
  755. {
  756.     register hash_t    i;
  757.     register code_t    ent;
  758.     hash_t        disp;
  759.     int        c;
  760.     code_t        freecode;    /* first unused entry */
  761.     code_t        maxcode;    /* maximum code, given n_bits */
  762.     code_t        maxmaxcode;
  763.     code_t        k;
  764. #ifdef CHECK_GAP
  765.     long        checkpoint = 0;
  766. #endif
  767.  
  768.     if (maxbits < INIT_BITS)
  769.         maxbits = INIT_BITS;
  770.     if (maxbits > BITS)
  771.         maxbits = BITS;
  772.  
  773.     if (magic) {
  774.         putchar(MAGIC0); putchar(MAGIC1);
  775.         putchar(maxbits | block_compress);
  776.         if (ferror(stdout))
  777.             writeerr();
  778.     }
  779.  
  780.     bitbuf[bitoffset = 0] = 0;
  781.     out_count = 3;            /* includes 3-byte header mojo */
  782.     ratio = 0;
  783.     in_count = 1;
  784.  
  785.     n_bits = INIT_BITS;
  786.     n_bits8 = INIT_BITS << 3;
  787.     maxcode = MAXCODE(INIT_BITS);
  788.     maxmaxcode = MAXCODE(maxbits);
  789.     if (maxmaxcode > MAXMAXCODE)
  790.         maxmaxcode = MAXMAXCODE;
  791.  
  792.     freecode = ((block_compress) ? FIRST : 256);
  793.  
  794.     clearhash();
  795.  
  796.     ent = getchar();
  797.  
  798.     while ((c = getchar()) != EOF) {
  799.         in_count++;
  800.  
  801.         i = (hash_t)(c << 8) ^ ent;        /* xor hashing */
  802.  
  803.         if ((k = en_hashent(i)) == ent && en_hashchar(i) == (uchar)c) {
  804.             ent = en_hashcode(i);
  805.             goto Continue;
  806.         }
  807.  
  808.         if (k != NOENT) {
  809.             /*
  810.              * New secondary hash for 64K table.
  811.              * Experiment shows that the shift by 6 works well.
  812.              * Beats me why. "disp" must be relatively
  813.              * prime to the table size. Since the table size is a
  814.              * power of 2, this means "disp" must be odd.
  815.              *
  816.              * Note that we do not do a range check before doing
  817.              * "i -= disp". It is assumed that the hash table size
  818.              * (HSIZE) is 64K, and that the type "hash_t" (which
  819.              * is unsigned short) is 16 bits. Thus it is impossible
  820.              * for "i" to be out of range. On a machine with something
  821.              * other than 16 bit shorts, this would have to change.
  822.              */
  823.             disp = ((hash_t)(c << 6) ^ ent) | 1;
  824.             do {
  825.                 i -= disp;
  826.                 if ((k = en_hashent(i)) == ent &&
  827.                     en_hashchar(i) == (uchar)c) {
  828.                     ent = en_hashcode(i);
  829.                     goto Continue;
  830.                 }
  831.             } while (k != NOENT);
  832.         }
  833.  
  834.         putcode(ent);
  835.  
  836.         if (freecode <= maxmaxcode) {
  837.             /*
  838.              * Add the new entry.
  839.              */
  840.             en_hashchar(i) = (uchar)c;
  841.             en_hashent(i) = ent;
  842.             en_hashcode(i) = freecode;
  843.  
  844.             /*
  845.              * If the next entry is going to be too big for the
  846.              * code size, then increase it, if possible.
  847.              */
  848.             if (freecode++ > maxcode) {
  849.                 while (bitoffset)
  850.                     putcode(0);
  851.                 ++n_bits;
  852.                 n_bits8 += 8;
  853.                 maxcode = MAXCODE(n_bits);
  854.             }
  855.         }
  856. #ifdef CHECK_GAP
  857.         else if (in_count >= checkpoint && block_compress) {
  858.             checkpoint = in_count + CHECK_GAP;
  859.             if (need_clear()) {
  860. #else
  861.         else if (block_compress) {
  862.             if (1) {
  863. #endif
  864.                 putcode(CLEAR);
  865.                 while (bitoffset > 0)
  866.                     putcode(0);
  867.                 clearhash();
  868.                 freecode = FIRST;
  869.                 maxcode = MAXCODE(INIT_BITS);
  870.                 n_bits = INIT_BITS;
  871.                 n_bits8 = n_bits << 3;
  872.             }
  873.         }
  874.         ent = c;
  875. Continue:;
  876.     }
  877.     /*
  878.      * Put out the final code.
  879.      */
  880.     putcode(ent);
  881.  
  882.     /*
  883.      * At EOF, write the rest of the buffer.
  884.      */
  885.     if (bitoffset > 0)
  886.         fwrite(bitbuf, 1, (bitoffset + 7) / 8, stdout);
  887.     out_count += (bitoffset + 7) / 8;
  888.     fflush(stdout);
  889.     if (ferror(stdout))
  890.         writeerr();
  891.  
  892.     /*
  893.      * Print out stats on stderr
  894.      */
  895.     if (! zcat_flg && verbose) {
  896.         fprintf(stderr, "Compression: ");
  897.         prratio(in_count - out_count, in_count);
  898.     }
  899.     if (out_count > in_count)    /* exit(2) if no savings */
  900.         exit_stat = 2;
  901. }
  902.  
  903. /*
  904.  * Output the given code. Assumes that chars are 8 bits.
  905.  * "n_bits" output bytes (containing 8 codes) are assembled
  906.  * in in "bitbuf", and then written out.
  907.  */
  908. void putcode(code)
  909. code_t code;
  910. {
  911.     register int i;
  912.     register uchar *bp;
  913.  
  914.     bp = &bitbuf[(bitoffset >> 3)];
  915.     i = bitoffset & 7;
  916.     bp[0] |= (uchar)(code << i);
  917.     bp[1] = (uchar)(code >>= (8 - i));
  918.     bp[2] = (uchar)(code >> 8);
  919.  
  920.     if ((bitoffset += n_bits) == n_bits8) {
  921.         bp = bitbuf;
  922.         i = n_bits;
  923.         out_count += i;
  924.         do
  925.             putchar(*bp++);
  926.         while (--i);
  927.         bitbuf[bitoffset = 0] = 0;
  928.     }
  929. }
  930.  
  931. #ifdef CHECK_GAP
  932. /*
  933.  * Compute the current compression ratio, and return non-zero if
  934.  * it is has decreased since the last we checked.
  935.  *
  936.  * Don't use this anymore. Whenever the hash table fills,
  937.  * we send a CLEAR immediately (if block_compress). This is faster,
  938.  * and doesn't appear to affect the compression ratio much.
  939.  */
  940. int need_clear()
  941. {
  942.     long rat;
  943.  
  944.     if (in_count > 0x007fffffL) {        /* shift will overflow */
  945.         rat = out_count >> 8;
  946.         if (rat == 0)                 /* Don't divide by zero */
  947.             rat = 0x7fffffffL;
  948.         else
  949.             rat = in_count / rat;
  950.     } else
  951.         rat = (in_count << 8) / out_count;
  952.  
  953.     if (rat > ratio) {
  954.         ratio = rat;
  955.         return (0);
  956.     }
  957.     else {
  958.         ratio = 0;
  959.         return (1);
  960.     }
  961. }
  962. #endif
  963.  
  964. /*
  965.  * Decompress stdin to stdout. This code assumes that chars are 8 bits.
  966.  */
  967. void decompress()
  968. {
  969.     register uchar    *stackp;
  970.     register code_t    code;
  971.     code_t        oldcode, incode;
  972.     code_t        codemask;
  973.     code_t        freecode;        /* first unused entry */
  974.     code_t        maxcode;        /* maximum code, given n_bits */
  975.     code_t        maxmaxcode;
  976.     int        finchar;
  977.     int        size;            /* #bits in bitbuf */
  978.     int        bitoff;            /* Offset into bitbuf */
  979.     int        n_bits;            /* number of bits/code */
  980. #ifndef i8088
  981.     register uchar    *bp;
  982. #endif
  983.  
  984.     n_bits = INIT_BITS;
  985.     maxcode = MAXCODE(INIT_BITS) - 1;
  986.     codemask = MAXCODE(INIT_BITS);
  987.     freecode = ((block_compress) ? FIRST : 256) - 1;
  988.     maxmaxcode = MAXCODE(maxbits);
  989.  
  990.     /*
  991.      * Read the first code into "oldcode"
  992.      */
  993.     if ((size = fread(bitbuf, 1, n_bits, stdin)) <= 0)
  994.         return;
  995.     size = (size << 3) - (n_bits - 1);
  996.     oldcode = (bitbuf[0] | (bitbuf[1] << 8)) & codemask;
  997.     bitoff = n_bits;
  998.  
  999.     /*
  1000.      * First code must be 8 bits == char. Write it, and die
  1001.      * if it can't be written.
  1002.      */
  1003.     putchar(finchar = oldcode);
  1004.     if (ferror(stdout))
  1005.         writeerr();
  1006.  
  1007.     stackp = de_stack;
  1008.  
  1009.     for ( ; ; ) {
  1010.         if (bitoff >= size) {
  1011.             if ((size = fread(bitbuf, 1, n_bits, stdin)) <= 0)
  1012.                 break;
  1013.             /* Round size down to integral number of codes */
  1014.             size = (size << 3) - (n_bits - 1);
  1015.             bitoff = 0;
  1016.         }
  1017.         /*
  1018.          * Read the next code into "code". On the 8088,
  1019.          * a slight speedup is possible because it has the right byte
  1020.          * order, and no alignment restrictions.
  1021.          */
  1022. #ifdef i8088
  1023.         code = ((code_t)(*(long *)&bitbuf[(bitoff >> 3)] >>
  1024.              (bitoff&7))) & codemask;
  1025. #else
  1026.         bp = &bitbuf[(bitoff >> 3)];
  1027.         code = (code_t)(((bp[0] | (code_t)bp[1] << 8) |
  1028.              (ulong)bp[2] << 16) >> (bitoff & 7)) & codemask;
  1029. #endif
  1030.         bitoff += n_bits;
  1031.  
  1032.         if ((code == CLEAR) && block_compress) {
  1033.             n_bits = INIT_BITS;
  1034.                 maxcode = MAXCODE(INIT_BITS) - 1;
  1035.             codemask = MAXCODE(INIT_BITS);
  1036.             freecode = (FIRST - 1) - 1;
  1037.             size = 0;
  1038.             continue;
  1039.         }
  1040.         incode = code;
  1041.  
  1042.         /*
  1043.          * Special case for KwKwK string.
  1044.          */
  1045.         if (code > freecode) {
  1046.             if (code != freecode + 1)
  1047.                 oops();
  1048.                 *stackp++ = (uchar)finchar;
  1049.             code = oldcode;
  1050.         }
  1051.  
  1052.         /*
  1053.          * Generate output characters in reverse order
  1054.          */
  1055.         while (code >= 256) {
  1056.             *stackp++ = de_suffixof(code);
  1057.             code = de_prefixof(code);
  1058.         }
  1059.  
  1060.         /*
  1061.          * And write them out in the forward order.
  1062.          */
  1063.         putchar(finchar = code);
  1064.         for (code = (stackp - de_stack) + 1; --code != 0; )
  1065.             putchar(*--stackp);
  1066.  
  1067.         /*
  1068.          * Generate the new entry.
  1069.          */
  1070.         if (freecode < maxmaxcode) {
  1071.             if (++freecode > maxcode) {
  1072.                 if (++n_bits == maxbits)
  1073.                     maxcode = maxmaxcode;
  1074.                 else
  1075.                     maxcode = MAXCODE(n_bits) - 1;
  1076.                 size = 0;
  1077.                 codemask = MAXCODE(n_bits);
  1078.             }
  1079.             de_prefixof(freecode) = oldcode;
  1080.             de_suffixof(freecode) = (uchar)finchar;
  1081.         }
  1082.         /*
  1083.          * Remember previous code.
  1084.          */
  1085.         oldcode = incode;
  1086.     }
  1087.     fflush(stdout);
  1088.     if (ferror(stdout))
  1089.         writeerr();
  1090. }
  1091.  
  1092. /*
  1093.  * Check a compressed file to make sure it has the proper magic number
  1094.  * at the beginning. Also read the third byte to determine "maxbits",
  1095.  * and "block_compress".
  1096.  */
  1097. int check_magic()
  1098. {
  1099.     if (! magic)
  1100.         return (1);
  1101.     if ((getchar() != MAGIC0) || (getchar() != MAGIC1)) {
  1102.         fprintf(stderr, "%s: not in compressed format\n", ifname);
  1103.         return (0);
  1104.     }
  1105.     maxbits = getchar();    /* set -b from file */
  1106.     block_compress = maxbits & BLOCK_MASK;
  1107.     maxbits &= BIT_MASK;
  1108.     if (maxbits > BITS) {
  1109.         fprintf(stderr,
  1110.            "%s: compressed with %d bits, can only handle %d bits\n",
  1111.             ifname, maxbits, BITS);
  1112.         return (0);
  1113.     }
  1114.     return (1);
  1115. }
  1116.  
  1117. void writeerr()
  1118. {
  1119.     perror(ofname);
  1120.     fclose(stdout);
  1121.     unlink(ofname);
  1122.     exit(1);
  1123. }
  1124.  
  1125. /*
  1126.  * Copy the permissions and file times from the input file to the
  1127.  * output.
  1128.  */
  1129. void copystat()
  1130. {
  1131.     struct stat statbuf;
  1132.     int mode;
  1133.     void (* ss)();
  1134. #ifndef __TURBOC__
  1135.     time_t timep[2];
  1136. #else
  1137.     struct ftime filetime;
  1138.     int fd;
  1139. #endif
  1140.  
  1141.     fclose(stdout);
  1142.     if (stat(ifname, &statbuf)) {        /* Get stat on input file */
  1143.         perror(ifname);
  1144.         return;
  1145.     }
  1146.     if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
  1147.         if (! verbose)
  1148.                 fprintf(stderr, "%s: ", ifname);
  1149.         fprintf(stderr, " -- not a regular file: unchanged");
  1150.         exit_stat = 1;
  1151.     }
  1152.     else if (statbuf.st_nlink > 1) {
  1153.         if (! verbose)
  1154.             fprintf(stderr, "%s: ", ifname);
  1155.         fprintf(stderr, " -- has %d other links: unchanged",
  1156.             statbuf.st_nlink - 1);
  1157.         exit_stat = 1;
  1158.     }
  1159.     else if (exit_stat == 2 && !force) { /* No compression: remove file.Z */
  1160.         if (verbose)
  1161.             fprintf(stderr, " -- file unchanged");
  1162.     }
  1163.     else {            /* ***** Successful Compression ***** */
  1164.         exit_stat = 0;
  1165.         mode = statbuf.st_mode & 07777;
  1166. #ifndef __ZTC__
  1167.         if (chmod(ofname, mode))        /* Copy modes */
  1168.             perror(ofname);
  1169. #endif
  1170. #ifndef MSDOS
  1171.         chown(ofname, statbuf.st_uid, statbuf.st_gid);    /* Copy ownership */
  1172. #endif
  1173. #ifndef __TURBOC__
  1174.         timep[0] = statbuf.st_atime;
  1175.         timep[1] = statbuf.st_mtime;
  1176.         utime(ofname, timep);
  1177. #else
  1178.         if ((fd = open(ofname, O_RDONLY)) >= 0) {
  1179.             if (getftime(fileno(stdin), &filetime) == 0)
  1180.                 setftime(fd, &filetime);
  1181.             close(fd);
  1182.         }
  1183. #endif
  1184.         fclose(stdin);
  1185.         ss = signal(SIGINT, SIG_IGN);
  1186.         okunlink = 0;
  1187.                 /* ^C here would leave both input, and output files around */
  1188.                 if ( !keep )
  1189.                 {
  1190.                   if (unlink(ifname))     /* Remove input file */
  1191.                           perror(ifname);
  1192.                   signal(SIGINT, ss);
  1193.                   if (verbose)
  1194.                           fprintf(stderr, " -- replaced with %s", ofname);
  1195.                 }
  1196.         return;        /* Successful return */
  1197.     }
  1198.  
  1199.     /* Unsuccessful return -- one of the tests failed */
  1200.  
  1201.     if (unlink(ofname))
  1202.         perror(ofname);
  1203. }
  1204.  
  1205. void onintr(void)
  1206. {
  1207.     fclose(stdout);
  1208.     if (okunlink)
  1209.         unlink(ofname);
  1210.     exit(1);
  1211. }
  1212.  
  1213. void oops(void)     /* wild pointer -- assume bad input */
  1214. {
  1215.     if (do_decomp)
  1216.         fprintf (stderr, "uncompress: %s is corrupt.\n", ifname);
  1217.     fclose(stdout);
  1218.     if (okunlink)
  1219.         unlink(ofname);
  1220.     exit(1);
  1221. }
  1222.  
  1223. void prratio(num, den)
  1224. long int num, den;
  1225. {
  1226.     register int q;                /* Doesn't need to be long */
  1227.  
  1228.     if (num > 214748L)            /* 2147483647/10000 */
  1229.         q = (int)(num / (den / 10000L));
  1230.     else
  1231.         q = (int)(10000L * num / den);    /* Long calculations, though */
  1232.     if (q < 0) {
  1233.         putc('-', stderr);
  1234.         q = -q;
  1235.     }
  1236.     fprintf(stderr, "%d.%02d%%", q / 100, q % 100);
  1237. }
  1238.  
  1239. void version()
  1240. {
  1241.         static shown = 0;
  1242.  
  1243.         if ( shown == 0 )
  1244.         {
  1245.           fprintf(stderr, "\n%s\n", rcs_ident + 5);
  1246.           fprintf(stderr, "BITS = %d\n", BITS);
  1247.           shown = 1;
  1248.         }
  1249. }
  1250.  
  1251. /*
  1252.  * Open the file "ofname" for binary output with possible check
  1253.  * for overwrite. If all goes well, return non-zero, else zero.
  1254.  */
  1255. int ofopen(filename)
  1256. char *filename;
  1257. {
  1258.     static char IOoutbuf[8192];
  1259.     struct stat statbuf;
  1260.  
  1261.     if (filename && !*filename)
  1262.         filename = 0;
  1263.  
  1264.     /*
  1265.      * Check for overwrite of existing file
  1266.      */
  1267.     if (filename && !force && stat(filename, &statbuf) == 0) {
  1268.         char response[2];
  1269.         response[0] = 'n';
  1270.         fprintf(stderr, "%s already exists;", filename);
  1271.         if (foreground) {
  1272.             fprintf(stderr, " do you wish to overwrite %s (y or n)? ", filename);
  1273.             fflush(stderr);
  1274.             read(2, response, 2);
  1275.             while (response[1] != '\n') {
  1276.                 if (read(2, response+1, 1) < 0)    { /* Ack! */
  1277.                     perror("stderr");
  1278.                     break;
  1279.                 }
  1280.             }
  1281.         }
  1282.         if (response[0] != 'y') {
  1283.             fprintf(stderr, "\tnot overwritten\n");
  1284.             return (0);
  1285.         }
  1286.     }
  1287.  
  1288.     okunlink = 1;
  1289.     /*
  1290.      * Open the output file.
  1291.      */
  1292.     if (filename && !freopen(filename, "wb", stdout)) {
  1293.         perror(filename);
  1294.         return (0);
  1295.     }
  1296. #ifdef O_BINARY
  1297.     setmode(fileno(stdout), O_BINARY);
  1298. #else
  1299. #ifdef __ZTC__
  1300.     /*
  1301.      * I'm sure there must be a better way in Zortech C to change the
  1302.      * mode of an already opened file, but I can't find it. It doesn't
  1303.      * have a "setmode" call it seems.
  1304.      */
  1305.     stdout->_flag &= ~_IOTRAN;
  1306. #endif
  1307. #endif
  1308.     setvbuf(stdout, IOoutbuf, _IOFBF, sizeof(IOoutbuf));
  1309.     return (1);
  1310. }
  1311.  
  1312. ifopen(filename)
  1313. char *filename;
  1314. {
  1315.     static char IOinbuf[8192];
  1316.  
  1317.     if (filename && !freopen(filename, "rb", stdin)) {
  1318.         perror(filename);
  1319.         return (0);
  1320.     }
  1321. #ifdef O_BINARY
  1322.     setmode(fileno(stdin), O_BINARY);
  1323. #else
  1324. #ifdef __ZTC__
  1325.     stdin->_flag &= ~_IOTRAN;
  1326. #endif
  1327. #endif
  1328.     setvbuf(stdin, IOinbuf, _IOFBF, sizeof(IOinbuf));
  1329.     return (1);
  1330. }
  1331.