home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / reviewed / volume02 / ncmprss / part02 < prev    next >
Encoding:
Internet Message Format  |  1992-08-27  |  50.8 KB

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