Arc v5.21 (5 of 6)

egray at fthood.UUCP egray at fthood.UUCP
Tue Jan 3 09:54:00 AEST 1989


This is part 5 (of 6) to the Arc v5.21 distribution package.

Emmet P. Gray				US Army, HQ III Corps & Fort Hood
...!uunet!uiucuxc!fthood!egray		Attn: AFZF-DE-ENV
					Directorate of Engineering & Housing
					Environmental Management Office
					Fort Hood, TX 76544-5057

------------------------------------------------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	arcsq.c
#	arcsqs.c
#	arcsvc.c
#	arctst.c
#	arcunp.c
#	arcusq.c
#	getwd.c
# This archive created: Sun Jan  1 12:48:31 1989
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'arcsq.c'" '(14548 characters)'
if test -f 'arcsq.c'
then
	echo shar: "will not over-write existing file 'arcsq.c'"
else
sed 's/^X//' << \SHAR_EOF > 'arcsq.c'
X/*
X * $Header: arcsq.c,v 1.3 88/07/31 18:53:32 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCSQ 
X *
X * Version 3.10, created on 01/30/86 at 20:10:46
X *
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED 
X *
X * By:  Thom Henderson 
X *
X * Description: This file contains the routines used to squeeze a file when
X * placing it in an archive. 
X *
X * Language: Computer Innovations Optimizing C86 
X *
X * Programming notes: Most of the routines used for the Huffman squeezing
X * algorithm were lifted from the SQ program by Dick Greenlaw, as adapted to
X * CI-C86 by Robert J. Beilstein. 
X */
X#include <stdio.h>
X#include "arc.h"
X
X/* stuff for Huffman squeezing */
X
X#define TRUE 1
X#define FALSE 0
X#define ERROR (-1)
X#define SPEOF 256		/* special endfile token */
X#define NOCHILD (-1)		/* marks end of path through tree */
X#define NUMVALS 257		/* 256 data values plus SPEOF */
X#define NUMNODES (NUMVALS+NUMVALS-1)	/* number of nodes */
X#define MAXCOUNT (unsigned short) 65535	/* biggest unsigned integer */
X
X/*
X * The following array of structures are the nodes of the binary trees. The
X * first NUMVALS nodes become the leaves of the final tree and represent the
X * values of the data bytes being encoded and the special endfile, SPEOF. The
X * remaining nodes become the internal nodes of the final tree. 
X */
X
Xstruct nd {			/* shared by unsqueezer */
X	unsigned short	weight;	/* number of appearances */
X	short		tdepth;	/* length on longest path in tree */
X	short		lchild, rchild;	/* indices to next level */
X}               node[NUMNODES];	/* use large buffer */
X
Xstatic int      dctreehd;	/* index to head of final tree */
X
X/*
X * This is the encoding table: The bit strings have first bit in low bit.
X * Note that counts were scaled so code fits unsigned integer. 
X */
X
Xstatic int      codelen[NUMVALS];	/* number of bits in code */
Xstatic unsigned short code[NUMVALS];	/* code itself, right adjusted */
Xstatic unsigned short tcode;	/* temporary code value */
Xstatic long     valcount[NUMVALS];	/* actual count of times seen */
X
X/* Variables used by encoding process */
X
Xstatic int      curin;		/* value currently being encoded */
Xstatic int      cbitsrem;	/* # of code string bits left */
Xstatic unsigned short ccode;	/* current code right justified */
X
Xstatic	void	scale(), heap(), adjust(), bld_tree(), init_enc(), put_int();
Xstatic	int	cmptrees(), buildenc(), maxchar();
Xvoid 
Xinit_sq()
X{				/* prepare for scanning pass */
X	int             i;	/* node index */
X
X	/*
X	 * Initialize all nodes to single element binary trees with zero
X	 * weight and depth. 
X	 */
X
X	for (i = 0; i < NUMNODES; ++i) {
X		node[i].weight = 0;
X		node[i].tdepth = 0;
X		node[i].lchild = NOCHILD;
X		node[i].rchild = NOCHILD;
X	}
X
X	for (i = 0; i < NUMVALS; i++)
X		valcount[i] = 0;
X}
X
Xvoid 
Xscan_sq(c)			/* add a byte to the tables */
X	int             c;	/* byte to add */
X{
X	unsigned short *wp;	/* speeds up weight counting */
X
X	/* Build frequency info in tree */
X
X	if (c == EOF)		/* it's traditional */
X		c = SPEOF;	/* dumb, but traditional */
X
X	if (*(wp = &node[c].weight) != MAXCOUNT)
X		++(*wp);	/* bump weight counter */
X
X	valcount[c]++;		/* bump byte counter */
X}
X
Xlong 
Xpred_sq()
X{				/* predict size of squeezed file */
X	int             i;
X	int             btlist[NUMVALS];	/* list of intermediate
X						 * b-trees */
X	int             listlen;/* length of btlist */
X	unsigned short	ceiling;/* limit for scaling */
X	long            size = 0;	/* predicted size */
X	int             numnodes;	/* # of nodes in simplified tree */
X
X	scan_sq(EOF);		/* signal end of input */
X
X	ceiling = MAXCOUNT;
X
X	/* Keep trying to scale and encode */
X
X	do {
X		scale(ceiling);
X		ceiling /= 2;	/* in case we rescale */
X
X		/*
X		 * Build list of single node binary trees having leaves for
X		 * the input values with non-zero counts 
X		 */
X
X		for (i = listlen = 0; i < NUMVALS; ++i) {
X			if (node[i].weight != 0) {
X				node[i].tdepth = 0;
X				btlist[listlen++] = i;
X			}
X		}
X
X		/*
X		 * Arrange list of trees into a heap with the entry indexing
X		 * the node with the least weight at the top. 
X		 */
X
X		heap(btlist, listlen);
X
X		/* Convert the list of trees to a single decoding tree */
X
X		bld_tree(btlist, listlen);
X
X		/* Initialize the encoding table */
X
X		init_enc();
X
X		/*
X		 * Try to build encoding table. Fail if any code is > 16 bits
X		 * long. 
X		 */
X	} while (buildenc(0, dctreehd) == ERROR);
X
X	/* Initialize encoding variables */
X
X	cbitsrem = 0;		/* force initial read */
X	curin = 0;		/* anything but endfile */
X
X	for (i = 0; i < NUMVALS; i++)	/* add bits for each code */
X		size += valcount[i] * codelen[i];
X
X	size = (size + 7) / 8;	/* reduce to number of bytes */
X
X	numnodes = dctreehd < NUMVALS ? 0 : dctreehd - (NUMVALS - 1);
X
X	size += sizeof(short) + 2 * numnodes * sizeof(short);
X
X	return size;
X}
X
X/*
X * The count of number of occurrances of each input value have already been
X * prevented from exceeding MAXCOUNT. Now we must scale them so that their
X * sum doesn't exceed ceiling and yet no non-zero count can become zero. This
X * scaling prevents errors in the weights of the interior nodes of the
X * Huffman tree and also ensures that the codes will fit in an unsigned
X * integer. Rescaling is used if necessary to limit the code length. 
X */
X
Xstatic	void
Xscale(ceil)
X	unsigned short	ceil;	/* upper limit on total weight */
X{
X	register int    i;
X	int             ovflw, divisor;
X	unsigned short	w, sum;
X	unsigned char   increased;	/* flag */
X
X	do {
X		for (i = sum = ovflw = 0; i < NUMVALS; ++i) {
X			if (node[i].weight > (ceil - sum))
X				++ovflw;
X			sum += node[i].weight;
X		}
X
X		divisor = ovflw + 1;
X
X		/* Ensure no non-zero values are lost */
X
X		increased = FALSE;
X		for (i = 0; i < NUMVALS; ++i) {
X			w = node[i].weight;
X			if (w < divisor && w != 0) {	/* Don't fail to provide
X							 * a code if it's used
X							 * at all */
X
X				node[i].weight = divisor;
X				increased = TRUE;
X			}
X		}
X	} while (increased);
X
X	/* Scaling factor chosen, now scale */
X
X	if (divisor > 1)
X		for (i = 0; i < NUMVALS; ++i)
X			node[i].weight /= divisor;
X}
X
X/*
X * heap() and adjust() maintain a list of binary trees as a heap with the top
X * indexing the binary tree on the list which has the least weight or, in
X * case of equal weights, least depth in its longest path. The depth part is
X * not strictly necessary, but tends to avoid long codes which might provoke
X * rescaling. 
X */
X
Xstatic	void
Xheap(list, length)
X	int             list[], length;
X{
X	register int    i;
X
X	for (i = (length - 2) / 2; i >= 0; --i)
X		adjust(list, i, length - 1);
X}
X
X/* Make a heap from a heap with a new top */
X
Xstatic	void
Xadjust(list, top, bottom)
X	int             list[], top, bottom;
X{
X	register int    k, temp;
X
X	k = 2 * top + 1;	/* left child of top */
X	temp = list[top];	/* remember root node of top tree */
X
X	if (k <= bottom) {
X		if (k < bottom && cmptrees(list[k], list[k + 1]))
X			++k;
X
X		/* k indexes "smaller" child (in heap of trees) of top */
X		/* now make top index "smaller" of old top and smallest child */
X
X		if (cmptrees(temp, list[k])) {
X			list[top] = list[k];
X			list[k] = temp;
X
X			/* Make the changed list a heap */
X
X			adjust(list, k, bottom);	/* recursive */
X		}
X	}
X}
X
X/*
X * Compare two trees, if a > b return true, else return false. Note
X * comparison rules in previous comments. 
X */
X
Xstatic	int 
Xcmptrees(a, b)
X	int             a, b;	/* root nodes of trees */
X{
X	if (node[a].weight > node[b].weight)
X		return TRUE;
X	if (node[a].weight == node[b].weight)
X		if (node[a].tdepth > node[b].tdepth)
X			return TRUE;
X	return FALSE;
X}
X
X/*
X * HUFFMAN ALGORITHM: develops the single element trees into a single binary
X * tree by forming subtrees rooted in interior nodes having weights equal to
X * the sum of weights of all their descendents and having depth counts
X * indicating the depth of their longest paths. 
X *
X * When all trees have been formed into a single tree satisfying the heap
X * property (on weight, with depth as a tie breaker) then the binary code
X * assigned to a leaf (value to be encoded) is then the series of left (0)
X * and right (1) paths leading from the root to the leaf. Note that trees are
X * removed from the heaped list by moving the last element over the top
X * element and reheaping the shorter list. 
X */
X
Xstatic	void
Xbld_tree(list, len)
X	int             list[];
Xint             len;
X{
X	register int    freenode;	/* next free node in tree */
X	register struct nd *frnp;	/* free node pointer */
X	int             lch, rch;	/* temps for left, right children */
X
X	/*
X	 * Initialize index to next available (non-leaf) node. Lower numbered
X	 * nodes correspond to leaves (data values). 
X	 */
X
X	freenode = NUMVALS;
X
X	while (len > 1) {	/* Take from list two btrees with least
X				 * weight and build an interior node pointing
X				 * to them. This forms a new tree. */
X
X		lch = list[0];	/* This one will be left child */
X
X		/* delete top (least) tree from the list of trees */
X
X		list[0] = list[--len];
X		adjust(list, 0, len - 1);
X
X		/* Take new top (least) tree. Reuse list slot later */
X
X		rch = list[0];	/* This one will be right child */
X
X		/*
X		 * Form new tree from the two least trees using a free node
X		 * as root. Put the new tree in the list. 
X		 */
X
X		frnp = &node[freenode];	/* address of next free node */
X		list[0] = freenode++;	/* put at top for now */
X		frnp->lchild = lch;
X		frnp->rchild = rch;
X		frnp->weight = node[lch].weight + node[rch].weight;
X		frnp->tdepth = 1 + maxchar(node[lch].tdepth, node[rch].tdepth);
X
X		/* reheap list  to get least tree at top */
X
X		adjust(list, 0, len - 1);
X	}
X	dctreehd = list[0];	/* head of final tree */
X}
X
Xstatic int 
Xmaxchar(a, b)
X{
X	return a > b ? a : b;
X}
X
Xstatic	void
Xinit_enc()
X{
X	register int    i;
X
X	/* Initialize encoding table */
X
X	for (i = 0; i < NUMVALS; ++i)
X		codelen[i] = 0;
X}
X
X/*
X * Recursive routine to walk the indicated subtree and level and maintain the
X * current path code in bstree. When a leaf is found the entire code string
X * and length are put into the encoding table entry for the leaf's data value
X * . 
X *
X * Returns ERROR if codes are too long. 
X */
X
Xstatic int 
Xbuildenc(level, root)
X	int             level;	/* level of tree being examined, from zero */
X	int             root;	/* root of subtree is also data value if leaf */
X{
X	register int    l, r;
X
X	l = node[root].lchild;
X	r = node[root].rchild;
X
X	if (l == NOCHILD && r == NOCHILD) {	/* Leaf. Previous path
X						 * determines bit string code
X						 * of length level (bits 0 to
X						 * level - 1). Ensures unused
X						 * code bits are zero. */
X
X		codelen[root] = level;
X		code[root] = tcode & (((unsigned short	) ~0) >> (16 - level));
X		return (level > 16) ? ERROR : 0;
X	} else {
X		if (l != NOCHILD) {	/* Clear path bit and continue deeper */
X
X			tcode &= ~(1 << level);
X			if (buildenc(level + 1, l) == ERROR)
X				return ERROR;	/* pass back bad statuses */
X		}
X		if (r != NOCHILD) {	/* Set path bit and continue deeper */
X
X			tcode |= 1 << level;
X			if (buildenc(level + 1, r) == ERROR)
X				return ERROR;	/* pass back bad statuses */
X		}
X	}
X	return NULL;		/* it worked if we reach here */
X}
X
Xstatic	void
Xput_int(n, f)			/* output an integer */
X	short		n;	/* integer to output */
X	FILE           *f;	/* file to put it to */
X{
X	void		putc_pak();
X
X	putc_pak(n & 0xff, f);	/* first the low byte */
X	putc_pak(n >> 8, f);	/* then the high byte */
X}
X
X/* Write out the header of the compressed file */
X
Xstatic long 
Xwrt_head(ob)
X	FILE           *ob;
X{
X	register int    l, r;
X	int             i, k;
X	int             numnodes;	/* # of nodes in simplified tree */
X
X	/*
X	 * Write out a simplified decoding tree. Only the interior nodes are
X	 * written. When a child is a leaf index (representing a data value)
X	 * it is recoded as -(index + 1) to distinguish it from interior
X	 * indexes which are recoded as positive indexes in the new tree. 
X	 *
X	 * Note that this tree will be empty for an empty file. 
X	 */
X
X	numnodes = dctreehd < NUMVALS ? 0 : dctreehd - (NUMVALS - 1);
X	put_int(numnodes, ob);
X
X	for (k = 0, i = dctreehd; k < numnodes; ++k, --i) {
X		l = node[i].lchild;
X		r = node[i].rchild;
X		l = l < NUMVALS ? -(l + 1) : dctreehd - l;
X		r = r < NUMVALS ? -(r + 1) : dctreehd - r;
X		put_int(l, ob);
X		put_int(r, ob);
X	}
X
X	return sizeof(short) + numnodes * 2 * sizeof(short);
X}
X
X/*
X * Get an encoded byte or EOF. Reads from specified stream AS NEEDED. 
X *
X * There are two unsynchronized bit-byte relationships here. The input stream
X * bytes are converted to bit strings of various lengths via the static
X * variables named c... These bit strings are concatenated without padding to
X * become the stream of encoded result bytes, which this function returns one
X * at a time. The EOF (end of file) is converted to SPEOF for convenience and
X * encoded like any other input value. True EOF is returned after that. 
X */
X
Xstatic int 
Xgethuff(ib)			/* Returns bytes except for EOF */
X	FILE           *ib;
X{
X	int             rbyte;	/* Result byte value */
X	int             need;	/* number of bits */
X	int		getc_ncr();
X
X	rbyte = 0;
X	need = 8;		/* build one byte per call */
X
X	/*
X	 * Loop to build a byte of encoded data. Initialization forces read
X	 * the first time. 
X	 */
X
Xloop:
X	if (cbitsrem >= need) {	/* if current code is big enough */
X		if (need == 0)
X			return rbyte;
X
X		rbyte |= ccode << (8 - need);	/* take what we need */
X		ccode >>= need;	/* and leave the rest */
X		cbitsrem -= need;
X		return rbyte & 0xff;
X	}
X	/* We need more than current code */
X
X	if (cbitsrem > 0) {
X		rbyte |= ccode << (8 - need);	/* take what there is */
X		need -= cbitsrem;
X	}
X	/* No more bits in current code string */
X
X	if (curin == SPEOF) {	/* The end of file token has been encoded. If
X				 * result byte has data return it and do EOF
X				 * next time. */
X
X		cbitsrem = 0;
X		return (need == 8) ? EOF : rbyte + 0;
X	}
X	/* Get an input byte */
X
X	if ((curin = getc_ncr(ib)) == EOF)
X		curin = SPEOF;	/* convenient for encoding */
X
X	ccode = code[curin];	/* get the new byte's code */
X	cbitsrem = codelen[curin];
X
X	goto loop;
X}
X
X/*
X * This routine is used to perform the actual squeeze operation.  It can only
X * be called after the file has been scanned.  It returns the true length of
X * the squeezed entry. 
X */
X
Xlong 
Xfile_sq(f, t)			/* squeeze a file into an archive */
X	FILE           *f;	/* file to squeeze */
X	FILE           *t;	/* archive to receive file */
X{
X	int             c;	/* one byte of squeezed data */
X	long            size;	/* size after squeezing */
X
X	size = wrt_head(t);	/* write out the decode tree */
X
X	while ((c = gethuff(f)) != EOF) {
X		putc_pak(c, t);
X		size++;
X	}
X
X	return size;		/* report true size */
X}
SHAR_EOF
if test 14548 -ne "`wc -c < 'arcsq.c'`"
then
	echo shar: "error transmitting 'arcsq.c'" '(should have been 14548 characters)'
fi
fi
echo shar: "extracting 'arcsqs.c'" '(11513 characters)'
if test -f 'arcsqs.c'
then
	echo shar: "will not over-write existing file 'arcsqs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'arcsqs.c'
X/*
X * $Header: arcsqs.c,v 1.3 88/07/31 18:54:14 hyc Exp $
X */
X
X/*  ARC - Archive utility - SQUASH
X 
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X 
X This is a quick hack to ARCLZW to make it handle squashed archives.
X Dan Lanciani (ddl at harvard.*) July 87
X 
X*/
X
X/*
X * $Header: arcsqs.c,v 1.3 88/07/31 18:54:14 hyc Exp $
X */
X
X#include <stdio.h>
X#include "arc.h"
X
X#if	MSDOS
Xchar	*setmem();
X#else
Xchar	*memset();
X#endif
Xint	getc_unp();
Xvoid	putc_pak(), putc_unp();
Xstatic void	putcode();
X
X/* definitions for the new dynamic Lempel-Zev crunching */
X
X#define BITS   13		/* maximum bits per code */
X#define HSIZE  10007		/* 80% occupancy */
X#define INIT_BITS 9		/* initial number of bits/code */
Xstatic int      n_bits;		/* number of bits/code */
Xstatic int      maxcode;	/* maximum code, given n_bits */
X#define MAXCODE(n)      ((1<<(n)) - 1)	/* maximum code calculation */
Xstatic int      maxcodemax = 1 << BITS;	/* largest possible code (+1) */
X
Xstatic unsigned char buf[BITS];	/* input/output buffer */
X
Xstatic unsigned char lmask[9] =	/* left side masks */
X{0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
Xstatic unsigned char rmask[9] =	/* right side masks */
X{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
X
Xstatic int      offset;		/* byte offset for code output */
Xstatic long     in_count;	/* length of input */
Xstatic long     bytes_out;	/* length of compressed output */
Xstatic unsigned short ent;
X
Xlong     htab[HSIZE];	/* hash code table   (crunch) */
Xunsigned short codetab[HSIZE];	/* string code table (crunch) */
X
Xstatic unsigned short *prefix = codetab;  /* prefix code table (uncrunch) */
Xstatic unsigned char *suffix=(unsigned char *)htab;  /* suffix table (uncrunch) */
Xstatic int      free_ent;	/* first unused entry */
Xstatic int      firstcmp;	/* true at start of compression */
Xunsigned char stack[HSIZE];	/* local push/pop stack */
X
X/*
X * block compression parameters -- after all codes are used up,
X * and compression rate changes, start over.
X */
X
Xstatic int      clear_flg;
Xstatic long     ratio;
X#define CHECK_GAP 10000		/* ratio check interval */
Xstatic long     checkpoint;
X
X/*
X * the next two codes should not be changed lightly, as they must not
X * lie within the contiguous general code space.
X */
X#define FIRST   257		/* first free entry */
X#define CLEAR   256		/* table clear output code */
X
Xstatic void
Xcl_block(t)			/* table clear for block compress */
X	FILE           *t;	/* our output file */
X{
X	long            rat;
X
X	checkpoint = in_count + CHECK_GAP;
X
X	if (in_count > 0x007fffffL) {	/* shift will overflow */
X		rat = bytes_out >> 8;
X		if (rat == 0)	/* Don't divide by zero */
X			rat = 0x7fffffffL;
X		else
X			rat = in_count / rat;
X	} else
X		rat = (in_count << 8) / bytes_out;	/* 8 fractional bits */
X
X	if (rat > ratio)
X		ratio = rat;
X	else {
X		ratio = 0;
X		setmem(htab, HSIZE * sizeof(long), 0xff);
X		free_ent = FIRST;
X		clear_flg = 1;
X		putcode(CLEAR, t);
X	}
X}
X
X/*****************************************************************
X *
X * Output a given code.
X * Inputs:
X *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
X *              that n_bits =< (long)wordsize - 1.
X * Outputs:
X *      Outputs code to the file.
X * Assumptions:
X *      Chars are 8 bits long.
X * Algorithm:
X *      Maintain a BITS character long buffer (so that 8 codes will
X * fit in it exactly).  When the buffer fills up empty it and start over.
X */
X
Xstatic void
Xputcode(code, t)		/* output a code */
X	int             code;	/* code to output */
X	FILE           *t;	/* where to put it */
X{
X	int             r_off = offset;	/* right offset */
X	int             bits = n_bits;	/* bits to go */
X	unsigned char  *bp = buf;	/* buffer pointer */
X	int             n;	/* index */
X	register int	ztmp;
X
X	if (code >= 0) {	/* if a real code *//* Get to the first byte. */
X		bp += (r_off >> 3);
X		r_off &= 7;
X
X		/*
X		 * Since code is always >= 8 bits, only need to mask the
X		 * first hunk on the left. 
X		 */
X		ztmp = (code << r_off) & lmask[r_off];
X		*bp = (*bp & rmask[r_off]) | ztmp;
X		bp++;
X		bits -= (8 - r_off);
X		code >>= (8 - r_off);
X
X		/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
X		if (bits >= 8) {
X			*bp++ = code;
X			code >>= 8;
X			bits -= 8;
X		}
X		/* Last bits. */
X		if (bits)
X			*bp = code;
X
X		offset += n_bits;
X
X		if (offset == (n_bits << 3)) {
X			bp = buf;
X			bits = n_bits;
X			bytes_out += bits;
X			do
X				putc_pak(*bp++, t);
X			while (--bits);
X			offset = 0;
X		}
X		/*
X		 * If the next entry is going to be too big for the code
X		 * size, then increase it, if possible. 
X		 */
X		if (free_ent > maxcode || clear_flg > 0) {	/* Write the whole
X								 * buffer, because the
X								 * input side won't
X								 * discover the size
X								 * increase until after
X								 * it has read it. */
X			if (offset > 0) {
X				bp = buf;	/* reset pointer for writing */
X				bytes_out += n = n_bits;
X				while (n--)
X					putc_pak(*bp++, t);
X			}
X			offset = 0;
X
X			if (clear_flg) {	/* reset if clearing */
X				maxcode = MAXCODE(n_bits = INIT_BITS);
X				clear_flg = 0;
X			} else {/* else use more bits */
X				n_bits++;
X				if (n_bits == BITS)
X					maxcode = maxcodemax;
X				else
X					maxcode = MAXCODE(n_bits);
X			}
X		}
X	} else {		/* dump the buffer on EOF */
X		bytes_out += n = (offset + 7) / 8;
X
X		if (offset > 0)
X			while (n--)
X				putc_pak(*bp++, t);
X		offset = 0;
X	}
X}
X
X/*****************************************************************
X *
X * Read one code from the standard input.  If EOF, return -1.
X * Inputs:
X *      cmpin
X * Outputs:
X *      code or -1 is returned.
X */
X
Xstatic int
Xgetcode(f)			/* get a code */
X	FILE           *f;	/* file to get from */
X{
X	int             code;
X	static int      loffset = 0, size = 0;
X	int             r_off, bits;
X	unsigned char  *bp = buf;
X
X	if (clear_flg > 0 || loffset >= size || free_ent > maxcode) {
X		/* If the next entry will be too big for the current code
X		 * size, then we must increase the size. This implies reading
X		 * a new buffer full, too. */
X		if (free_ent > maxcode) {
X			n_bits++;
X			if (n_bits == BITS)
X				maxcode = maxcodemax;	/* won't get any bigger
X							 * now */
X			else
X				maxcode = MAXCODE(n_bits);
X		}
X		if (clear_flg > 0) {
X			maxcode = MAXCODE(n_bits = INIT_BITS);
X			clear_flg = 0;
X		}
X		for (size = 0; size < n_bits; size++) {
X			if ((code = getc_unp(f)) == EOF)
X				break;
X			else
X				buf[size] = code;
X		}
X		if (size <= 0)
X			return -1;	/* end of file */
X
X		loffset = 0;
X		/* Round size down to integral number of codes */
X		size = (size << 3) - (n_bits - 1);
X	}
X	r_off = loffset;
X	bits = n_bits;
X
X	/*
X	 * Get to the first byte. 
X	 */
X	bp += (r_off >> 3);
X	r_off &= 7;
X
X	/* Get first part (low order bits) */
X	code = (*bp++ >> r_off);
X	bits -= 8 - r_off;
X	r_off = 8 - r_off;	/* now, offset into code word */
X
X	/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
X	if (bits >= 8) {
X		code |= *bp++ << r_off;
X		r_off += 8;
X		bits -= 8;
X	}
X	/* high order bits. */
X	code |= (*bp & rmask[bits]) << r_off;
X	loffset += n_bits;
X
X	return code;
X}
X
X/*
X * compress a file
X *
X * Algorithm:  use open addressing double hashing (no chaining) on the
X * prefix code / next character combination.  We do a variant of Knuth's
X * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
X * secondary probe.  Here, the modular division first probe is gives way
X * to a faster exclusive-or manipulation.  Also do block compression with
X * an adaptive reset, where the code table is cleared when the compression
X * ratio decreases, but after the table fills.  The variable-length output
X * codes are re-sized at this point, and a special CLEAR code is generated
X * for the decompressor.
X */
X
Xvoid
Xsqinit_cm()			/* initialize for compression */
X{
X	offset = 0;
X	bytes_out = 0;
X	clear_flg = 0;
X	ratio = 0;
X	in_count = 1;
X	checkpoint = CHECK_GAP;
X	maxcode = MAXCODE(n_bits = INIT_BITS);
X	free_ent = FIRST;
X	setmem(htab, HSIZE * sizeof(long), 0xff);
X	n_bits = INIT_BITS;	/* set starting code size */
X
X	firstcmp = 1;		/* next byte will be first */
X}
X
Xvoid
Xsqputc_cm(c, t)			/* compress a character */
X	unsigned char   c;	/* character to compress */
X	FILE           *t;	/* where to put it */
X{
X	static long     fcode;
X	static int      hshift;
X	int             i;
X	int             disp;
X
X	if (firstcmp) {		/* special case for first byte */
X		ent = c;	/* remember first byte */
X
X		hshift = 0;
X		for (fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L)
X			hshift++;
X		hshift = 8 - hshift;	/* set hash code range bund */
X
X		firstcmp = 0;	/* no longer first */
X		return;
X	}
X	in_count++;
X	fcode = (long) (((long) c << BITS) + ent);
X	i = (c << hshift) ^ ent;/* xor hashing */
X
X	if (htab[i] == fcode) {
X		ent = codetab[i];
X		return;
X	} else if (htab[i] < 0)	/* empty slot */
X		goto nomatch;
X	disp = HSIZE - i;	/* secondary hash (after G.Knott) */
X	if (i == 0)
X		disp = 1;
X
Xprobe:
X	if ((i -= disp) < 0)
X		i += HSIZE;
X
X	if (htab[i] == fcode) {
X		ent = codetab[i];
X		return;
X	}
X	if (htab[i] > 0)
X		goto probe;
X
Xnomatch:
X	putcode(ent, t);
X	ent = c;
X	if (free_ent < maxcodemax) {
X		codetab[i] = free_ent++;	/* code -> hashtable */
X		htab[i] = fcode;
X	} else if ((long) in_count >= checkpoint)
X		cl_block(t);
X}
X
Xlong 
Xsqpred_cm(t)			/* finish compressing a file */
X	FILE           *t;	/* where to put it */
X{
X	putcode(ent, t);	/* put out the final code */
X	putcode(-1, t);		/* tell output we are done */
X
X	return bytes_out;	/* say how big it got */
X}
X
X/*
X * Decompress a file.  This routine adapts to the codes in the file
X * building the string table on-the-fly; requiring no table to be stored
X * in the compressed file.  The tables used herein are shared with those of
X * the compress() routine.  See the definitions above.
X */
X
Xvoid
Xsqdecomp(f, t)			/* decompress a file */
X	FILE           *f;	/* file to read codes from */
X	FILE           *t;	/* file to write text to */
X{
X	unsigned char  *stackp;
X	int             finchar;
X	int             code, oldcode, incode;
X
X	n_bits = INIT_BITS;	/* set starting code size */
X	clear_flg = 0;
X
X	/*
X	 * As above, initialize the first 256 entries in the table. 
X	 */
X	maxcode = MAXCODE(n_bits = INIT_BITS);
X	for (code = 255; code >= 0; code--) {
X		prefix[code] = 0;
X		suffix[code] = (unsigned char) code;
X	}
X	free_ent = FIRST;
X
X	finchar = oldcode = getcode(f);
X	if (oldcode == -1)	/* EOF already? */
X		return;		/* Get out of here */
X	putc_unp((char) finchar, t);	/* first code must be 8 bits=char */
X	stackp = stack;
X
X	while ((code = getcode(f)) > -1) {
X		if (code == CLEAR) {
X			for (code = 255; code >= 0; code--)
X				prefix[code] = 0;
X			clear_flg = 1;
X			free_ent = FIRST - 1;
X			if ((code = getcode(f)) == -1)	/* O, untimely death! */
X				break;
X		}
X		incode = code;
X		/*
X		 * Special case for KwKwK string. 
X		 */
X		if (code >= free_ent) {
X			if (code > free_ent) {
X				if (warn) {
X					printf("Corrupted compressed file.\n");
X					printf("Invalid code %d when max is %d.\n",
X						code, free_ent);
X				}
X				nerrs++;
X				return;
X			}
X			*stackp++ = finchar;
X			code = oldcode;
X		}
X		/*
X		 * Generate output characters in reverse order 
X		 */
X		while (code >= 256) {
X			*stackp++ = suffix[code];
X			code = prefix[code];
X		}
X		*stackp++ = finchar = suffix[code];
X
X		/*
X		 * And put them out in forward order 
X		 */
X		do
X			putc_unp(*--stackp, t);
X		while (stackp > stack);
X
X		/*
X		 * Generate the new entry. 
X		 */
X		if ((code = free_ent) < maxcodemax) {
X			prefix[code] = (unsigned short) oldcode;
X			suffix[code] = finchar;
X			free_ent = code + 1;
X		}
X		/*
X		 * Remember previous code. 
X		 */
X		oldcode = incode;
X	}
X}
SHAR_EOF
if test 11513 -ne "`wc -c < 'arcsqs.c'`"
then
	echo shar: "error transmitting 'arcsqs.c'" '(should have been 11513 characters)'
fi
fi
echo shar: "extracting 'arcsvc.c'" '(4689 characters)'
if test -f 'arcsvc.c'
then
	echo shar: "will not over-write existing file 'arcsvc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'arcsvc.c'
X/*
X * $Header: arcsvc.c,v 1.9 88/07/31 18:54:55 hyc Exp $
X */
X
X/*  ARC - Archive utility - ARCSVC
X
X    Version 2.23, created on 04/22/87 at 13:10:10
X
X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:	 Thom Henderson
X
X    Description:
X	 This file contains service routines needed to maintain an archive.
X
X    Language:
X	 Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X#if	MTS
X#include <mts.h>
X#endif
X
Xvoid	abort(), setstamp();
Xint	unlink();
X
Xvoid
Xopenarc(chg)			/* open archive */
X	int             chg;	/* true to open for changes */
X{
X	FILE           *fopen();/* file opener */
X
X	if (!(arc = fopen(arcname, OPEN_R))) {
X		if (chg) {
X			if (note)
X				printf("Creating new archive: %s\n", arcname);
X		}
X		else
X			abort("Archive not found: %s", arcname);
X	}
X#if	MTS
X		/* allow reading archives of max MTS record length */
X	else {
X		char *buffer, *malloc();
X		int inlen;
X		struct GDDSECT *region;
X
X		region=gdinfo(arc->_fd._fdub);
X		inlen=region->GDINLEN;
X		buffer=malloc(inlen);
X		setbuf(arc, buffer);
X		arc->_bufsiz=inlen;
X	}
X#endif
X	if (chg) {		/* if opening for changes */
X		if (!(new = fopen(newname, OPEN_W)))
X			abort("Cannot create archive copy: %s", newname);
X
X	changing = chg;		/* note if open for changes */
X	}
X}
X
Xvoid
Xclosearc(chg)			/* close an archive */
X	int             chg;	/* true if archive was changed */
X{
X	if (arc) {		/* if we had an initial archive */
X		fclose(arc);
X#if	!MTS
X		if (kludge)	/* kludge to update timestamp */
X			setstamp(arcname, olddate, oldtime);
X#endif
X	}
X	if (chg) {		/* if things have changed */
X		fclose(new);	/* close the new copy */
X		if (arc) {	/* if we had an original archive */
X			if (keepbak) {	/* if a backup is wanted */
X				unlink(bakname);	/* erase any old copies */
X				if (move(arcname, bakname))
X					abort("Cannot rename %s to %s", arcname, bakname);
X				printf("Keeping backup archive: %s\n", bakname);
X			} else if (unlink(arcname))
X				abort("Cannot delete old archive: %s", arcname);
X		}
X		if (move(newname, arcname))
X			abort("Cannot move %s to %s", newname, arcname);
X#if	!MTS
X		setstamp(arcname, arcdate, arctime);
X#endif
X	}
X}
X
X/*
X * CRC computation logic
X * 
X * The logic for this method of calculating the CRC 16 bit polynomial is taken
X * from an article by David Schwaderer in the April 1985 issue of PC Tech
X * Journal.
X */
X
Xstatic short      crctab[] =	/* CRC lookup table */
X{
X 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
X 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
X 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
X 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
X 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
X 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
X 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
X 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
X 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
X 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
X 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
X 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
X 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
X 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
X 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
X 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
X 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
X 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
X 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
X 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
X 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
X 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
X 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
X 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
X 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
X 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
X 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
X 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
X 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
X 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
X 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
X 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
X};
X
Xint
Xaddcrc(crc, c)			/* update a CRC check */
X	int             crc;	/* running CRC value */
X	unsigned char   c;	/* character to add */
X{
X	return ((crc >> 8) & 0x00ff) ^ crctab[(crc ^ c) & 0x00ff];
X}
SHAR_EOF
if test 4689 -ne "`wc -c < 'arcsvc.c'`"
then
	echo shar: "error transmitting 'arcsvc.c'" '(should have been 4689 characters)'
fi
fi
echo shar: "extracting 'arctst.c'" '(1284 characters)'
if test -f 'arctst.c'
then
	echo shar: "will not over-write existing file 'arctst.c'"
else
sed 's/^X//' << \SHAR_EOF > 'arctst.c'
X/*
X * $Header: arctst.c,v 1.4 88/04/19 01:40:28 hyc Exp $
X */
X
X/*
X * ARC - Archive utility - ARCTST
X * 
X * Version 2.12, created on 02/03/86 at 23:00:40
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to test archive integrity.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
Xvoid	openarc();
Xint	readhdr(), unpack();
X
Xvoid
Xtstarc()
X{				/* test integrity of an archive */
X	struct heads    hdr;	/* file header */
X	long            arcsize, ftell();	/* archive size */
X
X	openarc(0);		/* open archive for reading */
X	fseek(arc, 0L, 2);	/* move to end of archive */
X	arcsize = ftell(arc);	/* see how big it is */
X	fseek(arc, 0L, 0);	/* return to top of archive */
X
X	while (readhdr(&hdr, arc)) {
X		if (ftell(arc) + hdr.size > arcsize) {
X			printf("Archive truncated in file %s\n", hdr.name);
X			nerrs++;
X			break;
X		} else {
X			printf("Testing file: %-12s  ", hdr.name);
X			fflush(stdout);
X			if (unpack(arc, NULL, &hdr))
X				nerrs++;
X			else
X				printf("okay\n");
X		}
X	}
X
X	if (nerrs < 1)
X		printf("No errors detected\n");
X	else if (nerrs == 1)
X		printf("One error detected\n");
X	else
X		printf("%d errors detected\n", nerrs);
X}
SHAR_EOF
if test 1284 -ne "`wc -c < 'arctst.c'`"
then
	echo shar: "error transmitting 'arctst.c'" '(should have been 1284 characters)'
fi
fi
echo shar: "extracting 'arcunp.c'" '(5347 characters)'
if test -f 'arcunp.c'
then
	echo shar: "will not over-write existing file 'arcunp.c'"
else
sed 's/^X//' << \SHAR_EOF > 'arcunp.c'
X/*
X * $Header: arcunp.c,v 1.7 88/06/18 03:12:36 hyc Locked $
X */
X
X/*
X * ARC - Archive utility - ARCUNP
X * 
X * Version 3.17, created on 02/13/86 at 10:20:08
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to expand a file when
X * taking it out of an archive.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X#if	MTS
X#include <ctype.h>
X#endif
X
Xvoid	setcode(), init_usq(), init_ucr(), decomp(), sqdecomp();
Xvoid	abort(), putc_tst();
Xint	getc_usq(), getc_ucr(), addcrc();
X
X/* stuff for repeat unpacking */
X
X#define DLE 0x90		/* repeat byte flag */
X
Xstatic int      state;		/* repeat unpacking state */
X
X/* repeat unpacking states */
X
X#define NOHIST 0		/* no relevant history */
X#define INREP 1			/* sending a repeated value */
X
Xstatic short    crcval;		/* CRC check value */
Xstatic long     size;		/* bytes to read */
X#if	!DOS
Xstatic int	gotcr;		/* got a carriage return? */
X#endif
X
Xint
Xunpack(f, t, hdr)		/* unpack an archive entry */
X	FILE           *f, *t;	/* source, destination */
X	struct heads   *hdr;	/* pointer to file header data */
X{
X	int             c;	/* one char of stream */
X	void            putc_unp();
X	void            putc_ncr();
X	int             getc_unp();
X
X	/* setups common to all methods */
X#if	!DOS
X	gotcr = 0;
X#endif
X	crcval = 0;		/* reset CRC check value */
X	size = hdr->size;	/* set input byte counter */
X	state = NOHIST;		/* initial repeat unpacking state */
X	setcode();		/* set up for decoding */
X
X	/* use whatever method is appropriate */
X
X	switch (hdrver) {	/* choose proper unpack method */
X	case 1:		/* standard packing */
X	case 2:
X		while ((c = getc_unp(f)) != EOF)
X			putc_unp((char) c, t);
X		break;
X
X	case 3:		/* non-repeat packing */
X		while ((c = getc_unp(f)) != EOF)
X			putc_ncr((unsigned char) c, t);
X		break;
X
X	case 4:		/* Huffman squeezing */
X		init_usq(f);
X		while ((c = getc_usq(f)) != EOF)
X			putc_ncr((unsigned char) c, t);
X		break;
X
X	case 5:		/* Lempel-Zev compression */
X		init_ucr(0);
X		while ((c = getc_ucr(f)) != EOF)
X			putc_unp((char) c, t);
X		break;
X
X	case 6:		/* Lempel-Zev plus non-repeat */
X		init_ucr(0);
X		while ((c = getc_ucr(f)) != EOF)
X			putc_ncr((unsigned char) c, t);
X		break;
X
X	case 7:		/* L-Z plus ncr with new hash */
X		init_ucr(1);
X		while ((c = getc_ucr(f)) != EOF)
X			putc_ncr((unsigned char) c, t);
X		break;
X
X	case 8:		/* dynamic Lempel-Zev */
X		decomp(f, t);
X		break;
X
X	case 9:		/* Squashing */
X		sqdecomp(f, t);
X		break;
X
X	default:		/* unknown method */
X		if (warn) {
X			printf("I don't know how to unpack file %s\n", hdr->name);
X			printf("I think you need a newer version of ARC\n");
X			nerrs++;
X		}
X		fseek(f, hdr->size, 1);	/* skip over bad file */
X		return 1;	/* note defective file */
X	}
X
X	/* cleanups common to all methods */
X
X	if (crcval != hdr->crc) {
X		if (warn || kludge) {
X			printf("WARNING: File %s fails CRC check\n", hdr->name);
X			nerrs++;
X		}
X		return 1;	/* note defective file */
X	}
X	return 0;		/* file is okay */
X}
X
X/*
X * This routine is used to put bytes in the output file.  It also performs
X * various housekeeping functions, such as maintaining the CRC check value.
X */
X
Xvoid
Xputc_unp(c, t)			/* output an unpacked byte */
X	char            c;	/* byte to output */
X	FILE           *t;	/* file to output to */
X{
X	crcval = addcrc(crcval, c);	/* update the CRC check value */
X#if	MTS
X	if (!image)
X		atoe(&c, 1);
X#endif
X#if	DOS
X	putc_tst(c, t);
X#else
X	if (image)
X		putc_tst(c, t);
X	else {
X		if (gotcr) {
X			gotcr = 0;
X			if (c != '\n')
X				putc_tst('\r', t);
X		}
X		if (c == '\r')
X			gotcr = 1;
X		else
X			putc_tst(c, t);
X	}
X#endif
X}
X
X/*
X * This routine is used to decode non-repeat compression.  Bytes are passed
X * one at a time in coded format, and are written out uncoded. The data is
X * stored normally, except that runs of more than two characters are
X * represented as:
X * 
X * <char> <DLE> <count>
X * 
X * With a special case that a count of zero indicates a DLE as data, not as a
X * repeat marker.
X */
X
Xvoid
Xputc_ncr(c, t)			/* put NCR coded bytes */
X	unsigned char   c;	/* next byte of stream */
X	FILE           *t;	/* file to receive data */
X{
X	static int      lastc;	/* last character seen */
X
X	switch (state) {	/* action depends on our state */
X	case NOHIST:		/* no previous history */
X		if (c == DLE)	/* if starting a series */
X			state = INREP;	/* then remember it next time */
X		else
X			putc_unp(lastc = c, t);	/* else nothing unusual */
X		return;
X
X	case INREP:		/* in a repeat */
X		if (c)		/* if count is nonzero */
X			while (--c)	/* then repeatedly ... */
X				putc_unp(lastc, t);	/* ... output the byte */
X		else
X			putc_unp(DLE, t);	/* else output DLE as data */
X		state = NOHIST;	/* back to no history */
X		return;
X
X	default:
X		abort("Bad NCR unpacking state (%d)", state);
X	}
X}
X
X/*
X * This routine provides low-level byte input from an archive.  This routine
X * MUST be used, as end-of-file is simulated at the end of the archive entry.
X */
X
Xint
Xgetc_unp(f)			/* get a byte from an archive */
X	FILE           *f;	/* archive file to read */
X{
X	register int    xx;
X	unsigned char		code();
X
X	if (!size)		/* if no data left */
X		return EOF;	/* then pretend end of file */
X
X	size--;			/* deduct from input counter */
X	xx = getc(f);
X	return code(xx);	/* and return next decoded byte */
X}
SHAR_EOF
if test 5347 -ne "`wc -c < 'arcunp.c'`"
then
	echo shar: "error transmitting 'arcunp.c'" '(should have been 5347 characters)'
fi
fi
echo shar: "extracting 'arcusq.c'" '(2486 characters)'
if test -f 'arcusq.c'
then
	echo shar: "will not over-write existing file 'arcusq.c'"
else
sed 's/^X//' << \SHAR_EOF > 'arcusq.c'
X/*
X * $Header: arcusq.c,v 1.2 88/06/02 16:27:44 hyc Locked $
X */
X
X/*
X * ARC - Archive utility - ARCUSQ
X * 
X * Version 3.14, created on 07/25/86 at 13:04:19
X * 
X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X * 
X * By:  Thom Henderson
X * 
X * Description: This file contains the routines used to expand a file which was
X * packed using Huffman squeezing.
X * 
X * Most of this code is taken from an USQ program by Richard Greenlaw, which was
X * adapted to CI-C86 by Robert J. Beilstein.
X * 
X * Language: Computer Innovations Optimizing C86
X */
X#include <stdio.h>
X#include "arc.h"
X
Xvoid	abort();
Xint	getc_unp();
X
X/* stuff for Huffman unsqueezing */
X
X#define ERROR (-1)
X
X#define SPEOF 256		/* special endfile token */
X#define NUMVALS 257		/* 256 data values plus SPEOF */
X
Xextern	struct nd {		/* decoding tree */
X	int	child[2];	/* left, right */
X}               node[NUMVALS];	/* use large buffer */
X
Xstatic int      bpos;		/* last bit position read */
Xstatic int      curin;		/* last byte value read */
Xstatic int      numnodes;	/* number of nodes in decode tree */
X
Xstatic          short
Xget_int(f)			/* get a 16bit integer */
X	FILE           *f;	/* file to get it from */
X{
X	int	i,j;
X	i = getc_unp(f);
X	j = getc_unp(f) << 8;
X	return (i | j) & 0xFFFF;
X}
X
Xvoid
Xinit_usq(f)			/* initialize Huffman unsqueezing */
X	FILE           *f;	/* file containing squeezed data */
X{
X	int             i;	/* node index */
X
X	bpos = 99;		/* force initial read */
X
X	numnodes = get_int(f);
X
X	if (numnodes < 0 || numnodes >= NUMVALS)
X		abort("File has an invalid decode tree");
X
X	/* initialize for possible empty tree (SPEOF only) */
X
X	node[0].child[0] = -(SPEOF + 1);
X	node[0].child[1] = -(SPEOF + 1);
X
X	for (i = 0; i < numnodes; ++i) {	/* get decoding tree from
X						 * file */
X		node[i].child[0] = get_int(f);
X		node[i].child[1] = get_int(f);
X	}
X}
X
Xint
Xgetc_usq(f)			/* get byte from squeezed file */
X	FILE           *f;	/* file containing squeezed data */
X{
X	short             i;	/* tree index */
X
X	/* follow bit stream in tree to a leaf */
X
X	for (i = 0; i >= 0;) {	/* work down(up?) from root */
X		if (++bpos > 7) {
X			if ((curin = getc_unp(f)) == ERROR)
X				return (ERROR);
X			bpos = 0;
X
X			/* move a level deeper in tree */
X			i = node[i].child[1 & curin];
X		} else
X			i = node[i].child[1 & (curin >>= 1)];
X	}
X
X	/* decode fake node index to original data value */
X
X	i = -(i + 1);
X
X	/* decode special endfile token to normal EOF */
X
X	i = (i == SPEOF) ? EOF : i;
X	return i;
X}
SHAR_EOF
if test 2486 -ne "`wc -c < 'arcusq.c'`"
then
	echo shar: "error transmitting 'arcusq.c'" '(should have been 2486 characters)'
fi
fi
echo shar: "extracting 'getwd.c'" '(786 characters)'
if test -f 'getwd.c'
then
	echo shar: "will not over-write existing file 'getwd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'getwd.c'
X/*
X * 4.2bsd getwd simulation for Sys V.3
X */
X
X#include <stdio.h>
X
X#undef SYSV3
X
X#define MAXWD 1024	     /* limited by 4.2 getwd(2) */
X
X#ifdef SYSV3
X
Xchar *getcwd();
X
Xchar *
Xgetwd(path)
Xchar *path;
X{
X    return(getcwd(path,MAXWD));
X}
X
X#else
X
X/*
X * 4.2bsd getwd simulation for Sys V.2
X */
X
X#include <stdio.h>
X
X#define MAXWD 1024	     /* limited by 4.2 getwd(2) */
X
Xchar *
Xgetwd(path)
Xchar *path;
X{
X     char *nlp;
X     FILE *fp;
X     FILE *popen();
X     char *strrchr();
X
X	putenv("IFS= \t\n");
X     fp = popen("PATH=/bin:/usr/bin pwd", "r");
X     if (fp == NULL)
X	     return 0;
X     if (fgets(path, MAXWD, fp) == NULL) {
X	     (void) pclose(fp);
X	     return 0;
X     }
X     if ((nlp = strrchr(path, '\n')) != NULL)
X	     *nlp = '\0';
X     (void) pclose(fp);
X     return path;
X}
X#endif
X
SHAR_EOF
if test 786 -ne "`wc -c < 'getwd.c'`"
then
	echo shar: "error transmitting 'getwd.c'" '(should have been 786 characters)'
fi
fi
exit 0
#	End of shell archive



More information about the Unix-pc.sources mailing list