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