home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / sources / reviewed / 120 < prev    next >
Encoding:
Internet Message Format  |  1992-08-29  |  51.3 KB

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