home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / turbo_c / comprs12.arc / COMPRESS.C next >
C/C++ Source or Header  |  1988-08-10  |  63KB  |  1,908 lines

  1. /*
  2.  * Compress - data compression program
  3.  */
  4. #ifndef __TURBOC__
  5. #define min(a,b)        ((a>b) ? b : a)
  6. #endif
  7. /*
  8.  * machine variants which require cc -Dmachine:  pdp11, z8000, pcxt
  9.  */
  10.  
  11. /*
  12.  * Set USERMEM to the maximum amount of physical user memory available
  13.  * in bytes.  USERMEM is used to determine the maximum BITS that can be used
  14.  * for compression.
  15.  *
  16.  * SACREDMEM is the amount of physical memory saved for others; compress
  17.  * will hog the rest.
  18.  */
  19. #ifndef SACREDMEM
  20. #define SACREDMEM       0
  21. #endif
  22.  
  23. #ifndef USERMEM
  24. # define USERMEM        450000  /* default user memory */
  25. #endif
  26.  
  27. #ifdef interdata                /* (Perkin-Elmer) */
  28. #define SIGNED_COMPARE_SLOW     /* signed compare is slower than unsigned */
  29. #endif
  30.  
  31. #ifdef pdp11
  32. # define BITS   12      /* max bits/code for 16-bit machine */
  33. # define NO_UCHAR       /* also if "unsigned char" functions as signed char */
  34. # undef USERMEM
  35. #endif /* pdp11 */      /* don't forget to compile with -i */
  36.  
  37. #ifdef z8000
  38. # define BITS   12
  39. # undef vax             /* weird preprocessor */
  40. # undef USERMEM
  41. #endif /* z8000 */
  42.  
  43. #ifdef __MSDOS__    /* Turbo C for MS-DOS */
  44. #    define MSDOS    /* convert defines to equiv. Microsoft defines */
  45. #    ifdef __COMPACT__
  46. #        define BIG
  47. #    endif
  48. #include <io.h>
  49. #include <string.h>
  50. #include <dos.h>
  51. #include <fcntl.h>
  52. #endif
  53.  
  54. #ifdef MSDOS            /* Microsoft C 3.0 for MS-DOS */
  55. # undef USERMEM
  56. # ifdef BIG             /* then this is a large data compilation */
  57. #  undef DEBUG          /*  DEBUG makes the executible too big */
  58. #  define BITS   16
  59. #  define XENIX_16
  60. # else                  /* this is a small model compilation */
  61. #  define BITS   12
  62. # endif
  63. #else
  64. #undef BIG
  65. #endif /* MSDOS */
  66.  
  67. #ifdef pcxt
  68. # define BITS   12
  69. # undef USERMEM
  70. #endif /* pcxt */
  71.  
  72. #ifdef USERMEM
  73. # if USERMEM >= (433484+SACREDMEM)
  74. #  define PBITS 16
  75. # else
  76. #  if USERMEM >= (229600+SACREDMEM)
  77. #   define PBITS        15
  78. #  else
  79. #   if USERMEM >= (127536+SACREDMEM)
  80. #    define PBITS       14
  81. #   else
  82. #    if USERMEM >= (73464+SACREDMEM)
  83. #     define PBITS      13
  84. #    else
  85. #     define PBITS      12
  86. #    endif
  87. #   endif
  88. #  endif
  89. # endif
  90. # undef USERMEM
  91. #endif /* USERMEM */
  92.  
  93. #ifdef PBITS            /* Preferred BITS for this memory size */
  94. # ifndef BITS
  95. #  define BITS PBITS
  96. # endif BITS
  97. #endif /* PBITS */
  98.  
  99. #if BITS == 16
  100. # define HSIZE  69001           /* 95% occupancy */
  101. #endif
  102. #if BITS == 15
  103. # define HSIZE  35023           /* 94% occupancy */
  104. #endif
  105. #if BITS == 14
  106. # define HSIZE  18013           /* 91% occupancy */
  107. #endif
  108. #if BITS == 13
  109. # define HSIZE  9001            /* 91% occupancy */
  110. #endif
  111. #if BITS <= 12
  112. # define HSIZE  5003            /* 80% occupancy */
  113. #endif
  114.  
  115. #ifdef M_XENIX                  /* Stupid compiler can't handle arrays with */
  116. # if BITS == 16                 /* more than 65535 bytes - so we fake it */
  117. #  define XENIX_16
  118. # else
  119. #  if BITS > 13                 /* Code only handles BITS = 12, 13, or 16 */
  120. #   define BITS 13
  121. #  endif
  122. # endif
  123. #endif
  124.  
  125. /*
  126.  * a code_int must be able to hold 2**BITS values of type int, and also -1
  127.  */
  128. #if BITS > 15
  129. typedef long int        code_int;
  130. #else
  131. typedef int             code_int;
  132. #endif
  133.  
  134. #ifdef SIGNED_COMPARE_SLOW
  135. typedef unsigned long int count_int;
  136. typedef unsigned short int count_short;
  137. #else
  138. typedef long int          count_int;
  139. #endif
  140.  
  141. #ifdef NO_UCHAR
  142.  typedef char   char_type;
  143. #else
  144.  typedef        unsigned char   char_type;
  145. #endif /* UCHAR */
  146. char_type magic_header[] = { "\037\235" };      /* 1F 9D */
  147.  
  148. /* Defines for third byte of header */
  149. #define BIT_MASK        0x1f
  150. #define BLOCK_MASK      0x80
  151. #define FB_MASK            0x20
  152. /* Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
  153.    a fourth header byte (for expansion).
  154. */
  155. /*    0x20 now used for that purpose... fourth byte is used under DOS to
  156.     hold filename char that is replaced by Z in compressed version */
  157. #define INIT_BITS 9                     /* initial number of bits/code */
  158.  
  159. #define UpCase(C) ('a' <= (C) && (C) <= 'z' ? (C) + 'A' - 'a' : (C))
  160.  
  161. /* compress.c:    Changes made for Turbo C compatibility and to enhance
  162.                 functionality under DOS : 4/88, 5/88
  163.                 Revisions by John H. DuBois III (spcecdt@ucscb.ucsc.edu)
  164.  
  165.     Turbo C compatibility changes: Translate Turbo C memory model defines
  166.         to MSC defines, so that #ifdef's that expect MSC defines will work;
  167.         add function prototypes, casts, expression parentheses,
  168.         void function types, etc. to minimize warning messages; include extra
  169.         headers, use different ctrl-brk handling, filestat calls, etc. for
  170.         compatibility.
  171.         Hopefully will still compile under MSC.  Not tested.
  172.         Could only get it to compile in small memory model (12 bit compression).
  173.     DOS functionality changes: The check of argv[0] to determine what function
  174.         is to be performed (compress, zcat, uncompress) failed under several
  175.         cicumstances.  If the name was given as a drive specifier and name
  176.         (i.e., C:ZCAT.EXE), or if forward slashes were used instead of
  177.         backslashes as path separators (as allowed by some shells, like 
  178.         MKS sh.exe), the tail of
  179.         the path would not be separated correctly, so recognition of the name
  180.         would fail.  Also, if the name was not all in caps, or if the name was
  181.         not truncated to 8 chars (i.e., "uncompress.exe") (again as allowed by
  182.         some shells), it would not be recognized.  Interpretation of argv[0]
  183.         changed to handle these cases correctly.
  184.         The loss of one or two characters of the filename extension (when they
  185.         are replaced by Z or XZ) can be annoying.  Therefore, the XZ extension
  186.         is no longer used.  If the original extension is 0, 1, or 2 characters 
  187.         long a Z is added to the end.  If it is 3 characters the last character
  188.         is replaced with a Z and the old character is
  189.         stored in the file as a fourth byte of the header.  0x20 is ORed into
  190.         the third byte of the header as a flag to indicate this.  When a file
  191.         with that bit of the header set is decompressed, the Z is replaced with
  192.         the fourth byte of the header to restore the original filename.  Files
  193.         compressed with the old compress are compatible with this, though if
  194.         the extension was replaced with .?XZ the X will remain after
  195.         decompression.  Although it was suggested in the comments of this
  196.         program that mask 0x20 be used to
  197.         indicate a fourth header byte, the old compress does not recognize
  198.         this, so compressed files that use the fourth byte are not backward-
  199.         compatible.  To create a compressed file that can be decompressed by
  200.         the old compress, make sure that the extension is not more than two
  201.         characters long or use the -N flag, so that a fourth header byte will
  202.         not be used.  
  203. */
  204. /*
  205.  * compress.c - File compression ala IEEE Computer, June 1984.
  206.  *
  207.  * Authors:     Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
  208.  *              Jim McKie               (decvax!mcvax!jim)
  209.  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
  210.  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
  211.  *              James A. Woods          (decvax!ihnp4!ames!jaw)
  212.  *              Joe Orost               (decvax!vax135!petsd!joe)
  213.  *
  214.  * $Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $
  215.  * $Log:        compress.c,v $
  216.  * Revision 4.0  85/07/30  12:50:00  joe
  217.  * Removed ferror() calls in output routine on every output except first.
  218.  * Prepared for release to the world.
  219.  * 
  220.  * Revision 3.6  85/07/04  01:22:21  joe
  221.  * Remove much wasted storage by overlaying hash table with the tables
  222.  * used by decompress: tab_suffix[1<<BITS], stack[8000].  Updated USERMEM
  223.  * computations.  Fixed dump_tab() DEBUG routine.
  224.  *
  225.  * Revision 3.5  85/06/30  20:47:21  jaw
  226.  * Change hash function to use exclusive-or.  Rip out hash cache.  These
  227.  * speedups render the megamemory version defunct, for now.  Make decoder
  228.  * stack global.  Parts of the RCS trunks 2.7, 2.6, and 2.1 no longer apply.
  229.  *
  230.  * Revision 3.4  85/06/27  12:00:00  ken
  231.  * Get rid of all floating-point calculations by doing all compression ratio
  232.  * calculations in fixed point.
  233.  *
  234.  * Revision 3.3  85/06/24  21:53:24  joe
  235.  * Incorporate portability suggestion for M_XENIX.  Got rid of text on #else
  236.  * and #endif lines.  Cleaned up #ifdefs for vax and interdata.
  237.  *
  238.  * Revision 3.2  85/06/06  21:53:24  jaw
  239.  * Incorporate portability suggestions for Z8000, IBM PC/XT from mailing list.
  240.  * Default to "quiet" output (no compression statistics).
  241.  *
  242.  * Revision 3.1  85/05/12  18:56:13  jaw
  243.  * Integrate decompress() stack speedups (from early pointer mods by McKie).
  244.  * Repair multi-file USERMEM gaffe.  Unify 'force' flags to mimic semantics
  245.  * of SVR2 'pack'.  Streamline block-compress table clear logic.  Increase
  246.  * output byte count by magic number size.
  247.  * 
  248.  * Revision 3.0   84/11/27  11:50:00  petsd!joe
  249.  * Set HSIZE depending on BITS.  Set BITS depending on USERMEM.  Unrolled
  250.  * loops in clear routines.  Added "-C" flag for 2.0 compatibility.  Used
  251.  * unsigned compares on Perkin-Elmer.  Fixed foreground check.
  252.  *
  253.  * Revision 2.7   84/11/16  19:35:39  ames!jaw
  254.  * Cache common hash codes based on input statistics; this improves
  255.  * performance for low-density raster images.  Pass on #ifdef bundle
  256.  * from Turkowski.
  257.  *
  258.  * Revision 2.6   84/11/05  19:18:21  ames!jaw
  259.  * Vary size of hash tables to reduce time for small files.
  260.  * Tune PDP-11 hash function.
  261.  *
  262.  * Revision 2.5   84/10/30  20:15:14  ames!jaw
  263.  * Junk chaining; replace with the simpler (and, on the VAX, faster)
  264.  * double hashing, discussed within.  Make block compression standard.
  265.  *
  266.  * Revision 2.4   84/10/16  11:11:11  ames!jaw
  267.  * Introduce adaptive reset for block compression, to boost the rate
  268.  * another several percent.  (See mailing list notes.)
  269.  *
  270.  * Revision 2.3   84/09/22  22:00:00  petsd!joe
  271.  * Implemented "-B" block compress.  Implemented REVERSE sorting of tab_next.
  272.  * Bug fix for last bits.  Changed fwrite to putchar loop everywhere.
  273.  *
  274.  * Revision 2.2   84/09/18  14:12:21  ames!jaw
  275.  * Fold in news changes, small machine typedef from thomas,
  276.  * #ifdef interdata from joe.
  277.  *
  278.  * Revision 2.1   84/09/10  12:34:56  ames!jaw
  279.  * Configured fast table lookup for 32-bit machines.
  280.  * This cuts user time in half for b <= FBITS, and is useful for news batching
  281.  * from VAX to PDP sites.  Also sped up decompress() [fwrite->putc] and
  282.  * added signal catcher [plus beef in writeerr()] to delete effluvia.
  283.  *
  284.  * Revision 2.0   84/08/28  22:00:00  petsd!joe
  285.  * Add check for foreground before prompting user.  Insert maxbits into
  286.  * compressed file.  Force file being uncompressed to end with ".Z".
  287.  * Added "-c" flag and "zcat".  Prepared for release.
  288.  *
  289.  * Revision 1.10  84/08/24  18:28:00  turtlevax!ken
  290.  * Will only compress regular files (no directories), added a magic number
  291.  * header (plus an undocumented -n flag to handle old files without headers),
  292.  * added -f flag to force overwriting of possibly existing destination file,
  293.  * otherwise the user is prompted for a response.  Will tack on a .Z to a
  294.  * filename if it doesn't have one when decompressing.  Will only replace
  295.  * file if it was compressed.
  296.  *
  297.  * Revision 1.9  84/08/16  17:28:00  turtlevax!ken
  298.  * Removed scanargs(), getopt(), added .Z extension and unlimited number of
  299.  * filenames to compress.  Flags may be clustered (-Ddvb12) or separated
  300.  * (-D -d -v -b 12), or combination thereof.  Modes and other status is
  301.  * copied with copystat().  -O bug for 4.2 seems to have disappeared with
  302.  * 1.8.
  303.  *
  304.  * Revision 1.8  84/08/09  23:15:00  joe
  305.  * Made it compatible with vax version, installed jim's fixes/enhancements
  306.  *
  307.  * Revision 1.6  84/08/01  22:08:00  joe
  308.  * Sped up algorithm significantly by sorting the compress chain.
  309.  *
  310.  * Revision 1.5  84/07/13  13:11:00  srd
  311.  * Added C version of vax asm routines.  Changed structure to arrays to
  312.  * save much memory.  Do unsigned compares where possible (faster on
  313.  * Perkin-Elmer)
  314.  *
  315.  * Revision 1.4  84/07/05  03:11:11  thomas
  316.  * Clean up the code a little and lint it.  (Lint complains about all
  317.  * the regs used in the asm, but I'm not going to "fix" this.)
  318.  *
  319.  * Revision 1.3  84/07/05  02:06:54  thomas
  320.  * Minor fixes.
  321.  *
  322.  * Revision 1.2  84/07/05  00:27:27  thomas
  323.  * Add variable bit length output.
  324.  *
  325.  */
  326. static char rcs_ident[] = "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $";
  327.  
  328. #include <stdio.h>
  329. #include <ctype.h>
  330. #include <signal.h>
  331.  
  332. #ifndef __TURBOC__
  333. #include <sys/types.h>
  334. #endif
  335.  
  336. #include <sys/stat.h>
  337.  
  338. #ifdef MSDOS
  339. #include <stdlib.h>
  340. #endif
  341.  
  342. #ifdef __MSDOS__    /* Prototypes for Turbo C */
  343. void Usage(void);
  344. void version(void);
  345. void compress(char OldChar);
  346. void output(code_int code);
  347. code_int getcode(void);
  348. char *rindex(char *s,char c);
  349. void printcodes(void);
  350. void dump_tab(void);
  351. int in_stack(register c, register stack_top);
  352. void writeerr(void);
  353. void copystat(char *ifname,char *ofname);
  354. int c_break(void);
  355. void cl_block (void);
  356. void cl_hash(register count_int hsize);
  357. void prratio(FILE *stream,long num,long den);
  358. void version(void);
  359. char *PathTail(char *Path);
  360. char *strrpbrk(char *S,char *Chars);
  361. void decompress(void);
  362. #endif
  363.  
  364. #define ARGVAL() (*++(*argv) || (--argc && *++argv))
  365.  
  366. int n_bits;                             /* number of bits/code */
  367. int maxbits = BITS;                     /* user settable max # bits/code */
  368. code_int maxcode;                       /* maximum code, given n_bits */
  369. code_int maxmaxcode = (code_int)1 << BITS; /* should NEVER generate this code */
  370. #ifdef COMPATIBLE               /* But wrong! */
  371. # define MAXCODE(n_bits)        ((code_int) 1 << (n_bits) - 1)
  372. #else
  373. # define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
  374. #endif /* COMPATIBLE */
  375.  
  376. #ifdef XENIX_16
  377. # ifdef MSDOS
  378.  
  379. count_int far htab0[8192];
  380. count_int far htab1[8192];
  381. count_int far htab2[8192];
  382. count_int far htab3[8192];
  383. count_int far htab4[8192];
  384. count_int far htab5[8192];
  385. count_int far htab6[8192];
  386. count_int far htab7[8192];
  387. count_int far htab8[HSIZE-65536];
  388. count_int far * htab[9] = {
  389.         htab0, htab1, htab2, htab3, htab4, htab5, htab6, htab7, htab8 };
  390.  
  391. unsigned short far code0tab[16384];
  392. unsigned short far code1tab[16384];
  393. unsigned short far code2tab[16384];
  394. unsigned short far code3tab[16384];
  395. unsigned short far code4tab[16384];
  396. unsigned short far * codetab[5] = {
  397.         code0tab, code1tab, code2tab, code3tab, code4tab };
  398.  
  399. # else
  400.  
  401. count_int htab0[8192];
  402. count_int htab1[8192];
  403. count_int htab2[8192];
  404. count_int htab3[8192];
  405. count_int htab4[8192];
  406. count_int htab5[8192];
  407. count_int htab6[8192];
  408. count_int htab7[8192];
  409. count_int htab8[HSIZE-65536];
  410. count_int * htab[9] = {
  411.         htab0, htab1, htab2, htab3, htab4, htab5, htab6, htab7, htab8 };
  412.  
  413. unsigned short code0tab[16384];
  414. unsigned short code1tab[16384];
  415. unsigned short code2tab[16384];
  416. unsigned short code3tab[16384];
  417. unsigned short code4tab[16384];
  418. unsigned short * codetab[5] = {
  419.         code0tab, code1tab, code2tab, code3tab, code4tab };
  420.  
  421. # endif /* MSDOS */
  422.  
  423. #define htabof(i)       (htab[(i) >> 13][(i) & 0x1fff])
  424. #define codetabof(i)    (codetab[(i) >> 14][(i) & 0x3fff])
  425.  
  426. #else   /* Normal machine */
  427. count_int htab [HSIZE];
  428. unsigned short codetab [HSIZE];
  429. #define htabof(i)       htab[i]
  430. #define codetabof(i)    codetab[i]
  431.  
  432. #endif  /* XENIX_16 */
  433. code_int hsize = HSIZE;                 /* for dynamic table sizing */
  434. count_int fsize;
  435.  
  436. /*
  437.  * To save much memory, we overlay the table used by compress() with those
  438.  * used by decompress().  The tab_prefix table is the same size and type
  439.  * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
  440.  * get this from the beginning of htab.  The output stack uses the rest
  441.  * of htab, and contains characters.  There is plenty of room for any
  442.  * possible stack (stack used to be 8000 characters).
  443.  */
  444.  
  445. #define tab_prefixof(i) codetabof(i)
  446.  
  447. #ifdef XENIX_16
  448. # ifdef MSDOS
  449. #  define tab_suffixof(i)       ((char_type far *)htab[(i)>>15])[(i) & 0x7fff]
  450. #  define de_stack              ((char_type far *)(htab2))
  451. # else
  452. #  define tab_suffixof(i)       ((char_type *)htab[(i)>>15])[(i) & 0x7fff]
  453. #  define de_stack              ((char_type *)(htab2))
  454. # endif /* MSDOS */
  455. #else   /* Normal machine */
  456. # define tab_suffixof(i)        ((char_type *)(htab))[i]
  457. # define de_stack               ((char_type *)&tab_suffixof((code_int)1<<BITS))
  458. #endif  /* XENIX_16 */
  459.  
  460. code_int free_ent = 0;                  /* first unused entry */
  461. int exit_stat = 0;
  462.  
  463. code_int getcode();
  464.  
  465. void Usage() {
  466. #ifdef DEBUG
  467.  
  468. # ifdef MSDOS
  469.     fprintf(stderr,"Usage: compress [-cdDfivV] [-b maxbits] [file ...]\n");
  470.     fprintf(stderr,"-c: Write output on stdout, don't remove original.\n");
  471.     fprintf(stderr,"-d: If given, decompression is done instead.\n");
  472.     fprintf(stderr,"-f: Forces output file to be generated, even if one already exists,\n");
  473.     fprintf(stderr,"    and even if no space is saved by compressing.  If -f is not used,\n");
  474.     fprintf(stderr,"    the user will be prompted if stdin is a tty, otherwise, the\n");
  475.     fprintf(stderr,"    output file will not be overwritten.\n");
  476.     fprintf(stderr,"-i: Image mode (defined only under MS-DOS).  Prevents conversion\n");
  477.     fprintf(stderr,"    between UNIX text representation (LF line termination) in\n");
  478.     fprintf(stderr,"    compressed form and MS-DOS text representation (CR-LF line\n");
  479.     fprintf(stderr,"    termination) in uncompressed form.  Useful with non-text files.\n");
  480.     fprintf(stderr,"-v: Write compression statistics\n");
  481.     fprintf(stderr,"-V: Write version and compilation options.\n");
  482.     fprintf(stderr,"-b: Parameter limits the max number of bits/code.\n");
  483.     fprintf(stderr,"file ...:   Files to be compressed.  If none specified, stdin is used.\n");
  484.     fprintf(stderr,"\nOutputs:\n");
  485.     fprintf(stderr,"file.Z: Compressed form of file with same mode, owner, and utimes or\n");
  486.     fprintf(stderr,"        stdout (if stdin used as input) When filenames are given,\n");
  487.     fprintf(stderr,"        replaces with the compressed version (.Z suffix) only if the\n");
  488.     fprintf(stderr,"        file decreases in size.\n");
  489. # else
  490.     fprintf(stderr,"Usage: compress [-cdDfvV] [-b maxbits] [file ...]\n");
  491. # endif /* MSDOS */
  492.  
  493. }
  494. int debug = 0;
  495. #else
  496.  
  497. # ifdef MSDOS
  498.     fprintf(stderr,"Usage: compress [-cdfivV] [-b maxbits] [file ...]\n");
  499.     fprintf(stderr,"-c: Write output on stdout, don't remove original.\n");
  500.     fprintf(stderr,"-d: If given, decompression is done instead.\n");
  501.     fprintf(stderr,"-f: Forces output file to be generated, even if one already exists,\n");
  502.     fprintf(stderr,"    and even if no space is saved by compressing.  If -f is not used,\n");
  503.     fprintf(stderr,"    the user will be prompted if stdin is a tty, otherwise, the\n");
  504.     fprintf(stderr,"    output file will not be overwritten.\n");
  505.     fprintf(stderr,"-i: Image mode (defined only under MS-DOS).  Prevents conversion\n");
  506.     fprintf(stderr,"    between UNIX text representation (LF line termination) in\n");
  507.     fprintf(stderr,"    compressed form and MS-DOS text representation (CR-LF line\n");
  508.     fprintf(stderr,"    termination) in uncompressed form.  Useful with non-text files.\n");
  509.     fprintf(stderr,"-v: Write compression statistics\n");
  510.     fprintf(stderr,"-V: Write version and compilation options.\n");
  511.     fprintf(stderr,"-b: Parameter limits the max number of bits/code.\n");
  512.     fprintf(stderr,"file ...:   Files to be compressed.  If none specified, stdin is used.\n");
  513.     fprintf(stderr,"\nOutputs:\n");
  514.     fprintf(stderr,"file.Z: Compressed form of file with same mode, owner, and utimes or\n");
  515.     fprintf(stderr,"        stdout (if stdin used as input) When filenames are given,\n");
  516.     fprintf(stderr,"        replaces with the compressed version (.Z suffix) only if the\n");
  517.     fprintf(stderr,"        file decreases in size.\n");
  518. # else
  519.     fprintf(stderr,"Usage: compress [-cdfvV] [-b maxbits] [file ...]\n");
  520. # endif /* MSDOS */
  521.  
  522. }
  523. #endif /* DEBUG */
  524. int nomagic = 0;        /* Use a 3-byte magic number header, unless old file */
  525. int zcat_flg = 0;       /* Write output on stdout, suppress messages */
  526. int quiet = 1;          /* don't tell me about compression */
  527.  
  528. /*
  529.  * block compression parameters -- after all codes are used up,
  530.  * and compression rate changes, start over.
  531.  */
  532. int block_compress = BLOCK_MASK;
  533. int clear_flg = 0;
  534. long int ratio = 0;
  535. #define CHECK_GAP 10000 /* ratio check interval */
  536. count_int checkpoint = CHECK_GAP;
  537. /*
  538.  * the next two codes should not be changed lightly, as they must not
  539.  * lie within the contiguous general code space.
  540.  */ 
  541. #define FIRST   257     /* first free entry */
  542. #define CLEAR   256     /* table clear output code */
  543.  
  544. int force = 0;
  545. char ofname [100];
  546.                   
  547. #ifdef MSDOS
  548. int image = 2;          /* 1 <=> image (binary) mode; 2 <=> text mode */
  549. int nocharsave = 0;        /* set to 1 if -N flag (no char save) is given */
  550. #endif
  551.  
  552. #ifdef DEBUG
  553. int verbose = 0;
  554. #endif /* DEBUG */
  555. int (*bgnd_flag)();
  556.  
  557. int do_decomp = 0;
  558.  
  559. /*****************************************************************
  560.  * TAG( main )
  561.  *
  562.  * Algorithm from "A Technique for High Performance Data Compression",
  563.  * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
  564.  *
  565.  * Usage: compress [-cdfivV] [-b bits] [file ...]
  566.  * Inputs:
  567.  *
  568.  *      -c:         Write output on stdout, don't remove original.
  569.  *
  570.  *      -d:         If given, decompression is done instead.
  571.  *
  572.  *      -f:         Forces output file to be generated, even if one already
  573.  *                  exists, and even if no space is saved by compressing.
  574.  *                  If -f is not used, the user will be prompted if stdin is
  575.  *                  a tty, otherwise, the output file will not be overwritten.
  576.  *
  577.  *      -i:         Image mode (defined only under MS-DOS).  Prevents
  578.  *                  conversion between UNIX text representation (LF line
  579.  *                  termination) in compressed form and MS-DOS text
  580.  *                  representation (CR-LF line termination) in uncompressed
  581.  *                  form.  Useful with non-text files.
  582.  *
  583.  *        -N:            Do not save extension char that is replaced with "Z" as
  584.  *                    a fourth header byte (so that file will be compatible
  585.  *                    with old compress).  MSDOS only.
  586.  *
  587.  *      -v:         Write compression statistics
  588.  *
  589.  *      -V:         Write version and compilation options.
  590.  *
  591.  *      -b:         Parameter limits the max number of bits/code.
  592.  *
  593.  *      file ...:   Files to be compressed.  If none specified, stdin
  594.  *                  is used.
  595.  * Outputs:
  596.  *      file.Z:     Compressed form of file with same mode, owner, and utimes
  597.  *      or stdout   (if stdin used as input)
  598.  *
  599.  * Assumptions:
  600.  *      When filenames are given, replaces with the compressed version
  601.  *      (.Z suffix) only if the file decreases in size.
  602.  * Algorithm:
  603.  *      Modified Lempel-Ziv method (LZW).  Basically finds common
  604.  * substrings and replaces them with a variable size code.  This is
  605.  * deterministic, and can be done on the fly.  Thus, the decompression
  606.  * procedure needs no input table, but tracks the way the table was built.
  607.  */
  608.  
  609. void main( argc, argv )
  610. register int argc; char **argv;
  611. {
  612.     int overwrite = 0;  /* Do not overwrite unless given -f flag */
  613.     char tempname[100];
  614.     char **filelist, **fileptr;
  615.     char *cp, *rindex();
  616.     struct stat statbuf;
  617.     int FourthByte;        /* Whether header has a fourth byte */
  618.     char OldChar = '\0';    /* Char in DOS filename overwritten by Z */
  619. #ifndef __TURBOC__
  620.     extern onintr();
  621. #endif
  622.  
  623. #ifdef MSDOS
  624.     char *sufp;
  625. #else
  626.     extern oops();
  627. #endif
  628.  
  629. #ifdef __TURBOC__
  630.     ctrlbrk(c_break);
  631. #else
  632. #    ifndef MSDOS
  633.         if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
  634. #    endif
  635.             signal ( SIGINT, onintr );
  636. #    ifndef MSDOS
  637.             signal ( SIGSEGV, oops );
  638.         }
  639. #    endif
  640. #endif
  641.  
  642. #ifdef COMPATIBLE
  643.     nomagic = 1;        /* Original didn't have a magic number */
  644. #endif /* COMPATIBLE */
  645.  
  646.     filelist = fileptr = (char **)(malloc(argc * sizeof(*argv)));
  647.     *filelist = NULL;
  648.  
  649.     cp = PathTail(argv[0]);
  650.  
  651. #ifdef MSDOS
  652.     if(UpCase(*cp) == 'U') {
  653. #else
  654.     if(strcmp(cp, "uncompress") == 0) {
  655. #endif
  656.  
  657.         do_decomp = 1;
  658.  
  659. #ifdef MSDOS
  660.     } else if(UpCase(*cp) == 'Z') {
  661. #else
  662.     } else if(strcmp(cp, "zcat") == 0) {
  663. #endif
  664.  
  665.         do_decomp = 1;
  666.         zcat_flg = 1;
  667.     }
  668.  
  669. #ifdef BSD4_2
  670.     /* 4.2BSD dependent - take it out if not */
  671.     setlinebuf( stderr );
  672. #endif /* BSD4_2 */
  673.  
  674.     /* Argument Processing
  675.      * All flags are optional.
  676.      * -D => debug
  677.      * -V => print Version; debug verbose
  678.      * -d => do_decomp
  679.      * -v => unquiet
  680.      * -f => force overwrite of output file
  681.      * -n => no header: useful to uncompress old files
  682.      * -b maxbits => maxbits.  If -b is specified, then maxbits MUST be
  683.      *      given also.
  684.      * -c => cat all output to stdout
  685.      * -C => generate output compatible with compress 2.0.
  686.      * -N => (MSDOS): do not save replaced extension char in header
  687.      * -i => (MSDOS): compress/uncompress as binary
  688.      * if a string is left, must be an input filename.
  689.      */
  690.     for (argc--, argv++; argc > 0; argc--, argv++) {
  691.         if (**argv == '-') {    /* A flag argument */
  692.             while (*++(*argv)) {        /* Process all flags in this arg */
  693.                 switch (**argv) {
  694. #ifdef DEBUG
  695.                     case 'D':
  696.                         debug = 1;
  697.                         break;
  698.                     case 'V':
  699.                         verbose = 1;
  700.                         version();
  701.                         break;
  702. #else
  703.                     case 'V':
  704.                         version();
  705.                         break;
  706. #endif /* DEBUG */
  707.  
  708. #ifdef MSDOS
  709.                     case 'i':
  710.                         image = 1;
  711.                         break;
  712.                     case 'N':
  713.                         nocharsave = 1;
  714.                         break;
  715. #endif
  716.  
  717.                     case 'v':
  718.                         quiet = 0;
  719.                         break;
  720.                     case 'd':
  721.                         do_decomp = 1;
  722.                         break;
  723.                     case 'f':
  724.                     case 'F':
  725.                         overwrite = 1;
  726.                         force = 1;
  727.                         break;
  728.                     case 'n':
  729.                         nomagic = 1;
  730.                         break;
  731.                     case 'C':
  732.                         block_compress = 0;
  733.                         break;
  734.                     case 'b':
  735.                         if (!ARGVAL()) {
  736.                             fprintf(stderr, "Missing maxbits\n");
  737.                             Usage();
  738.                             exit(1);
  739.                         }
  740.                         maxbits = atoi(*argv);
  741.                         goto nextarg;
  742.                     case 'c':
  743.                         zcat_flg = 1;
  744.                         break;
  745.                     case 'q':
  746.                         quiet = 1;
  747.                         break;
  748.                     default:
  749.                         fprintf(stderr, "Unknown flag: '%c'; ", **argv);
  750.                         Usage();
  751.                         exit(1);
  752.                 }
  753.             }
  754.         }
  755.         else {          /* Input file name */
  756.             *fileptr++ = *argv; /* Build input file list */
  757.             *fileptr = NULL;
  758.             /* process nextarg; */
  759.         }
  760.         nextarg: continue;
  761.     }
  762.  
  763.     if(maxbits < INIT_BITS) maxbits = INIT_BITS;
  764.     if (maxbits > BITS) maxbits = BITS;
  765.     maxmaxcode = (code_int) 1 << maxbits;
  766.  
  767.     if (*filelist != NULL) {
  768.         for (fileptr = filelist; *fileptr; fileptr++) {
  769.             exit_stat = 0;
  770.             if (do_decomp != 0) {                       /* DECOMPRESSION */
  771.  
  772. #ifdef MSDOS
  773.                 /* Check for .*Z suffix; add one if necessary */
  774.                 cp = *fileptr + strlen(*fileptr) - 1;
  775.                 if (rindex(*fileptr,'.') == NULL || UpCase (*cp) != 'Z') {
  776.                     strcpy(tempname, *fileptr);
  777.                     if ((cp=rindex(tempname,'.')) == NULL)
  778.                         strcat(tempname, ".Z");
  779.                     else {
  780.                         if (*(++cp) != '\0' && *(++cp) != '\0')
  781.                             *(++cp) = '\0';
  782.                         strcat(tempname, "Z");
  783.                     }
  784.                     *fileptr = tempname;
  785.                 }
  786. #else
  787.                 /* Check for .Z suffix */
  788.                 if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) {
  789.                     /* No .Z: tack one on */
  790.                     strcpy(tempname, *fileptr);
  791.                     strcat(tempname, ".Z");
  792.                     *fileptr = tempname;
  793.                 }
  794. #endif /*MSDOS */
  795.  
  796.                 /* Open input file for decompression */
  797.  
  798. #ifdef MSDOS
  799.                 if ((freopen(*fileptr, "rb", stdin)) == NULL) {
  800. #else
  801.                 if ((freopen(*fileptr, "r", stdin)) == NULL) {
  802. #endif
  803.  
  804.                         perror(*fileptr); continue;
  805.                 }
  806.                 /* Check the magic number */
  807.                 if (nomagic == 0) {
  808.                     if ((getchar() != (magic_header[0] & 0xFF))
  809.                      || (getchar() != (magic_header[1] & 0xFF))) {
  810.                         fprintf(stderr, "%s: not in compressed format\n",
  811.                             *fileptr);
  812.                     continue;
  813.                     }
  814.                     maxbits = getchar();        /* set -b from file */
  815.                     block_compress = maxbits & BLOCK_MASK;
  816.                     FourthByte = maxbits & FB_MASK;
  817.                     maxbits &= BIT_MASK;
  818.                     maxmaxcode = (code_int) 1 << maxbits;
  819.                     if(maxbits > BITS) {
  820.                         fprintf(stderr,
  821.                         "%s: compressed with %d bits, can only handle %d bits\n",
  822.                         *fileptr, maxbits, BITS);
  823.                         continue;
  824.                     }
  825.                 }
  826.                 /* Generate output filename */
  827.                 strcpy(ofname, *fileptr);
  828. #ifdef MSDOS
  829.                 if (FourthByte) {   /* Replace Z with original character */
  830.                     ofname[strlen(*fileptr) - 1] = getchar();
  831.                     if (!zcat_flg)
  832.                         fprintf(stderr,"Restoring filename char.\n");
  833.                 }
  834.                 else 
  835.                     if ((ofname + strlen(*fileptr) - 2) != ".")
  836.                         ofname[strlen(*fileptr) - 1] = '\0';  /* Strip off Z */
  837.                     else
  838. #endif
  839.                     ofname[strlen(*fileptr) - 2] = '\0';  /* Strip off .Z */
  840.             } 
  841.             else {                                    /* COMPRESSION */
  842.  
  843. #ifdef MSDOS
  844.                 cp = *fileptr + strlen(*fileptr) - 1;
  845.                 if (*cp == 'Z' || *cp == 'z') {
  846.                     fprintf(stderr,"%s: already has %s suffix -- no change\n",
  847.                         *fileptr,cp);
  848. #else
  849.                 if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0) {
  850.                     fprintf(stderr, "%s: already has .Z suffix -- no change\n",
  851.                         *fileptr);
  852. #endif /* MSDOS */
  853.  
  854.                     continue;
  855.                 }
  856.                 /* Open input file for compression */
  857.  
  858. #ifdef MSDOS
  859.                 if ((freopen(*fileptr, image == 2 ? "rt" : "rb", stdin))
  860.                     == NULL) {
  861. #else
  862.                 if ((freopen(*fileptr, "r", stdin)) == NULL) {
  863. #endif
  864.  
  865.                     perror(*fileptr); continue;
  866.                 }
  867.                 stat ( *fileptr, &statbuf );
  868.                 fsize = (long) statbuf.st_size;
  869.                 /*
  870.                  * tune hash table size for small files -- ad hoc,
  871.                  * but the sizes match earlier #defines, which
  872.                  * serve as upper bounds on the number of output codes. 
  873.                  */
  874.                 hsize = HSIZE;
  875.                 if ( fsize < (1 << 12) )
  876.                     hsize = (code_int) min ( 5003L, HSIZE );
  877.                 else if ( fsize < (1L << 13) )
  878.                     hsize = (code_int) min ( 9001L, HSIZE );
  879.                 else if ( fsize < (1L << 14) )
  880.                     hsize = (code_int) min ( 18013L, HSIZE );
  881.                 else if ( fsize < (1L << 15) )
  882.                     hsize = (code_int) min ( 35023L, HSIZE );
  883.                 else if ( fsize < 47000L )
  884.                     hsize = (code_int) min ( 50021L, HSIZE );
  885.  
  886.                 /* Generate output filename */
  887.                 strcpy(ofname, *fileptr);
  888. #ifndef BSD4_2          /* Short filenames */
  889.                 cp = PathTail(ofname);
  890. # ifdef MSDOS
  891.                 if (zcat_flg == 0 && (sufp = rindex(cp, '.')) != NULL &&
  892.                     strlen(sufp) > 3) fprintf(stderr,
  893.                     "%s: part of filename extension will be replaced by Z\n",
  894.                     cp);
  895. # else
  896.                 if (strlen(cp) > 12) {
  897.                     fprintf(stderr,"%s: filename too long to tack on .Z\n",cp);
  898.                     continue;
  899.                 }
  900. # endif
  901. #endif  /* BSD4_2               Long filenames allowed */
  902.                                                          
  903. #ifdef MSDOS
  904.                 if ((cp = rindex(ofname, '.')) == NULL)
  905.                     strcat(ofname, ".Z");
  906.                 else {
  907.                     if (strlen(cp) > 3) {
  908.                         if (!nocharsave)
  909.                             OldChar = cp[3];
  910.                         cp[3] = '\0';
  911.                     }
  912.                    strcat(ofname, "Z");
  913.                 }
  914. #else
  915.                 strcat(ofname, ".Z");
  916. #endif /* MSDOS */
  917.  
  918.             } /* Compression */
  919.             /* Check for overwrite of existing file */
  920.             if (overwrite == 0 && zcat_flg == 0) {
  921.                 if (stat(ofname, &statbuf) == 0) {
  922.                     char response[2];
  923.                     response[0] = 'n';
  924.                     fprintf(stderr, "%s already exists;", ofname);
  925. #ifndef MSDOS
  926.                     if (foreground()) {
  927. #endif
  928.                         fprintf(stderr,
  929.                             " do you wish to overwrite %s (y or n)? ", ofname);
  930.                         fflush(stderr);
  931.                         read(2, response, 2);
  932.                         while (response[1] != '\n') {
  933.                             if (read(2, response+1, 1) < 0) {   /* Ack! */
  934.                                 perror("stderr"); break;
  935.                             }
  936.                         }
  937. #ifndef MSDOS
  938.                   }
  939. #endif
  940.                     if (response[0] != 'y') {
  941.                         fprintf(stderr, "\tnot overwritten\n");
  942.                         continue;
  943.                     }
  944.                 }
  945.             }
  946.             if(zcat_flg == 0) {         /* Open output file */
  947.  
  948. #ifdef MSDOS
  949.                 if (freopen(ofname, do_decomp && image == 2 ? "wt" : "wb",
  950.                     stdout) == NULL) {
  951. #else            
  952.                 if (freopen(ofname, "w", stdout) == NULL) {
  953. #endif
  954.  
  955.                     perror(ofname); continue;
  956.                 }
  957.                 if(!quiet)
  958.                         fprintf(stderr, "%s: ", *fileptr);
  959.             }
  960.  
  961.             /* Actually do the compression/decompression */
  962.             if (do_decomp == 0) compress(OldChar);
  963. #ifndef DEBUG
  964.             else                        decompress();
  965. #else
  966.             else if (debug == 0)        decompress();
  967.             else                        printcodes();
  968.             if (verbose)                dump_tab();
  969. #endif /* DEBUG */
  970.             if(zcat_flg == 0) {
  971.                 copystat(*fileptr, ofname);     /* Copy stats */
  972.                 if((exit_stat == 1) || (!quiet))
  973.                         putc('\n', stderr);
  974.             }
  975.         }
  976.     } else {            /* Standard input */
  977.         if (do_decomp == 0) {
  978.                 compress('\0');
  979. #ifdef DEBUG
  980.                 if(verbose)             dump_tab();
  981. #endif /* DEBUG */
  982.                 if(!quiet)
  983.                         putc('\n', stderr);
  984.         } else {
  985.             /* Check the magic number */
  986.             if (nomagic == 0) {
  987.                 if ((getchar()!=(magic_header[0] & 0xFF))
  988.                  || (getchar()!=(magic_header[1] & 0xFF))) {
  989.                     fprintf(stderr, "stdin: not in compressed format\n");
  990.                     exit(1);
  991.                 }
  992.                 maxbits = getchar();    /* set -b from file */
  993.                 block_compress = maxbits & BLOCK_MASK;
  994.                 if (maxbits & FB_MASK)
  995.                     getchar();
  996.                 maxbits &= BIT_MASK;
  997.                 maxmaxcode = (code_int) 1 << maxbits;
  998.                 fsize = 100000L;         /* assume stdin large for USERMEM */
  999.                 if(maxbits > BITS) {
  1000.                         fprintf(stderr,
  1001.                         "stdin: compressed with %d bits, can only handle %d bits\n",
  1002.                         maxbits, BITS);
  1003.                         exit(1);
  1004.                 }
  1005.             }
  1006. #ifndef DEBUG
  1007.             decompress();
  1008. #else
  1009.             if (debug == 0)     decompress();
  1010.             else                printcodes();
  1011.             if (verbose)        dump_tab();
  1012. #endif /* DEBUG */
  1013.         }
  1014.     }
  1015.     exit(exit_stat);
  1016. }
  1017.  
  1018. static int offset;
  1019. long int in_count = 1;                  /* length of input */
  1020. long int bytes_out;                     /* length of compressed output */
  1021. long int out_count = 0;                 /* # of codes output (for debugging) */
  1022.  
  1023. /*
  1024.  * compress stdin to stdout
  1025.  *
  1026.  * Algorithm:  use open addressing double hashing (no chaining) on the 
  1027.  * prefix code / next character combination.  We do a variant of Knuth's
  1028.  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  1029.  * secondary probe.  Here, the modular division first probe is gives way
  1030.  * to a faster exclusive-or manipulation.  Also do block compression with
  1031.  * an adaptive reset, whereby the code table is cleared when the compression
  1032.  * ratio decreases, but after the table fills.  The variable-length output
  1033.  * codes are re-sized at this point, and a special CLEAR code is generated
  1034.  * for the decompressor.  Late addition:  construct the table according to
  1035.  * file size for noticeable speed improvement on small files.  Please direct
  1036.  * questions about this implementation to ames!jaw.
  1037.  */
  1038.  
  1039. void compress(OldChar) 
  1040. char OldChar;
  1041. {
  1042.     register long fcode;
  1043.     register code_int i = 0;
  1044.     register int c;
  1045.     register code_int ent;
  1046.     register code_int disp;
  1047.     register code_int hsize_reg;
  1048.     register int hshift;
  1049.  
  1050. #ifndef COMPATIBLE
  1051.     if (nomagic == 0) {
  1052.         putchar(magic_header[0]); putchar(magic_header[1]);
  1053. #ifdef MSDOS
  1054.         if (OldChar) {
  1055.             putchar((char)(maxbits | block_compress | FB_MASK));
  1056.             putchar(OldChar);
  1057.         }
  1058.         else
  1059. #endif
  1060.         putchar((char)(maxbits | block_compress));
  1061.         if(ferror(stdout))
  1062.                 writeerr();
  1063.     }
  1064. #endif /* COMPATIBLE */
  1065.  
  1066.     offset = 0;
  1067.     bytes_out = 3;              /* includes 3-byte header mojo */
  1068.     out_count = 0;
  1069.     clear_flg = 0;
  1070.     ratio = 0;
  1071.     in_count = 1;
  1072.     checkpoint = CHECK_GAP;
  1073.     maxcode = MAXCODE(n_bits = INIT_BITS);
  1074.     free_ent = ((block_compress) ? FIRST : 256 );
  1075.  
  1076.     ent = getchar ();
  1077.  
  1078.     hshift = 0;
  1079.     for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
  1080.         hshift++;
  1081.     hshift = 8 - hshift;                /* set hash code range bound */
  1082.  
  1083.     hsize_reg = hsize;
  1084.     cl_hash( (count_int) hsize_reg);            /* clear hash table */
  1085.  
  1086. #ifdef SIGNED_COMPARE_SLOW
  1087.     while ( (c = getchar()) != (unsigned) EOF ) {
  1088. #else
  1089.     while ( (c = getchar()) != EOF ) {
  1090. #endif
  1091.  
  1092. #ifdef MSDOS
  1093.         if (c == '\n') in_count += image; else /* include CR if text mode */
  1094. #endif
  1095.  
  1096.         in_count++;
  1097.  
  1098.         fcode = (long) (((long) c << maxbits) + ent);
  1099.         i = (((code_int)c << hshift) ^ ent);    /* xor hashing */
  1100.  
  1101.         if ( htabof (i) == fcode ) {
  1102.             ent = codetabof (i);
  1103.             continue;
  1104.         } else if ( (long)htabof (i) < 0 )      /* empty slot */
  1105.             goto nomatch;
  1106.         disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
  1107.         if ( i == 0 )
  1108.             disp = 1;
  1109. probe:
  1110.         if ( (i -= disp) < 0 )
  1111.             i += hsize_reg;
  1112.  
  1113.         if ( htabof (i) == fcode ) {
  1114.             ent = codetabof (i);
  1115.             continue;
  1116.         }
  1117.         if ( (long)htabof (i) > 0 ) 
  1118.             goto probe;
  1119. nomatch:
  1120.         output ( (code_int) ent );
  1121.         out_count++;
  1122.         ent = c;
  1123. #ifdef SIGNED_COMPARE_SLOW
  1124.         if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
  1125. #else
  1126.         if ( free_ent < maxmaxcode ) {
  1127. #endif
  1128.             codetabof (i) = free_ent++; /* code -> hashtable */
  1129.             htabof (i) = fcode;
  1130.         }
  1131.         else if ( (count_int)in_count >= checkpoint && block_compress )
  1132.             cl_block ();
  1133.     }
  1134.     /*
  1135.      * Put out the final code.
  1136.      */
  1137.     output( (code_int)ent );
  1138.     out_count++;
  1139.     output( (code_int)-1 );
  1140.  
  1141.     /*
  1142.      * Print out stats on stderr
  1143.      */
  1144.     if(zcat_flg == 0 && !quiet) {
  1145. #ifdef DEBUG
  1146.         fprintf( stderr,
  1147.                 "%ld chars in, %ld codes (%ld bytes) out, compression factor: ",
  1148.                 in_count, out_count, bytes_out );
  1149.         prratio( stderr, in_count, bytes_out );
  1150.         fprintf( stderr, "\n");
  1151.         fprintf( stderr, "\tCompression as in compact: " );
  1152.         prratio( stderr, in_count-bytes_out, in_count );
  1153.         fprintf( stderr, "\n");
  1154.         fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
  1155.                 free_ent - 1, n_bits );
  1156. #else /* !DEBUG */
  1157.         fprintf( stderr, "Compression: " );
  1158.         prratio( stderr, in_count-bytes_out, in_count );
  1159. #endif /* DEBUG */
  1160.     }
  1161.     if(bytes_out > in_count)    /* exit(2) if no savings */
  1162.         exit_stat = 2;
  1163.     return;
  1164. }
  1165.  
  1166. /*****************************************************************
  1167.  * TAG( output )
  1168.  *
  1169.  * Output the given code.
  1170.  * Inputs:
  1171.  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
  1172.  *              that n_bits =< (long)wordsize - 1.
  1173.  * Outputs:
  1174.  *      Outputs code to the file.
  1175.  * Assumptions:
  1176.  *      Chars are 8 bits long.
  1177.  * Algorithm:
  1178.  *      Maintain a BITS character long buffer (so that 8 codes will
  1179.  * fit in it exactly).  Use the VAX insv instruction to insert each
  1180.  * code in turn.  When the buffer fills up empty it and start over.
  1181.  */
  1182.  
  1183. static char buf[BITS];
  1184.  
  1185. #ifndef vax
  1186. char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
  1187. char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  1188. #endif /* vax */
  1189. void output( code )
  1190. code_int  code;
  1191. {
  1192. #ifdef DEBUG
  1193.     static int col = 0;
  1194. #endif /* DEBUG */
  1195.  
  1196.     /*
  1197.      * On the VAX, it is important to have the register declarations
  1198.      * in exactly the order given, or the asm will break.
  1199.      */
  1200.     register int r_off = offset, bits= n_bits;
  1201.     register char * bp = buf;
  1202.  
  1203. #ifdef DEBUG
  1204.         if ( verbose )
  1205.             fprintf( stderr, "%5d%c", code,
  1206.                     (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
  1207. #endif /* DEBUG */
  1208.     if ( code >= 0 ) {
  1209. #ifdef vax
  1210.         /* VAX DEPENDENT!! Implementation on other machines is below.
  1211.          *
  1212.          * Translation: Insert BITS bits from the argument starting at
  1213.          * offset bits from the beginning of buf.
  1214.          */
  1215.         0;      /* Work around for pcc -O bug with asm and if stmt */
  1216.         asm( "insv      4(ap),r11,r10,(r9)" );
  1217. #else /* not a vax */
  1218. /* 
  1219.  * byte/bit numbering on the VAX is simulated by the following code
  1220.  */
  1221.         /*
  1222.          * Get to the first byte.
  1223.          */
  1224.         bp += (r_off >> 3);
  1225.         r_off &= 7;
  1226.         /*
  1227.          * Since code is always >= 8 bits, only need to mask the first
  1228.          * hunk on the left.
  1229.          */
  1230.         *bp = (*bp & rmask[r_off]) | ((code << r_off) & lmask[r_off]);
  1231.         bp++;
  1232.         bits -= (8 - r_off);
  1233.         code >>= 8 - r_off;
  1234.         /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  1235.         if ( bits >= 8 ) {
  1236.             *bp++ = code;
  1237.             code >>= 8;
  1238.             bits -= 8;
  1239.         }
  1240.         /* Last bits. */
  1241.         if(bits)
  1242.             *bp = code;
  1243. #endif /* vax */
  1244.         offset += n_bits;
  1245.         if ( offset == (n_bits << 3) ) {
  1246.             bp = buf;
  1247.             bits = n_bits;
  1248.             bytes_out += bits;
  1249.             do
  1250.                 putchar(*bp++);
  1251.             while(--bits);
  1252.             offset = 0;
  1253.         }
  1254.  
  1255.         /*
  1256.          * If the next entry is going to be too big for the code size,
  1257.          * then increase it, if possible.
  1258.          */
  1259.         if ( free_ent > maxcode || (clear_flg > 0))
  1260.         {
  1261.             /*
  1262.              * Write the whole buffer, because the input side won't
  1263.              * discover the size increase until after it has read it.
  1264.              */
  1265.             if ( offset > 0 ) {
  1266.                 if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
  1267.                         writeerr();
  1268.                 bytes_out += n_bits;
  1269.             }
  1270.             offset = 0;
  1271.  
  1272.             if ( clear_flg ) {
  1273.                 maxcode = MAXCODE (n_bits = INIT_BITS);
  1274.                 clear_flg = 0;
  1275.             }
  1276.             else {
  1277.                 n_bits++;
  1278.                 if ( n_bits == maxbits )
  1279.                     maxcode = maxmaxcode;
  1280.                 else
  1281.                     maxcode = MAXCODE(n_bits);
  1282.             }
  1283. #ifdef DEBUG
  1284.             if ( debug ) {
  1285.                 fprintf( stderr, "\nChange to %d bits\n", n_bits );
  1286.                 col = 0;
  1287.             }
  1288. #endif /* DEBUG */
  1289.         }
  1290.     } else {
  1291.         /*
  1292.          * At EOF, write the rest of the buffer.
  1293.          */
  1294.         if ( offset > 0 )
  1295.             fwrite( buf, 1, (offset + 7) / 8, stdout );
  1296.         bytes_out += (offset + 7) / 8;
  1297.         offset = 0;
  1298.         fflush( stdout );
  1299. #ifdef DEBUG
  1300.         if ( verbose )
  1301.             fprintf( stderr, "\n" );
  1302. #endif /* DEBUG */
  1303.         if( ferror( stdout ) )
  1304.                 writeerr();
  1305.     }
  1306. }
  1307.  
  1308. /*
  1309.  * Decompress stdin to stdout.  This routine adapts to the codes in the
  1310.  * file building the "string" table on-the-fly; requiring no table to
  1311.  * be stored in the compressed file.  The tables used herein are shared
  1312.  * with those of the compress() routine.  See the definitions above.
  1313.  */
  1314.  
  1315. void decompress() {
  1316.  
  1317. #ifdef BIG
  1318.     register char_type far *stackp;
  1319. #else
  1320.     register char_type *stackp;
  1321. #endif
  1322.  
  1323.     register int finchar;
  1324.     register code_int code, oldcode, incode;
  1325.  
  1326.     /*
  1327.      * As above, initialize the first 256 entries in the table.
  1328.      */
  1329.     maxcode = MAXCODE(n_bits = INIT_BITS);
  1330.     for ( code = 255; code >= 0; code-- ) {
  1331.         tab_prefixof(code) = 0;
  1332.         tab_suffixof(code) = (char_type)code;
  1333.     }
  1334.     free_ent = ((block_compress) ? FIRST : 256 );
  1335.  
  1336.     finchar = oldcode = getcode();
  1337.     if(oldcode == -1)   /* EOF already? */
  1338.         return;                 /* Get out of here */
  1339.     putchar( (char)finchar );           /* first code must be 8 bits = char */
  1340.     if(ferror(stdout))          /* Crash if can't write */
  1341.         writeerr();
  1342.     stackp = de_stack;
  1343.  
  1344.     while ( (code = getcode()) > -1 ) {
  1345.  
  1346.         if ( (code == CLEAR) && block_compress ) {
  1347.             for ( code = 255; code >= 0; code-- )
  1348.                 tab_prefixof(code) = 0;
  1349.             clear_flg = 1;
  1350.             free_ent = FIRST - 1;
  1351.             if ( (code = getcode ()) == -1 )    /* O, untimely death! */
  1352.                 break;
  1353.         }
  1354.         incode = code;
  1355.         /*
  1356.          * Special case for KwKwK string.
  1357.          */
  1358.         if ( code >= free_ent ) {
  1359.             *stackp++ = finchar;
  1360.             code = oldcode;
  1361.         }
  1362.  
  1363.         /*
  1364.          * Generate output characters in reverse order
  1365.          */
  1366. #ifdef SIGNED_COMPARE_SLOW
  1367.         while ( ((unsigned long)code) >= ((unsigned long)256) ) {
  1368. #else
  1369.         while ( code >= 256 ) {
  1370. #endif
  1371.             *stackp++ = tab_suffixof(code);
  1372.             code = tab_prefixof(code);
  1373.         }
  1374.         *stackp++ = finchar = tab_suffixof(code);
  1375.  
  1376.         /*
  1377.          * And put them out in forward order
  1378.          */
  1379.         do
  1380.             putchar ( *--stackp );
  1381.         while ( stackp > de_stack );
  1382.  
  1383.         /*
  1384.          * Generate the new entry.
  1385.          */
  1386.         if ( (code=free_ent) < maxmaxcode ) {
  1387.             tab_prefixof(code) = (unsigned short)oldcode;
  1388.             tab_suffixof(code) = finchar;
  1389.             free_ent = code+1;
  1390.         } 
  1391.         /*
  1392.          * Remember previous code.
  1393.          */
  1394.         oldcode = incode;
  1395.     }
  1396.     fflush( stdout );
  1397.     if(ferror(stdout))
  1398.         writeerr();
  1399. }
  1400.  
  1401. /*****************************************************************
  1402.  * TAG( getcode )
  1403.  *
  1404.  * Read one code from the standard input.  If EOF, return -1.
  1405.  * Inputs:
  1406.  *      stdin
  1407.  * Outputs:
  1408.  *      code or -1 is returned.
  1409.  */
  1410. code_int getcode() {
  1411.     /*
  1412.      * On the VAX, it is important to have the register declarations
  1413.      * in exactly the order given, or the asm will break.
  1414.      */
  1415.     register code_int code;
  1416.     static int offset = 0, size = 0;
  1417.     static char_type buf[BITS];
  1418.     register int r_off, bits;
  1419.     register char_type *bp = buf;
  1420.  
  1421.     if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
  1422.         /*
  1423.          * If the next entry will be too big for the current code
  1424.          * size, then we must increase the size.  This implies reading
  1425.          * a new buffer full, too.
  1426.          */
  1427.         if ( free_ent > maxcode ) {
  1428.             n_bits++;
  1429.             if ( n_bits == maxbits )
  1430.                 maxcode = maxmaxcode;   /* won't get any bigger now */
  1431.             else
  1432.                 maxcode = MAXCODE(n_bits);
  1433.         }
  1434.         if ( clear_flg > 0) {
  1435.             maxcode = MAXCODE (n_bits = INIT_BITS);
  1436.             clear_flg = 0;
  1437.         }
  1438.         size = fread( buf, 1, n_bits, stdin );
  1439.         if ( size <= 0 )
  1440.             return -1;                  /* end of file */
  1441.         offset = 0;
  1442.         /* Round size down to integral number of codes */
  1443.         size = (size << 3) - (n_bits - 1);
  1444.     }
  1445.     r_off = offset;
  1446.     bits = n_bits;
  1447. #ifdef vax
  1448.     asm( "extzv   r10,r9,(r8),r11" );
  1449. #else /* not a vax */
  1450.         /*
  1451.          * Get to the first byte.
  1452.          */
  1453.         bp += (r_off >> 3);
  1454.         r_off &= 7;
  1455.         /* Get first part (low order bits) */
  1456. #ifdef NO_UCHAR
  1457.         code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
  1458. #else
  1459.         code = (*bp++ >> r_off);
  1460. #endif /* NO_UCHAR */
  1461.         bits -= (8 - r_off);
  1462.         r_off = 8 - r_off;              /* now, offset into code word */
  1463.         /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  1464.         if ( bits >= 8 ) {
  1465. #ifdef NO_UCHAR
  1466.             code |= (*bp++ & 0xff) << r_off;
  1467. #else
  1468.             code |= *bp++ << r_off;
  1469. #endif /* NO_UCHAR */
  1470.             r_off += 8;
  1471.             bits -= 8;
  1472.         }
  1473.         /* high order bits. */
  1474.         code |= (*bp & rmask[bits]) << r_off;
  1475. #endif /* vax */
  1476.     offset += n_bits;
  1477.  
  1478.     return code;
  1479. }
  1480. char * rindex(s, c)            /* For those who don't have it in libc.a */
  1481. register char *s, c;
  1482. {
  1483.         char *p;
  1484.         for (p = NULL; *s; s++)
  1485.             if (*s == c)
  1486.                 p = s;
  1487.         return(p);
  1488. }
  1489.  
  1490. #ifdef DEBUG
  1491.  
  1492. void printcodes()
  1493. {
  1494.     /*
  1495.      * Just print out codes from input file.  For debugging.
  1496.      */
  1497.     code_int code;
  1498.     int col = 0, bits;
  1499.  
  1500.     bits = n_bits = INIT_BITS;
  1501.     maxcode = MAXCODE(n_bits);
  1502.     free_ent = ((block_compress) ? FIRST : 256 );
  1503.     while ( ( code = getcode() ) >= 0 ) {
  1504.         if ( (code == CLEAR) && block_compress ) {
  1505.             free_ent = FIRST - 1;
  1506.             clear_flg = 1;
  1507.         }
  1508.         else if ( free_ent < maxmaxcode )
  1509.             free_ent++;
  1510.         if ( bits != n_bits ) {
  1511.             fprintf(stderr, "\nChange to %d bits\n", n_bits );
  1512.             bits = n_bits;
  1513.             col = 0;
  1514.         }
  1515.         fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
  1516.     }
  1517.     putc( '\n', stderr );
  1518.     exit( 0 );
  1519. }
  1520.  
  1521. code_int sorttab[1<<BITS];      /* sorted pointers into htab */
  1522. void dump_tab()      /* dump string table */
  1523. {
  1524.     register int i, first;
  1525.     register ent;
  1526. #define STACK_SIZE      15000
  1527.     int stack_top = STACK_SIZE;
  1528.     register c;
  1529.  
  1530.     if(do_decomp == 0) {        /* compressing */
  1531.         register int flag = 1;
  1532.  
  1533.         for(i=0; i<hsize; i++) {        /* build sort pointers */
  1534.                 if((long)htabof(i) >= 0) {
  1535.                         sorttab[codetabof(i)] = i;
  1536.                 }
  1537.         }
  1538.         first = block_compress ? FIRST : 256;
  1539.         for(i = first; i < free_ent; i++) {
  1540.                 fprintf(stderr, "%5d: \"", i);
  1541.                 de_stack[--stack_top] = '\n';
  1542.                 de_stack[--stack_top] = '"';
  1543.                 stack_top = in_stack((htabof(sorttab[i])>>maxbits)&0xff,
  1544.                                      stack_top);
  1545.                 for(ent=htabof(sorttab[i]) & ((1<<maxbits)-1);
  1546.                     ent > 256;
  1547.                     ent=htabof(sorttab[ent]) & ((1<<maxbits)-1)) {
  1548.                         stack_top = in_stack(htabof(sorttab[ent]) >> maxbits,
  1549.                                                 stack_top);
  1550.                 }
  1551.                 stack_top = in_stack(ent, stack_top);
  1552.                 fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr);
  1553.                 stack_top = STACK_SIZE;
  1554.         }
  1555.    } else if(!debug) {  /* decompressing */
  1556.  
  1557.        for ( i = 0; i < free_ent; i++ ) {
  1558.            ent = i;
  1559.            c = tab_suffixof(ent);
  1560.            if ( isascii(c) && isprint(c) )
  1561.                fprintf( stderr, "%5d: %5d/'%c'  \"",
  1562.                            ent, tab_prefixof(ent), c );
  1563.            else
  1564.                fprintf( stderr, "%5d: %5d/\\%03o \"",
  1565.                            ent, tab_prefixof(ent), c );
  1566.            de_stack[--stack_top] = '\n';
  1567.            de_stack[--stack_top] = '"';
  1568.            for ( ; ent != NULL;
  1569.                    ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
  1570.                stack_top = in_stack(tab_suffixof(ent), stack_top);
  1571.            }
  1572.            fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr );
  1573.            stack_top = STACK_SIZE;
  1574.        }
  1575.     }
  1576. }
  1577.  
  1578. int in_stack(c, stack_top)
  1579.         register c, stack_top;
  1580. {
  1581.         if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
  1582.             de_stack[--stack_top] = c;
  1583.         } else {
  1584.             switch( c ) {
  1585.             case '\n': de_stack[--stack_top] = 'n'; break;
  1586.             case '\t': de_stack[--stack_top] = 't'; break;
  1587.             case '\b': de_stack[--stack_top] = 'b'; break;
  1588.             case '\f': de_stack[--stack_top] = 'f'; break;
  1589.             case '\r': de_stack[--stack_top] = 'r'; break;
  1590.             case '\\': de_stack[--stack_top] = '\\'; break;
  1591.             default:
  1592.                 de_stack[--stack_top] = '0' + c % 8;
  1593.                 de_stack[--stack_top] = '0' + (c / 8) % 8;
  1594.                 de_stack[--stack_top] = '0' + c / 64;
  1595.                 break;
  1596.             }
  1597.             de_stack[--stack_top] = '\\';
  1598.         }
  1599.         return stack_top;
  1600. }
  1601. #endif /* DEBUG */
  1602.  
  1603. void writeerr()
  1604. {
  1605.     perror ( ofname );
  1606.     unlink ( ofname );
  1607.     exit ( 1 );
  1608. }
  1609.  
  1610. void copystat(ifname, ofname)
  1611. char *ifname, *ofname;
  1612. {
  1613.     struct stat statbuf;
  1614.     int mode;
  1615. #ifdef __TURBOC__
  1616.     struct ftime Ftime;
  1617.     int InFile,OutFile;
  1618. #else
  1619.     time_t timep[2];
  1620. #endif
  1621.  
  1622. #ifdef MSDOS
  1623.     if (_osmajor < 3) freopen("CON","at",stdout); else    /* MS-DOS 2.xx bug */
  1624. #endif
  1625.  
  1626.     fclose(stdout);
  1627.     if (stat(ifname, &statbuf)) {               /* Get stat on input file */
  1628.         perror(ifname);
  1629.         return;
  1630.     }
  1631.  
  1632. #ifndef MSDOS
  1633.     if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) {
  1634.         if(quiet)
  1635.                 fprintf(stderr, "%s: ", ifname);
  1636.         fprintf(stderr, " -- not a regular file: unchanged");
  1637.         exit_stat = 1;
  1638.     } else if (statbuf.st_nlink > 1) {
  1639.         if(quiet)
  1640.                 fprintf(stderr, "%s: ", ifname);
  1641.         fprintf(stderr, " -- has %d other links: unchanged",
  1642.                 statbuf.st_nlink - 1);
  1643.         exit_stat = 1;
  1644.     } else if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */
  1645. #else
  1646.     if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */
  1647. #endif /* MSDOS */
  1648.  
  1649.         if(!quiet)
  1650.                 fprintf(stderr, " -- file unchanged");
  1651.     } else {                    /* ***** Successful Compression ***** */
  1652.         exit_stat = 0;
  1653.         mode = statbuf.st_mode & 07777;
  1654.         if (chmod(ofname, mode))                /* Copy modes */
  1655.             perror(ofname);
  1656.  
  1657. #ifndef MSDOS
  1658.         chown(ofname, statbuf.st_uid, statbuf.st_gid);  /* Copy ownership */
  1659. #endif
  1660.  
  1661. #ifdef __TURBOC__
  1662.         InFile = open(ifname,O_RDONLY);
  1663.         OutFile = open(ofname,O_RDONLY);
  1664.         getftime(InFile,&Ftime);
  1665.         setftime(OutFile,&Ftime);
  1666. #else
  1667.         timep[0] = statbuf.st_atime;
  1668.         timep[1] = statbuf.st_mtime;
  1669.         utime(ofname, timep);   /* Update last accessed and modified times */
  1670. #endif
  1671.         if (unlink(ifname))     /* Remove input file */
  1672.             perror(ifname);
  1673.         if(!quiet)
  1674.                 fprintf(stderr, " -- replaced with %s", ofname);
  1675.         return;         /* Successful return */
  1676.     }
  1677.  
  1678.     /* Unsuccessful return -- one of the tests failed */
  1679.     if (unlink(ofname))
  1680.         perror(ofname);
  1681. }
  1682.  
  1683. #ifndef MSDOS
  1684. /*
  1685.  * This routine returns 1 if we are running in the foreground and stderr
  1686.  * is a tty.
  1687.  */
  1688. foreground()
  1689. {
  1690.         if(bgnd_flag) { /* background? */
  1691.                 return(0);
  1692.         } else {                        /* foreground */
  1693.                 if(isatty(2)) {         /* and stderr is a tty */
  1694.                         return(1);
  1695.                 } else {
  1696.                         return(0);
  1697.                 }
  1698.         }
  1699. }
  1700. #endif
  1701.  
  1702. #ifdef __TURBOC__
  1703. int c_break(void)    /* Control-break handler.  Does the job of onintr(). */
  1704. {
  1705.    unlink(ofname);
  1706.    return(0);
  1707. }
  1708. #else
  1709. void onintr ( )
  1710. {
  1711.     unlink ( ofname );
  1712.     exit ( 1 );
  1713. }
  1714. #endif
  1715.  
  1716. #ifndef MSDOS
  1717. oops ( )        /* wild pointer -- assume bad input */
  1718. {
  1719.     if ( do_decomp == 1 )
  1720.         fprintf ( stderr, "uncompress: corrupt input\n" );
  1721.     unlink ( ofname );
  1722.     exit ( 1 );
  1723. }
  1724. #endif /* MSDOS */
  1725.  
  1726.  
  1727. void cl_block ()             /* table clear for block compress */
  1728. {
  1729.     register long int rat;
  1730.  
  1731.     checkpoint = in_count + CHECK_GAP;
  1732. #ifdef DEBUG
  1733.         if ( debug ) {
  1734.                 fprintf ( stderr, "count: %ld, ratio: ", in_count );
  1735.                 prratio ( stderr, in_count, bytes_out );
  1736.                 fprintf ( stderr, "\n");
  1737.         }
  1738. #endif /* DEBUG */
  1739.  
  1740.     if(in_count > 0x007fffffL) { /* shift will overflow */
  1741.         rat = bytes_out >> 8;
  1742.         if(rat == 0) {          /* Don't divide by zero */
  1743.             rat = 0x7fffffffL;
  1744.         } else {
  1745.             rat = in_count / rat;
  1746.         }
  1747.     } else {
  1748.         rat = (in_count << 8) / bytes_out;      /* 8 fractional bits */
  1749.     }
  1750.     if ( rat > ratio ) {
  1751.         ratio = rat;
  1752.     } else {
  1753.         ratio = 0;
  1754. #ifdef DEBUG
  1755.         if(verbose)
  1756.                 dump_tab();     /* dump string table */
  1757. #endif
  1758.         cl_hash ( (count_int) hsize );
  1759.         free_ent = FIRST;
  1760.         clear_flg = 1;
  1761.         output ( (code_int) CLEAR );
  1762. #ifdef DEBUG
  1763.         if(debug)
  1764.                 fprintf ( stderr, "clear\n" );
  1765. #endif /* DEBUG */
  1766.     }
  1767. }
  1768.  
  1769. void cl_hash(hsize)          /* reset code table */
  1770.         register count_int hsize;
  1771. {
  1772.  
  1773. #ifdef XENIX_16
  1774.         register j;
  1775.         register long k = hsize;
  1776.          
  1777. # ifdef MSDOS
  1778.         register count_int far *htab_p;
  1779. # else
  1780.         register count_int *htab_p;
  1781. # endif /* MSDOS */
  1782.  
  1783. #else   /* Normal machine */
  1784.         register count_int *htab_p = (count_int *) htab+hsize;
  1785. #endif  /* XENIX_16 */
  1786.  
  1787.         register long i;
  1788.         register long m1 = -1;
  1789.  
  1790. #ifdef XENIX_16
  1791.     for(j=0; j<=8 && k>=0; j++,k-=8192) {
  1792.         i = 8192;
  1793.         if(k < 8192) {
  1794.             i = k;
  1795.         }
  1796.         htab_p = &(htab[j][i]);
  1797.         i -= 16;
  1798.         if(i > 0) {
  1799. #else
  1800.         i = hsize - 16;
  1801. #endif
  1802.         do {                            /* might use Sys V memset(3) here */
  1803.                 *(htab_p-16) = m1;
  1804.                 *(htab_p-15) = m1;
  1805.                 *(htab_p-14) = m1;
  1806.                 *(htab_p-13) = m1;
  1807.                 *(htab_p-12) = m1;
  1808.                 *(htab_p-11) = m1;
  1809.                 *(htab_p-10) = m1;
  1810.                 *(htab_p-9) = m1;
  1811.                 *(htab_p-8) = m1;
  1812.                 *(htab_p-7) = m1;
  1813.                 *(htab_p-6) = m1;
  1814.                 *(htab_p-5) = m1;
  1815.                 *(htab_p-4) = m1;
  1816.                 *(htab_p-3) = m1;
  1817.                 *(htab_p-2) = m1;
  1818.                 *(htab_p-1) = m1;
  1819.                 htab_p -= 16;
  1820.         } while ((i -= 16) >= 0);
  1821. #ifdef XENIX_16
  1822.         }
  1823.     }
  1824. #endif
  1825.         for ( i += 16; i > 0; i-- )
  1826.                 *--htab_p = m1;
  1827. }
  1828.  
  1829.  
  1830. void prratio(stream, num, den)
  1831. FILE *stream;
  1832. long int num, den;
  1833. {
  1834.  
  1835. register long q;
  1836.  
  1837.         if(num > 214748L) {             /* 2147483647/10000 */
  1838.                 q = num / (den / 10000L);
  1839.         } else {
  1840.                 q = 10000L * num / den;         /* Long calculations, though */
  1841.         }
  1842.         if (q < 0) {
  1843.                 putc('-', stream);
  1844.                 q = -q;
  1845.         }
  1846.         fprintf(stream, "%d.%02d%%", (int)(q / 100), (int)(q % 100));
  1847. }
  1848. void version()
  1849. {
  1850.         fprintf(stderr, "%s\n", rcs_ident);
  1851.         fprintf(stderr, "Options: ");
  1852. #ifdef vax
  1853.         fprintf(stderr, "vax, ");
  1854. #endif
  1855. #ifdef NO_UCHAR
  1856.         fprintf(stderr, "NO_UCHAR, ");
  1857. #endif
  1858. #ifdef SIGNED_COMPARE_SLOW
  1859.         fprintf(stderr, "SIGNED_COMPARE_SLOW, ");
  1860. #endif
  1861. #ifdef MSDOS
  1862.         fprintf(stderr, "MSDOS, ");
  1863. #endif
  1864. #ifdef XENIX_16
  1865.         fprintf(stderr, "XENIX_16, ");
  1866. #endif
  1867. #ifdef COMPATIBLE
  1868.         fprintf(stderr, "COMPATIBLE, ");
  1869. #endif
  1870. #ifdef DEBUG
  1871.         fprintf(stderr, "DEBUG, ");
  1872. #endif
  1873. #ifdef BSD4_2
  1874.         fprintf(stderr, "BSD4_2, ");
  1875. #endif
  1876.         fprintf(stderr, "BITS = %d\n", BITS);
  1877. }
  1878.  
  1879. #ifdef __MSDOS__
  1880. #define PATHSEP "/\\:"
  1881. #else
  1882. #define strchr index
  1883. #define strrchr rindex
  1884. #define PATHSEP "/"
  1885. #endif
  1886.  
  1887. char *PathTail(char *Path)
  1888. /* Given a path, returns a pointer to the last component (tail) */
  1889. {
  1890. char *Temp,*strrpbrk();
  1891.  
  1892.    Temp = strrpbrk(Path,PATHSEP);
  1893.    return (Temp == NULL ? Path : Temp + 1);
  1894. }
  1895.  
  1896. char *strrpbrk(S,Chars)
  1897. /* Returns a pointer to the last character in S that is also in Chars.
  1898.    If no char in Chars is found in S, a null pointer is returned. */
  1899. char *S,*Chars;
  1900. {
  1901. int I;
  1902.  
  1903.    I = strlen(S) - 1;
  1904.    while (I >= 0 && strchr(Chars,S[I]) == NULL)
  1905.       I--;
  1906.    return (strrchr(Chars,S[I]) == NULL ? NULL : S + I);
  1907. }
  1908.