Thread View: comp.sources.apple2
1 messages
1 total messages
Started by Jonathan A. Chandross
Wed, 01 May 1991 22:08
v001SRC032: Nulib - Archive Library Tools (Unix) 01/10
Author: Jonathan A. Chandross
Date: Wed, 01 May 1991 22:08
Date: Wed, 01 May 1991 22:08
1067 lines
37676 bytes
37676 bytes
Submitted-by: Andy McFadden (fadden@cory.berkeley.edu)
Posting-number: Volume 1, Source:32
Archive-name: archive/unix/nulib/part01.10
Architecture: UNIX
Version-number: 3.03
Nulib allows handles many of the archiving formats used on the Apple.
Very handy indeed.
Enjoy.
=README
-Nulib v3.03 (February 1991)
-- Fixed XENIX problems with includes and libs (Ron Higgins).
-- Fixed bug in directory expansion (Larry W. Virden).
-NuLib v3.02
-- Silenced screaming about bad dates (Larry W. Virden).
-- Fixed glitches in nulib.lnk and nulib.mak (Bruce Kahn).
-NuLib v3.01
-- Fixed non-compression bug in ShrinkIt LZW (Scott Blackman).
-
-NuLib v3.0 README (September 1990)
-
-New items in 3.0:
-- ShrinkIt LZW compression
-- UNIX 12-bit and 16-bit compression
-- New archive listing format (similar to ARC and ZOO)
-
-Things work much better if you read the documentation file (now available
-on the archive site... sorry I didn't put it up sooner). If you want to
-use UNIX compress to store files, READ THE DOCUMENTATION FIRST. Not only
-does it tell you how to do it, but it has some warnings about compatibility.
-
-Note that v3.0 does *NOT* unpack archives compressed with GS/ShrinkIt. The
-problem is that NuLib cannot at present decode LZW/II compression. You can
-read comments and extract files that were added without compression, but
-that's about it.
-
-To compile this on a UNIX-type system, edit the file "nudefs.h". Several
-systems are predefined; the default is a BSD UNIX system. If you want
-to run this on something other than BSD, comment out the #define statements
-(using "/*" and "*/"), and uncomment the appropriate statements. Then,
-type "make" to execute the Makefile. If all goes well, you will be
-left with an executable file called "nulib". If all does not go well,
-double check "nudefs.h". Send some mail to me if you can't get it to work
-at all.
-
-Currently AT&T 3B2 machines seem to be very uncooperative. If somebody gets
-NuLib to run on one, please let me know. The problem is in the directory
-manipulation routines (struct dirent, opendir(), readdir(), etc).
-
-To make the MS-DOS version, use the nulib.mak and nulib.lnk files with MS C
-(supplied by Bruce Kahn). To make the APW version, put all the files in
-one directory, and make a subdirectory called "OBJ". Put the "linked.scr"
-and "linker.scr" files in OBJ, and then "make.apw". This will compile all
-the files. When it finishes, change to OBJ and "alink linked.scr" (standard
-linker) or "alink linker.scr" (ZapLink). The makefile used to do this
-automatically, but with only 1.25MB of RAM you have to exit APW to purge
-all the memory used by the compiler, and and then restart APW and
-run the linker.
-
-In both cases, BE SURE to modify "nudefs.h" first. If you don't, the
-compilation will halt in "numain.c" on a line which reminds you to change
-"nudefs.h" (I tended to forget about this). Also, make sure all the file
-types are set to SRC, and the auxtype to CC. These are changed with the
-commands "filetype" and "change", respectively.
-
-Please send bug reports, ideas, or gripes to fadden@cory.berkeley.edu, or to
-one of the addresses mentioned in the documentation or under the "-hw"
-option.
-
-Known bugs:
- - Under some systems, using UNIX compress on a file which does not compress
-will cause the archive's EOF to be larger than it should be. This slack
-space will be used up if you add more files to the archive (with NuLib
-anyway; no guarantees about ShrinkIt or GS/ShrinkIt, but there's no reason
-why they shouldn't work).
-
-(just to make things clear: if the file being compressed doesn't get any
-smaller, the compression halts and the file is simply stored uncompressed.
-Because of the way compress works, on some systems the space that would
-have been occupied by more compressed data is left attached to the file.
-The ShrinkIt compression does not suffer from this problem. If you add
-more stuff to the file, NuLib will fill the slack space first, NOT just
-append to the end of the file).
-
-Things to come:
- - LZW/II decompression (for GS/ShrinkIt archives)
- - Support for UNIX tar archives
- - CRLF translations while adding files
- - Better handling of comments
-
-Don't hold your breath waiting for these...
-
-I can be reached at:
- fadden@cory.berkeley.edu (primary e-mail account)
- fadden@hermes.berkeley.edu (secondary e-mail, since primary is buggy)
-
-All this stuff, and documentation as well, is available via anonymous FTP at:
- avalanche.berkeley.edu
- tornado.berkeley.edu
- headcrash.berkeley.edu
- ...
-in pub/Apple2
-
=nucomp.c
-/*
- * nucomp.c - code to perform UNIX style LZW compression
- *
- * NuLib v3.0 February 1991 Freeware (distribute, don't sell)
- * By Andy McFadden (fadden@cory.berkeley.edu)
- *
- * This is the main compression code from compress v4.3. Modifications
- * have been made to integrate it with NuLib (primarily in that it no longer
- * uses stdin/stdout), but it's functionally the same.
- */
-#ifdef APW
-segment "Compress"
-#endif
-
-#include "nudefs.h"
-#include "nupak.h"
-#define MAIN /* cause nucomp.h to alloc global vars */
-
-/*@H************************ < COMPRESS API > ****************************
-* *
-* compress : compapi.c <current version of compress algorithm> *
-* *
-* port by : Donald J. Gloistein *
-* *
-* Source, Documentation, Object Code: *
-* released to Public Domain. This code is based on code as documented *
-* below in release notes. *
-* *
-*--------------------------- Module Description --------------------------*
-* Contains source code for modified Lempel-Ziv method (LZW) compression *
-* and decompression. *
-* *
-* This code module can be maintained to keep current on releases on the *
-* Unix system. The command shell and dos modules can remain the same. *
-* *
-*--------------------------- Implementation Notes --------------------------*
-* *
-* compiled with : compress.h compress.fns compress.c *
-* linked with : compress.obj compusi.obj *
-* *
-* problems: *
-* *
-* *
-* CAUTION: Uses a number of defines for access and speed. If you change *
-* anything, make sure about side effects. *
-* *
-* Compression: *
-* Algorithm: use open addressing double hashing (no chaining) on the *
-* prefix code / next character combination. We do a variant of Knuth's *
-* algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime *
-* secondary probe. Here, the modular division first probe is gives way *
-* to a faster exclusive-or manipulation. *
-* Also block compression with an adaptive reset was used in original code, *
-* whereby the code table is cleared when the compression ration decreases *
-* but after the table fills. This was removed from this edition. The table *
-* is re-sized at this point when it is filled , and a special CLEAR code is *
-* generated for the decompressor. This results in some size difference from *
-* straight version 4.0 joe Release. But it is fully compatible in both v4.0 *
-* and v4.01 *
-* *
-* Decompression: *
-* This routine adapts to the codes in the file building the "string" table *
-* on-the-fly; requiring no table to be stored in the compressed file. The *
-* tables used herein are shared with those of the compress() routine. *
-* *
-* Initials ---- Name --------------------------------- *
-* DjG Donald J. Gloistein, current port to MsDos 16 bit *
-* Plus many others, see rev.hst file for full list *
-* LvR Lyle V. Rains, many thanks for improved implementation *
-* of the compression and decompression routines. *
-*************************************************************************@H*/
-
-#include <stdio.h>
-#define assert(x)
-#include "nucomp.h" /* contains the rest of the include file declarations */
-
-FILE *nustdin, *nustdout; /* NuLib: use these instead of stdin/stdout */
-long nubytes_read, nucomp_thread_eof; /* NuLib: used in nextcode (decomp) */
-
-/* NuLib: pulled this out of nextcode() so we can initialize it every time */
-static int prevbits = 0;
-/* NuLib: pulled out of putcode() */
-static int oldbits = 0;
-
-static int offset;
-static long int in_count ; /* length of input */
-static long int bytes_out; /* length of compressed output */
-static long int max_bytes_out; /* NuLib: max #of bytes to output */
-
-static CODE prefxcode, nextfree;
-static CODE highcode;
-static CODE maxcode;
-static HASH hashsize;
-static int bits;
-
-
-/*
- * The following two parameter tables are the hash table sizes and
- * maximum code values for various code bit-lengths. The requirements
- * are that Hashsize[n] must be a prime number and Maxcode[n] must be less
- * than Maxhash[n]. Table occupancy factor is (Maxcode - 256)/Maxhash.
- * Note: I am using a lower Maxcode for 16-bit codes in order to
- * keep the hash table size less than 64k entries.
- */
-CONST HASH hs[] = {
- 0x13FF, /* 12-bit codes, 75% occupancy */
- 0x26C3, /* 13-bit codes, 80% occupancy */
- 0x4A1D, /* 14-bit codes, 85% occupancy */
- 0x8D0D, /* 15-bit codes, 90% occupancy */
- 0xFFD9 /* 16-bit codes, 94% occupancy, 6% of code values unused */
-};
-#define Hashsize(maxb) (hs[(maxb) -MINBITS])
-
-CONST CODE mc[] = {
- 0x0FFF, /* 12-bit codes */
- 0x1FFF, /* 13-bit codes */
- 0x3FFF, /* 14-bit codes */
- 0x7FFF, /* 15-bit codes */
- 0xEFFF /* 16-bit codes, 6% of code values unused */
-};
-#define Maxcode(maxb) (mc[(maxb) -MINBITS])
-
-#define allocx(type,ptr,size) \
- (((ptr) = (type FAR *) emalloc((unsigned int)(size),sizeof(type))) == NULLPTR(type) \
- ? NOMEM : OK \
- )
-
-#define free_array(type,ptr,offset) \
- if (ptr != NULLPTR(type)) { \
- efree((ALLOCTYPE FAR *)((ptr) + (offset))); \
- (ptr) = NULLPTR(type); \
- }
-
- /*
- * Macro to allocate new memory to a pointer with an offset value.
- */
-#define alloc_array(type, ptr, size, offset) \
- ( allocx(type, ptr, (size) - (offset)) != OK \
- ? NOMEM \
- : (((ptr) -= (offset)), OK) \
- )
-
-static char FAR *sfx = NULLPTR(char) ;
-#define suffix(code) sfx[code]
-
-
-#ifdef SPLIT_PFX
- static CODE FAR *pfx[2] = {NULLPTR(CODE), NULLPTR(CODE)};
-#else
- static CODE FAR *pfx = NULLPTR(CODE);
-#endif
-
-
-#ifdef SPLIT_HT
- static CODE FAR *ht[2] = {NULLPTR(CODE),NULLPTR(CODE)};
-#else
- static CODE FAR *ht = NULLPTR(CODE);
-#endif
-
-
-int alloc_tables(maxcode, hashsize)
- CODE maxcode;
- HASH hashsize;
-{
- static CODE oldmaxcode = 0;
- static HASH oldhashsize = 0;
-
- if (hashsize > oldhashsize) {
-#ifdef SPLIT_HT
- free_array(CODE,ht[1], 0);
- free_array(CODE,ht[0], 0);
-#else
- free_array(CODE,ht, 0);
-#endif
- oldhashsize = 0;
- }
-
- if (maxcode > oldmaxcode) {
-#ifdef SPLIT_PFX
- free_array(CODE,pfx[1], 128);
- free_array(CODE,pfx[0], 128);
-#else
- free_array(CODE,pfx, 256);
-#endif
- free_array(char,sfx, 256);
-
- if ( alloc_array(char, sfx, maxcode + 1, 256)
-#ifdef SPLIT_PFX
- || alloc_array(CODE, pfx[0], (maxcode + 1) / 2, 128)
- || alloc_array(CODE, pfx[1], (maxcode + 1) / 2, 128)
-#else
- || alloc_array(CODE, pfx, (maxcode + 1), 256)
-#endif
- ) {
- oldmaxcode = 0;
- exit_stat = NOMEM;
- return(NOMEM);
- }
- oldmaxcode = maxcode;
- }
- if (hashsize > oldhashsize) {
- if (
-#ifdef SPLIT_HT
- alloc_array(CODE, ht[0], (hashsize / 2) + 1, 0)
- || alloc_array(CODE, ht[1], hashsize / 2, 0)
-#else
- alloc_array(CODE, ht, hashsize, 0)
-#endif
- ) {
- oldhashsize = 0;
- exit_stat = NOMEM;
- return(NOMEM);
- }
- oldhashsize = hashsize;
- }
- return (OK);
-}
-
-# ifdef SPLIT_PFX
- /*
- * We have to split pfx[] table in half,
- * because it's potentially larger than 64k bytes.
- */
-# define prefix(code) (pfx[(code) & 1][(code) >> 1])
-# else
- /*
- * Then pfx[] can't be larger than 64k bytes,
- * or we don't care if it is, so we don't split.
- */
-# define prefix(code) (pfx[code])
-# endif
-
-
-/* The initializing of the tables can be done quicker with memset() */
-/* but this way is portable through out the memory models. */
-/* If you use Microsoft halloc() to allocate the arrays, then */
-/* include the pragma #pragma function(memset) and make sure that */
-/* the length of the memory block is not greater than 64K. */
-/* This also means that you MUST compile in a model that makes the */
-/* default pointers to be far pointers (compact or large models). */
-/* See the file COMPUSI.DOS to modify function emalloc(). */
-
-# ifdef SPLIT_HT
- /*
- * We have to split ht[] hash table in half,
- * because it's potentially larger than 64k bytes.
- */
-# define probe(hash) (ht[(hash) & 1][(hash) >> 1])
-# define init_tables() \
- { \
- hash = hashsize >> 1; \
- ht[0][hash] = 0; \
- while (hash--) ht[0][hash] = ht[1][hash] = 0; \
- highcode = ~(~(CODE)0 << (bits = INITBITS)); \
- nextfree = (block_compress ? FIRSTFREE : 256); \
- }
-
-# else
-
- /*
- * Then ht[] can't be larger than 64k bytes,
- * or we don't care if it is, so we don't split.
- */
-# define probe(hash) (ht[hash])
-# define init_tables() \
- { \
- hash = hashsize; \
- while (hash--) ht[hash] = 0; \
- highcode = ~(~(CODE)0 << (bits = INITBITS)); \
- nextfree = (block_compress ? FIRSTFREE : 256); \
- }
-
-# endif
-
-#ifdef COMP40
-/* table clear for block compress */
-/* this is for adaptive reset present in version 4.0 joe release */
-/* DjG, sets it up and returns TRUE to compress and FALSE to not compress */
-int cl_block ()
-{
- register long int rat;
-
- checkpoint = in_count + CHECK_GAP;
-#ifndef NDEBUG
- if ( debug ) {
- fprintf ( stderr, "count: %ld, ratio: ", in_count );
- prratio ( stderr, in_count, bytes_out );
- fprintf ( stderr, "\n");
- }
-#endif
-
- if(in_count > 0x007fffff) { /* shift will overflow */
- rat = bytes_out >> 8;
- if(rat == 0) /* Don't divide by zero */
- rat = 0x7fffffff;
- else
- rat = in_count / rat;
- }
- else
- rat = (in_count << 8) / bytes_out; /* 8 fractional bits */
-
- if ( rat > ratio ){
- ratio = rat;
- return FALSE;
- }
- else {
- ratio = 0;
-#ifndef NDEBUG
- if(debug)
- fprintf ( stderr, "clear\n" );
-#endif
- return TRUE; /* clear the table */
- }
- return FALSE; /* don't clear the table */
-}
-#endif
-
-/*
- * compress stdin to stdout <-- nope
- * NuLib: compress thread_eof bytes from srcfd, writing to dstfd
- * Sets up a few things and then calls u_compress.
- */
-int u_compress(srcfd, dstfd, thread_eof)
-int srcfd, dstfd;
-long thread_eof;
-{
- int src2, dst2;
- long srcposn, dstposn;
- static char *procName = "u_compress";
-
- if ((srcposn = lseek(srcfd, 0L, S_REL)) < 0)
- Fatal("Bad posn lseek(1)", procName);
- if ((dstposn = lseek(dstfd, 0L, S_REL)) < 0)
- Fatal("Bad posn lseek(2)", procName);
-
- src2 = dup(srcfd);
- dst2 = dup(dstfd);
-
- /* NuLib: open new stdin/stdout, and seek */
- if ((nustdin = fdopen(src2, FREAD_STR)) == NULL)
- Fatal("can't fdopen() nustdin", procName);
- if ((nustdout = fdopen(dst2, FWRITE_STR)) == NULL)
- Fatal("can't fdopen() nustdout", procName);
- setvbuf(nustdin,xbuf,_IOFBF,XBUFSIZE); /* make the buffers larger */
- setvbuf(nustdout,zbuf,_IOFBF,ZBUFSIZE); /* (note setvbuf is a macro) */
- if (fseek(nustdin, srcposn, S_ABS) < 0) /* seek may not be needed */
- Fatal("Bad stream posn lseek(1)", procName);
- if (fseek(nustdout, dstposn, S_ABS) < 0)
- Fatal("Bad stream posn lseek(2)", procName);
-
- oldbits = 0; /* init for putcode() */
- compress(thread_eof);
- check_error();
-
- fclose(nustdin); /* note this closes the duped fd */
- fclose(nustdout);
- return (exit_stat);
-}
-
-void compress(thread_eof)
-long thread_eof;
-{
- int c,adjbits;
- register HASH hash;
- register CODE code;
- HASH hashf[256];
-
- max_bytes_out = thread_eof; /* NuLib: don't exceed original size */
- maxcode = Maxcode(maxbits);
- hashsize = Hashsize(maxbits);
-
-#ifdef COMP40
-/* Only needed for adaptive reset */
- checkpoint = CHECK_GAP;
- ratio = 0;
-#endif
-
- adjbits = maxbits -10;
- for (c = 256; --c >= 0; ){
- hashf[c] = ((( c &0x7) << 7) ^ c) << adjbits;
- }
- exit_stat = OK;
- if (alloc_tables(maxcode, hashsize)) /* exit_stat already set */
- return;
- init_tables();
- /* if not zcat or filter (NuLib: never happens) */
- if(is_list && !zcat_flg) { /* Open output file */
- if (freopen(ofname, WRITE_FILE_TYPE, nustdout) == NULL) {
- exit_stat = NOTOPENED;
- return;
- }
- if (!quiet)
- fprintf(stderr, "%s: ",ifname);
- setvbuf(nustdout,zbuf,_IOFBF,ZBUFSIZE);
- }
- /*
- * Check the input stream for previously seen strings. We keep
- * adding characters to the previously seen prefix string until we
- * get a character which forms a new (unseen) string. We then send
- * the code for the previously seen prefix string, and add the new
- * string to our tables. The check for previous strings is done by
- * hashing. If the code for the hash value is unused, then we have
- * a new string. If the code is used, we check to see if the prefix
- * and suffix values match the current input; if so, we have found
- * a previously seen string. Otherwise, we have a hash collision,
- * and we try secondary hash probes until we either find the current
- * string, or we find an unused entry (which indicates a new string).
- */
- if (!nomagic) {
- putc(magic_header[0], nustdout); /* was putchar() */
- putc(magic_header[1], nustdout); /* was putchar() */
- putc((char)(maxbits | block_compress), nustdout); /*was putchar*/
- if(ferror(nustdout)){ /* check it on entry */
- exit_stat = WRITEERR;
- return;
- }
- bytes_out = 3L; /* includes 3-byte header mojo */
- }
- else
- bytes_out = 0L; /* no 3-byte header mojo */
- in_count = 1L;
- offset = 0;
-
- if ((c = getc(nustdin)) == EOF) { /* NuLib: was getchar() */
- exit_stat = ferror(nustdin) ? READERR : OK;
- return;
- }
- prefxcode = (CODE)c;
-
- while ((c = getc(nustdin)) != EOF) { /* NuLib: was getchar() */
- in_count++;
-
-/* NuLib : May not be compressing entire file, so can't rely on EOF for end */
- if (in_count > thread_eof) break;
-
- hash = prefxcode ^ hashf[c];
- /* I need to check that my hash value is within range
- * because my 16-bit hash table is smaller than 64k.
- */
- if (hash >= hashsize)
- hash -= hashsize;
- if ((code = probe(hash)) != UNUSED) {
- if (suffix(code) != (char)c || prefix(code) != prefxcode) {
- /* hashdelta is subtracted from hash on each iteration of
- * the following hash table search loop. I compute it once
- * here to remove it from the loop.
- */
- HASH hashdelta = (0x120 - c) << (adjbits);
- do {
- /* rehash and keep looking */
- assert(code >= FIRSTFREE && code <= maxcode);
- if (hash >= hashdelta) hash -= hashdelta;
- else hash += (hashsize - hashdelta);
- assert(hash < hashsize);
- if ((code = probe(hash)) == UNUSED)
- goto newcode;
- } while (suffix(code) != (char)c || prefix(code) != prefxcode);
- }
- prefxcode = code;
- }
- else {
- newcode: {
- putcode(prefxcode, bits);
- code = nextfree;
- assert(hash < hashsize);
- assert(code >= FIRSTFREE);
- assert(code <= maxcode + 1);
- if (code <= maxcode) {
- probe(hash) = code;
- prefix(code) = prefxcode;
- suffix(code) = (char)c;
- if (code > highcode) {
- highcode += code;
- ++bits;
- }
- nextfree = code + 1;
- }
-#ifdef COMP40
- else if (in_count >= checkpoint && block_compress ) {
- if (cl_block()){
-#else
- else if (block_compress){
-#endif
- putcode((CODE)c, bits);
- putcode((CODE)CLEAR,bits);
- init_tables();
- if ((c = getc(nustdin)) == EOF) /* NuLib: was getchar*/
- break;
- in_count++;
-#ifdef COMP40
- }
-#endif
- }
- prefxcode = (CODE)c;
- }
- }
- }
- putcode(prefxcode, bits);
- putcode((CODE)CLEAR, 0);
- if (ferror(nustdout)){ /* check it on exit */
- exit_stat = WRITEERR;
- return;
- }
- /*
- * Print out stats on stderr
- */
- if(zcat_flg == 0 && !quiet) {
-#ifndef NDEBUG
- fprintf( stderr,
- "%ld chars in, (%ld bytes) out, compression factor: ",
- in_count, bytes_out );
- prratio( stderr, in_count, bytes_out );
- fprintf( stderr, "\n");
- fprintf( stderr, "\tCompression as in compact: " );
- prratio( stderr, in_count-bytes_out, in_count );
- fprintf( stderr, "\n");
- fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
- prefxcode - 1, bits );
-#else
- fprintf( stderr, "Compression: " );
- prratio( stderr, in_count-bytes_out, in_count );
-#endif /* NDEBUG */
- }
- if(bytes_out > in_count) /* if no savings */
- exit_stat = NOSAVING;
-
- packedSize = bytes_out; /* NuLib : return packed size in global */
-
- return ;
-}
-
-CONST UCHAR rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
-
-void putcode(code,bits)
-CODE code;
-register int bits;
-{
- static UCHAR outbuf[MAXBITS];
- register UCHAR *buf;
- register int shift;
- register int ok_to_write; /* NuLib (kludge... sorry) */
-
- ok_to_write = (exit_stat != NOSAVING);
-
- if (bits != oldbits) {
- if (bits == 0) {
- /* bits == 0 means EOF, write the rest of the buffer. */
- if (offset > 0) {
- int x = ((offset+7) >> 3); /* NuLib */
-
- if ((bytes_out + x) > max_bytes_out) { /* NuLib */
- /* compression failed. There's no clean way of bailing out
- /* (could use setjmp/longjmp, but that may not be supported
- /* on all systems), so just don't write anything.
- */
- exit_stat = NOSAVING;
- ok_to_write = FALSE;
- } else {
-/* fwrite(outbuf,1,(offset +7) >> 3, nustdout);*/
- fwrite(outbuf,1, x, nustdout);
- }
-/* bytes_out += ((offset +7) >> 3);*/
- bytes_out += x;
- }
- offset = 0;
- oldbits = 0;
- fflush(nustdout);
- return;
- }
- else {
- /* Change the code size. We must write the whole buffer,
- * because the expand side won't discover the size change
- * until after it has read a buffer full.
- */
- if (offset > 0) {
- if (ok_to_write) fwrite(outbuf, 1, oldbits, nustdout);
- bytes_out += oldbits;
- offset = 0;
- }
- oldbits = bits;
-#ifndef NDEBUG
- if ( debug )
- fprintf( stderr, "\nChange to %d bits\n", bits );
-#endif /* !NDEBUG */
- }
- }
- /* Get to the first byte. */
- buf = outbuf + ((shift = offset) >> 3);
- if ((shift &= 7) != 0) {
- *(buf) |= (*buf & rmask[shift]) | (UCHAR)(code << shift);
- *(++buf) = (UCHAR)(code >> (8 - shift));
- if (bits + shift > 16)
- *(++buf) = (UCHAR)(code >> (16 - shift));
- }
- else {
- /* Special case for fast execution */
- *(buf) = (UCHAR)code;
- *(++buf) = (UCHAR)(code >> 8);
- }
- if ((offset += bits) == (bits << 3)) {
- bytes_out += bits;
- if (ok_to_write) fwrite(outbuf,1,bits,nustdout);
- offset = 0;
- }
- return;
-}
-
-int nextcode(codeptr)
-CODE *codeptr;
-/* Get the next code from input and put it in *codeptr.
- * Return (TRUE) on success, or return (FALSE) on end-of-file.
- * Adapted from COMPRESS V4.0.
- */
-{
- register CODE code;
- static int size;
- static UCHAR inbuf[MAXBITS];
- register int shift;
- UCHAR *bp;
-
- /* If the next entry is a different bit-size than the preceeding one
- * then we must adjust the size and scrap the old buffer.
- */
- if (prevbits != bits) {
- prevbits = bits;
- size = 0;
- }
- /* If we can't read another code from the buffer, then refill it.
- */
- if (size - (shift = offset) < bits) {
- static int bytesize; /* NuLib: sigh */
- /* Read more input and convert size from # of bytes to # of bits */
-
- /* NuLib: stop after comp_thread_eof bytes */
- if (nubytes_read >= nucomp_thread_eof)
- return(NO);
-
- /* NuLib: replace old fread command with... */
- /*
- if ((size = fread(inbuf, 1, bits, nustdin) << 3) <= 0 || ferror(nustdin))
- return(NO);
- */
-
- bytesize = fread(inbuf, 1, bits, nustdin);
- if (nubytes_read + bits > nucomp_thread_eof) {
- bytesize = nucomp_thread_eof - nubytes_read;
- }
- size = bytesize << 3;
- if (size <= 0 || ferror(nustdin))
- return (NO);
-
- /* NuLib: increment nubytes_read */
- nubytes_read += (long) bytesize;
-
- offset = shift = 0;
- }
- /* Get to the first byte. */
- bp = inbuf + (shift >> 3);
- /* Get first part (low order bits) */
- code = (*bp++ >> (shift &= 7));
- /* high order bits. */
- code |= *bp++ << (shift = 8 - shift);
- if ((shift += 8) < bits) code |= *bp << shift;
- *codeptr = code & highcode;
- offset += bits;
- return (TRUE);
-}
-
-/*
- * NuLib: uncompress comp_thread_eof bytes from srcfd, writing to dstfd
- * Sets up a few things and then calls compress.
- */
-int u_decompress(srcfd, dstfd, comp_thread_eof)
-int srcfd, dstfd;
-long comp_thread_eof;
-{
- int src2, dst2;
- long srcposn, dstposn;
- static char *procName = "u_decompress";
-
- if ((srcposn = lseek(srcfd, 0L, S_REL)) < 0)
- Fatal("Bad posn lseek(1)", procName);
- if ((dstposn = lseek(dstfd, 0L, S_REL)) < 0)
- Fatal("Bad posn lseek(2)", procName);
-
- src2 = dup(srcfd);
- dst2 = dup(dstfd);
-
- /* NuLib: open new stdin/stdout, and seek */
- if ((nustdin = fdopen(src2, FREAD_STR)) == NULL)
- Fatal("can't fdopen() nustdin", procName);
- if ((nustdout = fdopen(dst2, FWRITE_STR)) == NULL)
- Fatal("can't fdopen() nustdout", procName);
- setvbuf(nustdin,zbuf,_IOFBF,ZBUFSIZE); /* make the buffers larger */
- setvbuf(nustdout,xbuf,_IOFBF,XBUFSIZE); /* (note order diff from comp) */
- if (fseek(nustdin, srcposn, S_ABS) < 0) /* seek may not be needed */
- Fatal("Bad stream posn lseek(1)", procName);
- if (fseek(nustdout, dstposn, S_ABS) < 0)
- Fatal("Bad stream posn lseek(2)", procName);
-
- /* Check the magic number */
- if (!nomagic) {
- if ((getc(nustdin)!=(magic_header[0] & 0xFF)) /* NuLib: was getchar*/
- || (getc(nustdin)!=(magic_header[1] & 0xFF))) {/* NuLib: was getchar*/
- fprintf(stderr, "decompress: not in compressed format\n");
- return(-1); /* NuLib: was exit(ERROR) */
- }
- maxbits = getc(nustdin); /* set -b from file (NuLib: was getchar) */
- block_compress = maxbits & BLOCK_MASK;
- maxbits &= BIT_MASK;
- if(maxbits > MAXBITS) {
- fprintf(stderr,
- "decompress: compressed with %d bits, can only handle %d bits\n",
- maxbits, MAXBITS);
- return(-1); /* NuLib: was exit(ERROR) */
- }
- nubytes_read = 3L;
- } else {
- nubytes_read = 0L;
- }
-
- nucomp_thread_eof = comp_thread_eof;
-/* printf("src file posn = %ld\n", ftell(nustdin));*/
- prevbits = 0; /* init for nextcode() */
- decompress();
- check_error();
-
- fclose(nustdin); /* note this closes the duped fd */
- fclose(nustdout);
- return (exit_stat);
-}
-
-void decompress()
-{
- register int i;
- register CODE code;
- char sufxchar;
- CODE savecode;
- FLAG fulltable, cleartable;
- static char token[MAXTOKLEN]; /* String buffer to build token */
-
- exit_stat = OK;
-
- if (alloc_tables(maxcode = ~(~(CODE)0 << maxbits),0)) /* exit_stat already set */
- return;
-
- /* if not zcat or filter (NuLib: never) */
- if(is_list && !zcat_flg) { /* Open output file */
- if (freopen(ofname, WRITE_FILE_TYPE, nustdout) == NULL) {
- exit_stat = NOTOPENED;
- return;
- }
- if (!quiet)
- fprintf(stderr, "%s: ",ifname);
- setvbuf(nustdout,xbuf,_IOFBF,XBUFSIZE);
- }
- cleartable = TRUE;
- savecode = CLEAR;
- offset = 0;
- do {
- if ((code = savecode) == CLEAR && cleartable) {
- highcode = ~(~(CODE)0 << (bits = INITBITS));
- fulltable = FALSE;
- nextfree = (cleartable = block_compress) == FALSE ? 256 : FIRSTFREE;
- if (!nextcode(&prefxcode))
- break;
- putc((sufxchar = (char)prefxcode), nustdout);
- continue;
- }
- i = 0;
- if (code >= nextfree && !fulltable) {
- if (code != nextfree){
- exit_stat = CODEBAD;
-/* fprintf(stderr, "Bad code; nubytes_read = %ld\n", nubytes_read); */
- /* CDEBUG */
- return ; /* Non-existant code */
- }
- /* Special case for sequence KwKwK (see text of article) */
- code = prefxcode;
- token[i++] = sufxchar;
- }
- /* Build the token string in reverse order by chasing down through
- * successive prefix tokens of the current token. Then output it.
- */
- while (code >= 256) {
-#ifndef NDEBUG
- /* These are checks to ease paranoia. Prefix codes must decrease
- * monotonically, otherwise we must have corrupt tables. We can
- * also check that we haven't overrun the token buffer.
- */
- if (code <= prefix(code)){
- exit_stat= TABLEBAD;
- return;
- }
- if (i >= MAXTOKLEN){
- exit_stat = TOKTOOBIG;
- return;
- }
-#endif
- token[i++] = suffix(code);
- code = prefix(code);
- }
- putc(sufxchar = (char)code, nustdout);
- while (--i >= 0)
- putc(token[i], nustdout);
- if (ferror(nustdout)) {
- exit_stat = WRITEERR;
- return;
- }
- /* If table isn't full, add new token code to the table with
- * codeprefix and codesuffix, and remember current code.
- */
- if (!fulltable) {
- code = nextfree;
- assert(256 <= code && code <= maxcode);
- prefix(code) = prefxcode;
- suffix(code) = sufxchar;
- prefxcode = savecode;
- if (code++ == highcode) {
- if (highcode >= maxcode) {
- fulltable = TRUE;
- --code;
- }
- else {
- ++bits;
- highcode += code; /* nextfree == highcode + 1 */
- }
- }
- nextfree = code;
- }
-
- } while (nextcode(&savecode));
- exit_stat = (ferror(nustdin))? READERR : OK;
-
- return ;
-}
-
-
-/*
- * These are routines pulled out of "compress.c" from compress v4.3.
- */
-void prratio(stream, num, den)
-FILE *stream;
-long int num, den;
-{
- register int q; /* Doesn't need to be long */
-
- if(num > 214748L) { /* 2147483647/10000 */
- q = (int) (num / (den / 10000L));
- }
- else {
- q = (int) (10000L * num / den); /* Long calculations, though */
- }
- if (q < 0) {
- putc('-', stream);
- q = -q;
- }
- fprintf(stream, "%d.%02d%%", q / 100, q % 100);
-}
-
-/*
- * Check exit status from compress() and decompress()
- *
- * exit_stat is a global var. Either returns something interesting or
- * bails out completely.
- */
-int check_error() /* returning OK continues with processing next file */
-{
- prog_name = prgName; /* NuLib: set prog_name to "nulib" */
-
- switch(exit_stat) {
- case OK:
- return (OK);
- case NOMEM:
- if (do_decomp)
- fprintf(stderr,"%s: not enough memory to decompress '%s'.\n", prog_name, ifname);
- else
- fprintf(stderr,"%s: not enough memory to compress '%s'.\n", prog_name, ifname);
- return(OK);
- case SIGNAL_ERROR:
- fprintf(stderr,"%s: error setting signal interupt.\n",prog_name);
- exit(ERROR);
- break;
- case READERR:
- fprintf(stderr,"%s: read error on input '%s'.\n", prog_name, ifname);
- break;
- case WRITEERR:
- fprintf(stderr,"%s: write error on output '%s'.\n", prog_name, ofname);
- break;
- case TOKTOOBIG:
- fprintf(stderr,"%s: token too long in '%s'.\n", prog_name, ifname);
- break;
- case INFILEBAD:
- fprintf(stderr, "%s: '%s' in unknown compressed format.\n", prog_name, ifname);
- break;
- case CODEBAD:
- fprintf(stderr,"%s: file token bad in '%s'.\n", prog_name,ifname);
- break;
- case TABLEBAD:
- fprintf(stderr,"%s: internal error -- tables corrupted.\n", prog_name);
- break;
- case NOTOPENED:
- fprintf(stderr,"%s: could not open output file %s\n",prog_name,ofname);
- exit(ERROR);
- break;
- case NOSAVING:
- if (force)
- exit_stat = OK;
- return (OK);
- default:
- fprintf(stderr,"%s: internal error -- illegal return value = %d.\n", prog_name,exit_stat);
- }
- if (!zcat_flg && !keep_error){
- fclose(nustdout); /* won't get here without an error */
- unlink ( ofname );
- }
- exit(exit_stat);
- return(ERROR);
-}
-
-/*
- * These are routines from "compusi.c"
- */
-void version()
-{
-#ifdef XENIX
-#ifndef NDEBUG
- fprintf(stderr, "%s\nOptions: Xenix %s MAXBITS = %d\n", rcs_ident,
- "DEBUG",MAXBITS);
-#else
- fprintf(stderr, "%s\nOptions: Xenix MAXBITS = %d\n", rcs_ident,MAXBITS);
-#endif
-#else
-#ifndef NDEBUG
- fprintf(stderr, "%s\nOptions: Unix %s MAXBITS = %d\n", rcs_ident,
- "DEBUG",MAXBITS);
-#else
- fprintf(stderr, "%s\nOptions: Unix MAXBITS = %d\n", rcs_ident,MAXBITS);
-#endif
-#endif
-}
-
-ALLOCTYPE FAR *emalloc(x,y)
-unsigned int x;
-int y;
-{
- ALLOCTYPE FAR *p;
- p = (ALLOCTYPE FAR *)ALLOCATE(x,y);
- return(p);
-}
-
-void efree(ptr)
-ALLOCTYPE FAR *ptr;
-{
- FREEIT(ptr);
-}
-
+ END OF ARCHIVE
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads