home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / gtak212b.zip / SOURCE.ZIP / UTIL / compress.c < prev    next >
C/C++ Source or Header  |  1993-01-20  |  35KB  |  1,309 lines

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