home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / apple2 / 50 < prev    next >
Encoding:
Internet Message Format  |  1991-05-02  |  35.7 KB

  1. From: jac@yoko.rutgers.edu (Jonathan A. Chandross)
  2. Newsgroups: comp.sources.apple2
  3. Subject: v001SRC032:  Nulib - Archive Library Tools (Unix) 01/10
  4. Message-ID: <May.1.18.08.23.1991.23454@yoko.rutgers.edu>
  5. Date: 1 May 91 22:08:25 GMT
  6. Approved: jac@paul.rutgers.edu
  7.  
  8.  
  9. Submitted-by: Andy McFadden (fadden@cory.berkeley.edu)
  10. Posting-number: Volume 1, Source:32
  11. Archive-name: archive/unix/nulib/part01.10
  12. Architecture: UNIX
  13. Version-number: 3.03
  14.  
  15.  
  16. Nulib allows handles many of the archiving formats used on the Apple.
  17. Very handy indeed.
  18.  
  19. Enjoy.
  20.  
  21.  
  22. =README
  23. -Nulib v3.03 (February 1991)
  24. -- Fixed XENIX problems with includes and libs (Ron Higgins).
  25. -- Fixed bug in directory expansion (Larry W. Virden).
  26. -NuLib v3.02
  27. -- Silenced screaming about bad dates (Larry W. Virden).
  28. -- Fixed glitches in nulib.lnk and nulib.mak (Bruce Kahn).
  29. -NuLib v3.01
  30. -- Fixed non-compression bug in ShrinkIt LZW (Scott Blackman).
  31. -
  32. -NuLib v3.0 README (September 1990)
  33. -
  34. -New items in 3.0:
  35. -- ShrinkIt LZW compression
  36. -- UNIX 12-bit and 16-bit compression
  37. -- New archive listing format (similar to ARC and ZOO)
  38. -
  39. -Things work much better if you read the documentation file (now available
  40. -on the archive site... sorry I didn't put it up sooner).  If you want to
  41. -use UNIX compress to store files, READ THE DOCUMENTATION FIRST.  Not only
  42. -does it tell you how to do it, but it has some warnings about compatibility.
  43. -
  44. -Note that v3.0 does *NOT* unpack archives compressed with GS/ShrinkIt.  The
  45. -problem is that NuLib cannot at present decode LZW/II compression.  You can
  46. -read comments and extract files that were added without compression, but
  47. -that's about it.
  48. -
  49. -To compile this on a UNIX-type system, edit the file "nudefs.h".  Several
  50. -systems are predefined; the default is a BSD UNIX system.  If you want
  51. -to run this on something other than BSD, comment out the #define statements
  52. -(using "/*" and "*/"), and uncomment the appropriate statements.  Then,
  53. -type "make" to execute the Makefile.  If all goes well, you will be
  54. -left with an executable file called "nulib".  If all does not go well,
  55. -double check "nudefs.h".  Send some mail to me if you can't get it to work
  56. -at all.
  57. -
  58. -Currently AT&T 3B2 machines seem to be very uncooperative.  If somebody gets
  59. -NuLib to run on one, please let me know.  The problem is in the directory
  60. -manipulation routines (struct dirent, opendir(), readdir(), etc).
  61. -
  62. -To make the MS-DOS version, use the nulib.mak and nulib.lnk files with MS C
  63. -(supplied by Bruce Kahn).  To make the APW version, put all the files in
  64. -one directory, and make a subdirectory called "OBJ".  Put the "linked.scr"
  65. -and "linker.scr" files in OBJ, and then "make.apw".  This will compile all
  66. -the files.  When it finishes, change to OBJ and "alink linked.scr" (standard
  67. -linker) or "alink linker.scr" (ZapLink).  The makefile used to do this
  68. -automatically, but with only 1.25MB of RAM you have to exit APW to purge
  69. -all the memory used by the compiler, and and then restart APW and
  70. -run the linker.
  71. -
  72. -In both cases, BE SURE to modify "nudefs.h" first.  If you don't, the
  73. -compilation will halt in "numain.c" on a line which reminds you to change
  74. -"nudefs.h" (I tended to forget about this).  Also, make sure all the file
  75. -types are set to SRC, and the auxtype to CC.  These are changed with the
  76. -commands "filetype" and "change", respectively.
  77. -
  78. -Please send bug reports, ideas, or gripes to fadden@cory.berkeley.edu, or to
  79. -one of the addresses mentioned in the documentation or under the "-hw"
  80. -option.
  81. -
  82. -Known bugs:
  83. - - Under some systems, using UNIX compress on a file which does not compress
  84. -will cause the archive's EOF to be larger than it should be.  This slack
  85. -space will be used up if you add more files to the archive (with NuLib
  86. -anyway; no guarantees about ShrinkIt or GS/ShrinkIt, but there's no reason
  87. -why they shouldn't work).
  88. -
  89. -(just to make things clear: if the file being compressed doesn't get any
  90. -smaller, the compression halts and the file is simply stored uncompressed.
  91. -Because of the way compress works, on some systems the space that would
  92. -have been occupied by more compressed data is left attached to the file.
  93. -The ShrinkIt compression does not suffer from this problem.  If you add
  94. -more stuff to the file, NuLib will fill the slack space first, NOT just
  95. -append to the end of the file).
  96. -
  97. -Things to come:
  98. - - LZW/II decompression (for GS/ShrinkIt archives)
  99. - - Support for UNIX tar archives
  100. - - CRLF translations while adding files
  101. - - Better handling of comments
  102. -
  103. -Don't hold your breath waiting for these...
  104. -
  105. -I can be reached at:
  106. - fadden@cory.berkeley.edu    (primary e-mail account)
  107. - fadden@hermes.berkeley.edu    (secondary e-mail, since primary is buggy)
  108. -
  109. -All this stuff, and documentation as well, is available via anonymous FTP at:
  110. - avalanche.berkeley.edu
  111. - tornado.berkeley.edu
  112. - headcrash.berkeley.edu
  113. - ...
  114. -in pub/Apple2
  115. -
  116. =nucomp.c
  117. -/*
  118. - * nucomp.c - code to perform UNIX style LZW compression
  119. - *
  120. - * NuLib v3.0  February 1991  Freeware (distribute, don't sell)
  121. - * By Andy McFadden (fadden@cory.berkeley.edu)
  122. - *
  123. - * This is the main compression code from compress v4.3.  Modifications
  124. - * have been made to integrate it with NuLib (primarily in that it no longer
  125. - * uses stdin/stdout), but it's functionally the same.
  126. - */
  127. -#ifdef APW
  128. -segment "Compress"
  129. -#endif
  130. -
  131. -#include "nudefs.h"
  132. -#include "nupak.h"
  133. -#define MAIN        /* cause nucomp.h to alloc global vars */
  134. -
  135. -/*@H************************ < COMPRESS API    > ****************************
  136. -*                                                                           *
  137. -*   compress : compapi.c  <current version of compress algorithm>           *
  138. -*                                                                           *
  139. -*   port by  : Donald J. Gloistein                                          *
  140. -*                                                                           *
  141. -*   Source, Documentation, Object Code:                                     *
  142. -*   released to Public Domain.  This code is based on code as documented    *
  143. -*   below in release notes.                                                 *
  144. -*                                                                           *
  145. -*---------------------------  Module Description  --------------------------*
  146. -*   Contains source code for modified Lempel-Ziv method (LZW) compression   *
  147. -*   and decompression.                                                      *
  148. -*                                                                           *
  149. -*   This code module can be maintained to keep current on releases on the   *
  150. -*   Unix system. The command shell and dos modules can remain the same.     *
  151. -*                                                                           *
  152. -*--------------------------- Implementation Notes --------------------------*
  153. -*                                                                           *
  154. -*   compiled with : compress.h compress.fns compress.c                      *
  155. -*   linked with   : compress.obj compusi.obj                                *
  156. -*                                                                           *
  157. -*   problems:                                                               *
  158. -*                                                                           *
  159. -*                                                                           *
  160. -*   CAUTION: Uses a number of defines for access and speed. If you change   *
  161. -*            anything, make sure about side effects.                        *
  162. -*                                                                           *
  163. -* Compression:                                                              *
  164. -* Algorithm:  use open addressing double hashing (no chaining) on the       *
  165. -* prefix code / next character combination.  We do a variant of Knuth's     *
  166. -* algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime     *
  167. -* secondary probe.  Here, the modular division first probe is gives way     *
  168. -* to a faster exclusive-or manipulation.                                    *
  169. -* Also block compression with an adaptive reset was used in original code,  *
  170. -* whereby the code table is cleared when the compression ration decreases   *
  171. -* but after the table fills.  This was removed from this edition. The table *
  172. -* is re-sized at this point when it is filled , and a special CLEAR code is *
  173. -* generated for the decompressor. This results in some size difference from *
  174. -* straight version 4.0 joe Release. But it is fully compatible in both v4.0 *
  175. -* and v4.01                                                                 *
  176. -*                                                                           *
  177. -* Decompression:                                                            *
  178. -* This routine adapts to the codes in the file building the "string" table  *
  179. -* on-the-fly; requiring no table to be stored in the compressed file.  The  *
  180. -* tables used herein are shared with those of the compress() routine.       *
  181. -*                                                                           *
  182. -*     Initials ---- Name ---------------------------------                  *
  183. -*      DjG          Donald J. Gloistein, current port to MsDos 16 bit       *
  184. -*                   Plus many others, see rev.hst file for full list        *
  185. -*      LvR          Lyle V. Rains, many thanks for improved implementation  *
  186. -*                   of the compression and decompression routines.          *
  187. -*************************************************************************@H*/
  188. -
  189. -#include <stdio.h>
  190. -#define assert(x)
  191. -#include "nucomp.h" /* contains the rest of the include file declarations */
  192. -
  193. -FILE *nustdin, *nustdout;    /* NuLib: use these instead of stdin/stdout */
  194. -long nubytes_read, nucomp_thread_eof;    /* NuLib: used in nextcode (decomp) */
  195. -
  196. -/* NuLib: pulled this out of nextcode() so we can initialize it every time */
  197. -static int prevbits = 0;
  198. -/* NuLib: pulled out of putcode() */
  199. -static int oldbits = 0;
  200. -
  201. -static int offset;
  202. -static long int in_count ;         /* length of input */
  203. -static long int bytes_out;         /* length of compressed output */
  204. -static long int max_bytes_out;    /* NuLib: max #of bytes to output */
  205. -
  206. -static CODE prefxcode, nextfree;
  207. -static CODE highcode;
  208. -static CODE maxcode;
  209. -static HASH hashsize;
  210. -static int  bits;
  211. -
  212. -
  213. -/*
  214. - * The following two parameter tables are the hash table sizes and
  215. - * maximum code values for various code bit-lengths.  The requirements
  216. - * are that Hashsize[n] must be a prime number and Maxcode[n] must be less
  217. - * than Maxhash[n].  Table occupancy factor is (Maxcode - 256)/Maxhash.
  218. - * Note:  I am using a lower Maxcode for 16-bit codes in order to
  219. - * keep the hash table size less than 64k entries.
  220. - */
  221. -CONST HASH hs[] = {
  222. -  0x13FF,       /* 12-bit codes, 75% occupancy */
  223. -  0x26C3,       /* 13-bit codes, 80% occupancy */
  224. -  0x4A1D,       /* 14-bit codes, 85% occupancy */
  225. -  0x8D0D,       /* 15-bit codes, 90% occupancy */
  226. -  0xFFD9        /* 16-bit codes, 94% occupancy, 6% of code values unused */
  227. -};
  228. -#define Hashsize(maxb) (hs[(maxb) -MINBITS])
  229. -
  230. -CONST CODE mc[] = {
  231. -  0x0FFF,       /* 12-bit codes */
  232. -  0x1FFF,       /* 13-bit codes */
  233. -  0x3FFF,       /* 14-bit codes */
  234. -  0x7FFF,       /* 15-bit codes */
  235. -  0xEFFF        /* 16-bit codes, 6% of code values unused */
  236. -};
  237. -#define Maxcode(maxb) (mc[(maxb) -MINBITS])
  238. -
  239. -#define allocx(type,ptr,size) \
  240. -    (((ptr) = (type FAR *) emalloc((unsigned int)(size),sizeof(type))) == NULLPTR(type) \
  241. -    ? NOMEM : OK \
  242. -    )
  243. -
  244. -#define free_array(type,ptr,offset) \
  245. -    if (ptr != NULLPTR(type)) { \
  246. -        efree((ALLOCTYPE FAR *)((ptr) + (offset))); \
  247. -        (ptr) = NULLPTR(type); \
  248. -    }
  249. -
  250. -  /*
  251. -   * Macro to allocate new memory to a pointer with an offset value.
  252. -   */
  253. -#define alloc_array(type, ptr, size, offset) \
  254. -    ( allocx(type, ptr, (size) - (offset)) != OK \
  255. -      ? NOMEM \
  256. -      : (((ptr) -= (offset)), OK) \
  257. -    )
  258. -
  259. -static char FAR *sfx = NULLPTR(char) ;
  260. -#define suffix(code)     sfx[code]
  261. -
  262. -
  263. -#ifdef SPLIT_PFX
  264. -  static CODE FAR *pfx[2] = {NULLPTR(CODE), NULLPTR(CODE)};
  265. -#else
  266. -  static CODE FAR *pfx = NULLPTR(CODE);
  267. -#endif
  268. -
  269. -
  270. -#ifdef SPLIT_HT
  271. -  static CODE FAR *ht[2] = {NULLPTR(CODE),NULLPTR(CODE)};
  272. -#else
  273. -  static CODE FAR *ht = NULLPTR(CODE);
  274. -#endif
  275. -
  276. -
  277. -int alloc_tables(maxcode, hashsize)
  278. -  CODE maxcode;
  279. -  HASH hashsize;
  280. -{
  281. -  static CODE oldmaxcode = 0;
  282. -  static HASH oldhashsize = 0;
  283. -
  284. -  if (hashsize > oldhashsize) {
  285. -#ifdef SPLIT_HT
  286. -      free_array(CODE,ht[1], 0);
  287. -      free_array(CODE,ht[0], 0);
  288. -#else
  289. -      free_array(CODE,ht, 0);
  290. -#endif
  291. -    oldhashsize = 0;
  292. -  }
  293. -
  294. -    if (maxcode > oldmaxcode) {
  295. -#ifdef SPLIT_PFX
  296. -        free_array(CODE,pfx[1], 128);
  297. -        free_array(CODE,pfx[0], 128);
  298. -#else
  299. -        free_array(CODE,pfx, 256);
  300. -#endif
  301. -        free_array(char,sfx, 256);
  302. -
  303. -        if (   alloc_array(char, sfx, maxcode + 1, 256)
  304. -#ifdef SPLIT_PFX
  305. -            || alloc_array(CODE, pfx[0], (maxcode + 1) / 2, 128)
  306. -            || alloc_array(CODE, pfx[1], (maxcode + 1) / 2, 128)
  307. -#else
  308. -            || alloc_array(CODE, pfx, (maxcode + 1), 256)
  309. -#endif
  310. -        ) {
  311. -            oldmaxcode = 0;
  312. -            exit_stat = NOMEM;
  313. -            return(NOMEM);
  314. -        }
  315. -        oldmaxcode = maxcode;
  316. -    }
  317. -    if (hashsize > oldhashsize) {
  318. -        if (
  319. -#ifdef SPLIT_HT
  320. -            alloc_array(CODE, ht[0], (hashsize / 2) + 1, 0)
  321. -            || alloc_array(CODE, ht[1], hashsize / 2, 0)
  322. -#else
  323. -            alloc_array(CODE, ht, hashsize, 0)
  324. -#endif
  325. -        ) {
  326. -            oldhashsize = 0;
  327. -            exit_stat = NOMEM;
  328. -            return(NOMEM);
  329. -        }
  330. -        oldhashsize = hashsize;
  331. -    }
  332. -    return (OK);
  333. -}
  334. -
  335. -# ifdef SPLIT_PFX
  336. -    /*
  337. -     * We have to split pfx[] table in half,
  338. -     * because it's potentially larger than 64k bytes.
  339. -     */
  340. -#   define prefix(code)   (pfx[(code) & 1][(code) >> 1])
  341. -# else
  342. -    /*
  343. -     * Then pfx[] can't be larger than 64k bytes,
  344. -     * or we don't care if it is, so we don't split.
  345. -     */
  346. -#   define prefix(code) (pfx[code])
  347. -# endif
  348. -
  349. -
  350. -/* The initializing of the tables can be done quicker with memset() */
  351. -/* but this way is portable through out the memory models.          */
  352. -/* If you use Microsoft halloc() to allocate the arrays, then       */
  353. -/* include the pragma #pragma function(memset)  and make sure that  */
  354. -/* the length of the memory block is not greater than 64K.          */
  355. -/* This also means that you MUST compile in a model that makes the  */
  356. -/* default pointers to be far pointers (compact or large models).   */
  357. -/* See the file COMPUSI.DOS to modify function emalloc().           */
  358. -
  359. -# ifdef SPLIT_HT
  360. -    /*
  361. -     * We have to split ht[] hash table in half,
  362. -     * because it's potentially larger than 64k bytes.
  363. -     */
  364. -#   define probe(hash)    (ht[(hash) & 1][(hash) >> 1])
  365. -#   define init_tables() \
  366. -    { \
  367. -      hash = hashsize >> 1; \
  368. -      ht[0][hash] = 0; \
  369. -      while (hash--) ht[0][hash] = ht[1][hash] = 0; \
  370. -      highcode = ~(~(CODE)0 << (bits = INITBITS)); \
  371. -      nextfree = (block_compress ? FIRSTFREE : 256); \
  372. -    }
  373. -
  374. -# else
  375. -
  376. -    /*
  377. -     * Then ht[] can't be larger than 64k bytes,
  378. -     * or we don't care if it is, so we don't split.
  379. -     */
  380. -#   define probe(hash) (ht[hash])
  381. -#   define init_tables() \
  382. -    { \
  383. -      hash = hashsize; \
  384. -      while (hash--) ht[hash] = 0; \
  385. -      highcode = ~(~(CODE)0 << (bits = INITBITS)); \
  386. -      nextfree = (block_compress ? FIRSTFREE : 256); \
  387. -    }
  388. -
  389. -# endif
  390. -
  391. -#ifdef COMP40
  392. -/* table clear for block compress */
  393. -/* this is for adaptive reset present in version 4.0 joe release */
  394. -/* DjG, sets it up and returns TRUE to compress and FALSE to not compress */
  395. -int cl_block ()     
  396. -{
  397. -    register long int rat;
  398. -
  399. -    checkpoint = in_count + CHECK_GAP;
  400. -#ifndef NDEBUG
  401. -    if ( debug ) {
  402. -        fprintf ( stderr, "count: %ld, ratio: ", in_count );
  403. -        prratio ( stderr, in_count, bytes_out );
  404. -        fprintf ( stderr, "\n");
  405. -    }
  406. -#endif
  407. -
  408. -    if(in_count > 0x007fffff) {    /* shift will overflow */
  409. -        rat = bytes_out >> 8;
  410. -        if(rat == 0)       /* Don't divide by zero */
  411. -            rat = 0x7fffffff;
  412. -        else
  413. -            rat = in_count / rat;
  414. -    }
  415. -    else
  416. -        rat = (in_count << 8) / bytes_out;  /* 8 fractional bits */
  417. -
  418. -    if ( rat > ratio ){
  419. -        ratio = rat;
  420. -        return FALSE;
  421. -    }
  422. -    else {
  423. -        ratio = 0;
  424. -#ifndef NDEBUG
  425. -        if(debug)
  426. -            fprintf ( stderr, "clear\n" );
  427. -#endif
  428. -        return TRUE;    /* clear the table */
  429. -    }
  430. -    return FALSE; /* don't clear the table */
  431. -}
  432. -#endif
  433. -
  434. -/*
  435. - * compress stdin to stdout    <-- nope
  436. - * NuLib: compress thread_eof bytes from srcfd, writing to dstfd
  437. - *        Sets up a few things and then calls u_compress.
  438. - */
  439. -int u_compress(srcfd, dstfd, thread_eof)
  440. -int srcfd, dstfd;
  441. -long thread_eof;
  442. -{
  443. -    int src2, dst2;
  444. -    long srcposn, dstposn;
  445. -    static char *procName = "u_compress";
  446. -
  447. -    if ((srcposn = lseek(srcfd, 0L, S_REL)) < 0)
  448. -    Fatal("Bad posn lseek(1)", procName);
  449. -    if ((dstposn = lseek(dstfd, 0L, S_REL)) < 0)
  450. -    Fatal("Bad posn lseek(2)", procName);
  451. -
  452. -    src2 = dup(srcfd);
  453. -    dst2 = dup(dstfd);
  454. -
  455. -    /* NuLib: open new stdin/stdout, and seek */
  456. -    if ((nustdin = fdopen(src2, FREAD_STR)) == NULL)
  457. -        Fatal("can't fdopen() nustdin", procName);
  458. -    if ((nustdout = fdopen(dst2, FWRITE_STR)) == NULL)
  459. -        Fatal("can't fdopen() nustdout", procName);
  460. -    setvbuf(nustdin,xbuf,_IOFBF,XBUFSIZE);  /* make the buffers larger */
  461. -    setvbuf(nustdout,zbuf,_IOFBF,ZBUFSIZE);    /* (note setvbuf is a macro) */
  462. -    if (fseek(nustdin, srcposn, S_ABS) < 0)    /* seek may not be needed */
  463. -    Fatal("Bad stream posn lseek(1)", procName);
  464. -    if (fseek(nustdout, dstposn, S_ABS) < 0)
  465. -    Fatal("Bad stream posn lseek(2)", procName);
  466. -
  467. -    oldbits = 0;    /* init for putcode() */
  468. -    compress(thread_eof);
  469. -    check_error();
  470. -
  471. -    fclose(nustdin);        /* note this closes the duped fd */
  472. -    fclose(nustdout);
  473. -    return (exit_stat);
  474. -}
  475. -
  476. -void compress(thread_eof)
  477. -long thread_eof;
  478. -{
  479. -    int c,adjbits;
  480. -    register HASH hash;
  481. -    register CODE code;
  482. -    HASH hashf[256];
  483. -
  484. -    max_bytes_out = thread_eof;        /* NuLib: don't exceed original size */
  485. -    maxcode = Maxcode(maxbits);
  486. -    hashsize = Hashsize(maxbits);
  487. -
  488. -#ifdef COMP40
  489. -/* Only needed for adaptive reset */
  490. -    checkpoint = CHECK_GAP;
  491. -    ratio = 0;
  492. -#endif
  493. -
  494. -    adjbits = maxbits -10;
  495. -    for (c = 256; --c >= 0; ){
  496. -        hashf[c] = ((( c &0x7) << 7) ^ c) << adjbits;
  497. -    }
  498. -    exit_stat = OK;
  499. -    if (alloc_tables(maxcode, hashsize))  /* exit_stat already set */
  500. -        return;
  501. -    init_tables();
  502. -    /* if not zcat or filter (NuLib: never happens) */
  503. -    if(is_list && !zcat_flg) {  /* Open output file */
  504. -        if (freopen(ofname, WRITE_FILE_TYPE, nustdout) == NULL) {
  505. -            exit_stat = NOTOPENED;
  506. -            return;
  507. -        }
  508. -        if (!quiet)
  509. -            fprintf(stderr, "%s: ",ifname);
  510. -        setvbuf(nustdout,zbuf,_IOFBF,ZBUFSIZE);
  511. -    }
  512. - /*
  513. -   * Check the input stream for previously seen strings.  We keep
  514. -   * adding characters to the previously seen prefix string until we
  515. -   * get a character which forms a new (unseen) string.  We then send
  516. -   * the code for the previously seen prefix string, and add the new
  517. -   * string to our tables.  The check for previous strings is done by
  518. -   * hashing.  If the code for the hash value is unused, then we have
  519. -   * a new string.  If the code is used, we check to see if the prefix
  520. -   * and suffix values match the current input; if so, we have found
  521. -   * a previously seen string.  Otherwise, we have a hash collision,
  522. -   * and we try secondary hash probes until we either find the current
  523. -   * string, or we find an unused entry (which indicates a new string).
  524. -   */
  525. -    if (!nomagic) {
  526. -        putc(magic_header[0], nustdout);    /* was putchar() */
  527. -    putc(magic_header[1], nustdout);    /* was putchar() */
  528. -        putc((char)(maxbits | block_compress), nustdout);    /*was putchar*/
  529. -        if(ferror(nustdout)){  /* check it on entry */
  530. -            exit_stat = WRITEERR;
  531. -            return;
  532. -        }
  533. -        bytes_out = 3L;     /* includes 3-byte header mojo */
  534. -    }
  535. -    else
  536. -        bytes_out = 0L;      /* no 3-byte header mojo */
  537. -    in_count = 1L;
  538. -    offset = 0;
  539. -
  540. -    if ((c = getc(nustdin)) == EOF) {    /* NuLib: was getchar() */
  541. -        exit_stat = ferror(nustdin) ? READERR : OK;
  542. -        return;
  543. -    }
  544. -    prefxcode = (CODE)c;
  545. -
  546. -    while ((c = getc(nustdin)) != EOF) {    /* NuLib: was getchar() */
  547. -        in_count++;
  548. -
  549. -/* NuLib : May not be compressing entire file, so can't rely on EOF for end */
  550. -    if (in_count > thread_eof) break;
  551. -
  552. -        hash = prefxcode ^ hashf[c];
  553. -        /* I need to check that my hash value is within range
  554. -        * because my 16-bit hash table is smaller than 64k.
  555. -        */
  556. -        if (hash >= hashsize)
  557. -            hash -= hashsize;
  558. -        if ((code = probe(hash)) != UNUSED) {
  559. -            if (suffix(code) != (char)c || prefix(code) != prefxcode) {
  560. -            /* hashdelta is subtracted from hash on each iteration of
  561. -            * the following hash table search loop.  I compute it once
  562. -            * here to remove it from the loop.
  563. -            */
  564. -                HASH hashdelta = (0x120 - c) << (adjbits);
  565. -                do  {
  566. -                    /* rehash and keep looking */
  567. -                    assert(code >= FIRSTFREE && code <= maxcode);
  568. -                    if (hash >= hashdelta) hash -= hashdelta;
  569. -                        else hash += (hashsize - hashdelta);
  570. -                    assert(hash < hashsize);
  571. -                    if ((code = probe(hash)) == UNUSED)
  572. -                        goto newcode;
  573. -                } while (suffix(code) != (char)c || prefix(code) != prefxcode);
  574. -            }
  575. -            prefxcode = code;
  576. -        }
  577. -        else {
  578. -            newcode: {
  579. -                putcode(prefxcode, bits);
  580. -                code = nextfree;
  581. -                assert(hash < hashsize);
  582. -                assert(code >= FIRSTFREE);
  583. -                assert(code <= maxcode + 1);
  584. -                if (code <= maxcode) {
  585. -                    probe(hash) = code;
  586. -                    prefix(code) = prefxcode;
  587. -                    suffix(code) = (char)c;
  588. -                    if (code > highcode) {
  589. -                        highcode += code;
  590. -                        ++bits;
  591. -                    }
  592. -                    nextfree = code + 1;
  593. -                }
  594. -#ifdef COMP40
  595. -                else if (in_count >= checkpoint && block_compress ) {
  596. -                    if (cl_block()){
  597. -#else
  598. -                else if (block_compress){
  599. -#endif
  600. -                        putcode((CODE)c, bits);
  601. -                        putcode((CODE)CLEAR,bits);
  602. -                        init_tables();
  603. -                        if ((c = getc(nustdin)) == EOF)    /* NuLib: was getchar*/
  604. -                            break;
  605. -                        in_count++;
  606. -#ifdef COMP40
  607. -                    }
  608. -#endif
  609. -                }
  610. -                prefxcode = (CODE)c;
  611. -            }
  612. -        }
  613. -    }
  614. -    putcode(prefxcode, bits);
  615. -    putcode((CODE)CLEAR, 0);
  616. -    if (ferror(nustdout)){ /* check it on exit */
  617. -        exit_stat = WRITEERR;
  618. -        return;
  619. -    }
  620. -    /*
  621. -     * Print out stats on stderr
  622. -     */
  623. -    if(zcat_flg == 0 && !quiet) {
  624. -#ifndef NDEBUG
  625. -        fprintf( stderr,
  626. -            "%ld chars in, (%ld bytes) out, compression factor: ",
  627. -            in_count, bytes_out );
  628. -        prratio( stderr, in_count, bytes_out );
  629. -        fprintf( stderr, "\n");
  630. -        fprintf( stderr, "\tCompression as in compact: " );
  631. -        prratio( stderr, in_count-bytes_out, in_count );
  632. -        fprintf( stderr, "\n");
  633. -        fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
  634. -            prefxcode - 1, bits );
  635. -#else
  636. -        fprintf( stderr, "Compression: " );
  637. -        prratio( stderr, in_count-bytes_out, in_count );
  638. -#endif /* NDEBUG */
  639. -    }
  640. -    if(bytes_out > in_count)      /*  if no savings */
  641. -        exit_stat = NOSAVING;
  642. -
  643. -    packedSize = bytes_out;    /* NuLib : return packed size in global */
  644. -
  645. -    return ;
  646. -}
  647. -
  648. -CONST UCHAR rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  649. -
  650. -void putcode(code,bits)
  651. -CODE code;
  652. -register int bits;
  653. -{
  654. -  static UCHAR outbuf[MAXBITS];
  655. -  register UCHAR *buf;
  656. -  register int shift;
  657. -  register int ok_to_write;    /* NuLib (kludge... sorry) */
  658. -
  659. -  ok_to_write = (exit_stat != NOSAVING);
  660. -
  661. -  if (bits != oldbits) {
  662. -    if (bits == 0) {
  663. -      /* bits == 0 means EOF, write the rest of the buffer. */
  664. -      if (offset > 0) {
  665. -    int x = ((offset+7) >> 3);    /* NuLib */
  666. -
  667. -    if ((bytes_out + x) > max_bytes_out) {    /* NuLib */
  668. -        /* compression failed.  There's no clean way of bailing out
  669. -        /* (could use setjmp/longjmp, but that may not be supported
  670. -        /* on all systems), so just don't write anything.
  671. -         */
  672. -        exit_stat = NOSAVING;
  673. -        ok_to_write = FALSE;
  674. -    } else {
  675. -/*          fwrite(outbuf,1,(offset +7) >> 3, nustdout);*/
  676. -        fwrite(outbuf,1, x, nustdout);
  677. -    }
  678. -/*        bytes_out += ((offset +7) >> 3);*/
  679. -    bytes_out += x;
  680. -      }
  681. -      offset = 0;
  682. -      oldbits = 0;
  683. -      fflush(nustdout);
  684. -      return;
  685. -    }
  686. -    else {
  687. -      /* Change the code size.  We must write the whole buffer,
  688. -       * because the expand side won't discover the size change
  689. -       * until after it has read a buffer full.
  690. -       */
  691. -      if (offset > 0) {
  692. -        if (ok_to_write) fwrite(outbuf, 1, oldbits, nustdout);
  693. -        bytes_out += oldbits;
  694. -        offset = 0;
  695. -      }
  696. -      oldbits = bits;
  697. -#ifndef NDEBUG
  698. -      if ( debug )
  699. -        fprintf( stderr, "\nChange to %d bits\n", bits );
  700. -#endif /* !NDEBUG */
  701. -    }
  702. -  }
  703. -  /*  Get to the first byte. */
  704. -  buf = outbuf + ((shift = offset) >> 3);
  705. -  if ((shift &= 7) != 0) {
  706. -    *(buf) |= (*buf & rmask[shift]) | (UCHAR)(code << shift);
  707. -    *(++buf) = (UCHAR)(code >> (8 - shift));
  708. -    if (bits + shift > 16)
  709. -        *(++buf) = (UCHAR)(code >> (16 - shift));
  710. -  }
  711. -  else {
  712. -    /* Special case for fast execution */
  713. -    *(buf) = (UCHAR)code;
  714. -    *(++buf) = (UCHAR)(code >> 8);
  715. -  }
  716. -  if ((offset += bits) == (bits << 3)) {
  717. -    bytes_out += bits;
  718. -    if (ok_to_write) fwrite(outbuf,1,bits,nustdout);
  719. -    offset = 0;
  720. -  }
  721. -  return;
  722. -}
  723. -
  724. -int nextcode(codeptr)
  725. -CODE *codeptr;
  726. -/* Get the next code from input and put it in *codeptr.
  727. - * Return (TRUE) on success, or return (FALSE) on end-of-file.
  728. - * Adapted from COMPRESS V4.0.
  729. - */
  730. -{
  731. -  register CODE code;
  732. -  static int size;
  733. -  static UCHAR inbuf[MAXBITS];
  734. -  register int shift;
  735. -  UCHAR *bp;
  736. -
  737. -  /* If the next entry is a different bit-size than the preceeding one
  738. -   * then we must adjust the size and scrap the old buffer.
  739. -   */
  740. -  if (prevbits != bits) {
  741. -    prevbits = bits;
  742. -    size = 0;
  743. -  }
  744. -  /* If we can't read another code from the buffer, then refill it.
  745. -   */
  746. -  if (size - (shift = offset) < bits) {
  747. -    static int bytesize;    /* NuLib: sigh */
  748. -    /* Read more input and convert size from # of bytes to # of bits */
  749. -
  750. -    /* NuLib: stop after comp_thread_eof bytes */
  751. -    if (nubytes_read >= nucomp_thread_eof)
  752. -      return(NO);
  753. -
  754. -    /* NuLib: replace old fread command with... */
  755. -    /*
  756. -    if ((size = fread(inbuf, 1, bits, nustdin) << 3) <= 0 || ferror(nustdin))
  757. -      return(NO);
  758. -    */
  759. -
  760. -    bytesize = fread(inbuf, 1, bits, nustdin);
  761. -    if (nubytes_read + bits > nucomp_thread_eof) {
  762. -    bytesize = nucomp_thread_eof - nubytes_read;
  763. -    }
  764. -    size = bytesize << 3;
  765. -    if (size <= 0 || ferror(nustdin))
  766. -    return (NO);
  767. -
  768. -    /* NuLib: increment nubytes_read */
  769. -    nubytes_read += (long) bytesize;
  770. -
  771. -    offset = shift = 0;
  772. -  }
  773. -  /* Get to the first byte. */
  774. -  bp = inbuf + (shift >> 3);
  775. -  /* Get first part (low order bits) */
  776. -  code = (*bp++ >> (shift &= 7));
  777. -  /* high order bits. */
  778. -  code |= *bp++ << (shift = 8 - shift);
  779. -  if ((shift += 8) < bits) code |= *bp << shift;
  780. -  *codeptr = code & highcode;
  781. -  offset += bits;
  782. -  return (TRUE);
  783. -}
  784. -
  785. -/*
  786. - * NuLib: uncompress comp_thread_eof bytes from srcfd, writing to dstfd
  787. - *        Sets up a few things and then calls compress.
  788. - */
  789. -int u_decompress(srcfd, dstfd, comp_thread_eof)
  790. -int srcfd, dstfd;
  791. -long comp_thread_eof;
  792. -{
  793. -    int src2, dst2;
  794. -    long srcposn, dstposn;
  795. -    static char *procName = "u_decompress";
  796. -
  797. -    if ((srcposn = lseek(srcfd, 0L, S_REL)) < 0)
  798. -    Fatal("Bad posn lseek(1)", procName);
  799. -    if ((dstposn = lseek(dstfd, 0L, S_REL)) < 0)
  800. -    Fatal("Bad posn lseek(2)", procName);
  801. -
  802. -    src2 = dup(srcfd);
  803. -    dst2 = dup(dstfd);
  804. -
  805. -    /* NuLib: open new stdin/stdout, and seek */
  806. -    if ((nustdin = fdopen(src2, FREAD_STR)) == NULL)
  807. -        Fatal("can't fdopen() nustdin", procName);
  808. -    if ((nustdout = fdopen(dst2, FWRITE_STR)) == NULL)
  809. -        Fatal("can't fdopen() nustdout", procName);
  810. -    setvbuf(nustdin,zbuf,_IOFBF,ZBUFSIZE);  /* make the buffers larger */
  811. -    setvbuf(nustdout,xbuf,_IOFBF,XBUFSIZE); /* (note order diff from comp) */
  812. -    if (fseek(nustdin, srcposn, S_ABS) < 0)    /* seek may not be needed */
  813. -    Fatal("Bad stream posn lseek(1)", procName);
  814. -    if (fseek(nustdout, dstposn, S_ABS) < 0)
  815. -    Fatal("Bad stream posn lseek(2)", procName);
  816. -
  817. -    /* Check the magic number */
  818. -    if (!nomagic) {
  819. -    if ((getc(nustdin)!=(magic_header[0] & 0xFF))    /* NuLib: was getchar*/
  820. -     || (getc(nustdin)!=(magic_header[1] & 0xFF))) {/* NuLib: was getchar*/
  821. -        fprintf(stderr, "decompress: not in compressed format\n");
  822. -        return(-1);    /* NuLib: was exit(ERROR) */
  823. -    }
  824. -    maxbits = getc(nustdin);    /* set -b from file (NuLib: was getchar) */
  825. -    block_compress = maxbits & BLOCK_MASK;
  826. -    maxbits &= BIT_MASK;
  827. -    if(maxbits > MAXBITS) {
  828. -        fprintf(stderr,
  829. -        "decompress: compressed with %d bits, can only handle %d bits\n",
  830. -        maxbits, MAXBITS);
  831. -        return(-1);    /* NuLib: was exit(ERROR) */
  832. -    }
  833. -    nubytes_read = 3L;
  834. -    } else {
  835. -    nubytes_read = 0L;
  836. -    }
  837. -
  838. -    nucomp_thread_eof = comp_thread_eof;
  839. -/*    printf("src file posn = %ld\n", ftell(nustdin));*/
  840. -    prevbits = 0;    /* init for nextcode() */
  841. -    decompress();
  842. -    check_error();
  843. -
  844. -    fclose(nustdin);        /* note this closes the duped fd */
  845. -    fclose(nustdout);
  846. -    return (exit_stat);
  847. -}
  848. -
  849. -void decompress()
  850. -{
  851. -  register int i;
  852. -  register CODE code;
  853. -  char sufxchar;
  854. -  CODE savecode;
  855. -  FLAG fulltable, cleartable;
  856. -  static char token[MAXTOKLEN];         /* String buffer to build token */
  857. -
  858. -  exit_stat = OK;
  859. -
  860. -  if (alloc_tables(maxcode = ~(~(CODE)0 << maxbits),0)) /* exit_stat already set */
  861. -     return;
  862. -
  863. -    /* if not zcat or filter (NuLib: never) */
  864. -    if(is_list && !zcat_flg) {  /* Open output file */
  865. -        if (freopen(ofname, WRITE_FILE_TYPE, nustdout) == NULL) {
  866. -            exit_stat = NOTOPENED;
  867. -            return;
  868. -        }
  869. -        if (!quiet)
  870. -            fprintf(stderr, "%s: ",ifname);
  871. -        setvbuf(nustdout,xbuf,_IOFBF,XBUFSIZE);
  872. -    }
  873. -  cleartable = TRUE;
  874. -  savecode = CLEAR;
  875. -  offset = 0;
  876. -  do {
  877. -    if ((code = savecode) == CLEAR && cleartable) {
  878. -      highcode = ~(~(CODE)0 << (bits = INITBITS));
  879. -      fulltable = FALSE;
  880. -      nextfree = (cleartable = block_compress) == FALSE ? 256 : FIRSTFREE;
  881. -      if (!nextcode(&prefxcode))
  882. -        break;
  883. -      putc((sufxchar = (char)prefxcode), nustdout);
  884. -      continue;
  885. -    }
  886. -    i = 0;
  887. -    if (code >= nextfree && !fulltable) {
  888. -      if (code != nextfree){
  889. -        exit_stat = CODEBAD;
  890. -/*    fprintf(stderr, "Bad code; nubytes_read = %ld\n", nubytes_read); */
  891. -    /* CDEBUG */
  892. -        return ;     /* Non-existant code */
  893. -    }
  894. -      /* Special case for sequence KwKwK (see text of article)         */
  895. -      code = prefxcode;
  896. -      token[i++] = sufxchar;
  897. -    }
  898. -    /* Build the token string in reverse order by chasing down through
  899. -     * successive prefix tokens of the current token.  Then output it.
  900. -     */
  901. -    while (code >= 256) {
  902. -#ifndef NDEBUG
  903. -        /* These are checks to ease paranoia. Prefix codes must decrease
  904. -         * monotonically, otherwise we must have corrupt tables.  We can
  905. -         * also check that we haven't overrun the token buffer.
  906. -         */
  907. -        if (code <= prefix(code)){
  908. -            exit_stat= TABLEBAD;
  909. -            return;
  910. -        }
  911. -        if (i >= MAXTOKLEN){
  912. -            exit_stat = TOKTOOBIG;
  913. -            return;
  914. -        }
  915. -#endif
  916. -      token[i++] = suffix(code);
  917. -      code = prefix(code);
  918. -    }
  919. -    putc(sufxchar = (char)code, nustdout);
  920. -    while (--i >= 0)
  921. -        putc(token[i], nustdout);
  922. -    if (ferror(nustdout)) {
  923. -        exit_stat = WRITEERR;
  924. -        return;
  925. -    }
  926. -    /* If table isn't full, add new token code to the table with
  927. -     * codeprefix and codesuffix, and remember current code.
  928. -     */
  929. -    if (!fulltable) {
  930. -      code = nextfree;
  931. -      assert(256 <= code && code <= maxcode);
  932. -      prefix(code) = prefxcode;
  933. -      suffix(code) = sufxchar;
  934. -      prefxcode = savecode;
  935. -      if (code++ == highcode) {
  936. -        if (highcode >= maxcode) {
  937. -          fulltable = TRUE;
  938. -          --code;
  939. -        }
  940. -        else {
  941. -          ++bits;
  942. -          highcode += code;           /* nextfree == highcode + 1 */
  943. -        }
  944. -      }
  945. -      nextfree = code;
  946. -    }
  947. -
  948. -  } while (nextcode(&savecode));
  949. -  exit_stat = (ferror(nustdin))? READERR : OK;
  950. -
  951. -  return ;
  952. -}
  953. -
  954. -
  955. -/*
  956. - * These are routines pulled out of "compress.c" from compress v4.3.
  957. - */
  958. -void prratio(stream, num, den)
  959. -FILE *stream;
  960. -long int num, den;
  961. -{
  962. -    register int q;         /* Doesn't need to be long */
  963. -
  964. -    if(num > 214748L) {     /* 2147483647/10000 */
  965. -        q = (int) (num / (den / 10000L));
  966. -    }
  967. -    else {
  968. -        q = (int) (10000L * num / den);     /* Long calculations, though */
  969. -    }
  970. -    if (q < 0) {
  971. -        putc('-', stream);
  972. -        q = -q;
  973. -    }
  974. -    fprintf(stream, "%d.%02d%%", q / 100, q % 100);
  975. -}
  976. -
  977. -/*
  978. - * Check exit status from compress() and decompress()
  979. - *
  980. - * exit_stat is a global var.  Either returns something interesting or
  981. - * bails out completely.
  982. - */
  983. -int check_error()     /* returning OK continues with processing next file */
  984. -{
  985. -    prog_name = prgName;    /* NuLib: set prog_name to "nulib" */
  986. -
  987. -    switch(exit_stat) {
  988. -  case OK:
  989. -    return (OK);
  990. -  case NOMEM:
  991. -    if (do_decomp)
  992. -        fprintf(stderr,"%s: not enough memory to decompress '%s'.\n", prog_name, ifname);
  993. -    else
  994. -        fprintf(stderr,"%s: not enough memory to compress '%s'.\n", prog_name, ifname);
  995. -    return(OK);
  996. -  case SIGNAL_ERROR:
  997. -    fprintf(stderr,"%s: error setting signal interupt.\n",prog_name);
  998. -    exit(ERROR);
  999. -    break;
  1000. -  case READERR:
  1001. -    fprintf(stderr,"%s: read error on input '%s'.\n", prog_name, ifname);
  1002. -    break;
  1003. -  case WRITEERR:
  1004. -    fprintf(stderr,"%s: write error on output '%s'.\n", prog_name, ofname);
  1005. -    break;
  1006. -   case TOKTOOBIG:
  1007. -    fprintf(stderr,"%s: token too long in '%s'.\n", prog_name, ifname);
  1008. -    break;
  1009. -  case INFILEBAD:
  1010. -    fprintf(stderr, "%s: '%s' in unknown compressed format.\n", prog_name, ifname);
  1011. -    break;
  1012. - case CODEBAD:
  1013. -    fprintf(stderr,"%s: file token bad in '%s'.\n", prog_name,ifname);
  1014. -    break;
  1015. - case TABLEBAD:
  1016. -    fprintf(stderr,"%s: internal error -- tables corrupted.\n", prog_name);
  1017. -    break;
  1018. -  case NOTOPENED:
  1019. -    fprintf(stderr,"%s: could not open output file %s\n",prog_name,ofname);
  1020. -    exit(ERROR);
  1021. -    break;
  1022. -  case NOSAVING:
  1023. -    if (force)
  1024. -        exit_stat = OK;
  1025. -    return (OK);
  1026. -  default:
  1027. -    fprintf(stderr,"%s: internal error -- illegal return value = %d.\n", prog_name,exit_stat);
  1028. -  }
  1029. -  if (!zcat_flg && !keep_error){
  1030. -        fclose(nustdout);         /* won't get here without an error */
  1031. -        unlink ( ofname );
  1032. -    }
  1033. -  exit(exit_stat);
  1034. -  return(ERROR);
  1035. -}
  1036. -
  1037. -/*
  1038. - * These are routines from "compusi.c"
  1039. - */
  1040. -void version()
  1041. -{
  1042. -#ifdef XENIX
  1043. -#ifndef NDEBUG
  1044. -    fprintf(stderr, "%s\nOptions: Xenix %s MAXBITS = %d\n", rcs_ident,
  1045. -        "DEBUG",MAXBITS);
  1046. -#else
  1047. -    fprintf(stderr, "%s\nOptions: Xenix MAXBITS = %d\n", rcs_ident,MAXBITS);
  1048. -#endif
  1049. -#else
  1050. -#ifndef NDEBUG
  1051. -    fprintf(stderr, "%s\nOptions: Unix %s MAXBITS = %d\n", rcs_ident,
  1052. -        "DEBUG",MAXBITS);
  1053. -#else
  1054. -    fprintf(stderr, "%s\nOptions: Unix MAXBITS = %d\n", rcs_ident,MAXBITS);
  1055. -#endif
  1056. -#endif
  1057. -}
  1058. -
  1059. -ALLOCTYPE FAR *emalloc(x,y)
  1060. -unsigned int x;
  1061. -int y;
  1062. -{
  1063. -    ALLOCTYPE FAR *p;
  1064. -    p = (ALLOCTYPE FAR *)ALLOCATE(x,y);
  1065. -    return(p);
  1066. -}
  1067. -
  1068. -void efree(ptr)
  1069. -ALLOCTYPE FAR *ptr;
  1070. -{
  1071. -    FREEIT(ptr);
  1072. -}
  1073. -
  1074. + END OF ARCHIVE
  1075.