From:	CSBVAX::MRGATE!info-vax-RELAY@KL.SRI.COM@SMTP  9-JUL-1988 01:26
To:	ARISIA::EVERHART
Subj:	ARC_C.SHAR17_OF_19


Received: from CORNELLC.CCS.CORNELL.EDU by KL.SRI.COM with TCP; Fri, 24 Jun 88 18:27:36 PDT
Received: from UNCAEDU.BITnet by CORNELLC.CCS.CORNELL.EDU ; Fri, 24 Jun 88 21:27:53 EDT
Received: from Stasis.MRC.AdhocNet.CA by UcEdu.UNCA.AdhocNet.CA with DECNET ;
          Fri, 24 Jun 88 09:38:44 MDT
Date:    Fri, 24 Jun 88 09:29:26 MDT
From:     ewilts%Ins.MRC.AdhocNet.CA%Stasis.MRC.AdhocNet.CA%UNCAEDU.@CORNELLC.CCS.CORNELL.EDU
         BITnet (Ed Wilts)
Message-Id: <880624092928.02h@Ins.MRC.AdhocNet.CA>
Subject: ARC_C.SHAR17_OF_19
To:       info-vax@kl.sri.com
X-ST-Vmsmail-To: INFOVAX

$Part17:
$ File_is="ARCUNP.C"
$ Check_Sum_is=705508013
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
Xstatic char *RCSid = "$Header: arcunp.c,v 1.2 86/07/15 07:54:25 turner Exp $";
X
X/*
X * $Log:`009arcunp.c,v $
X * Hack-attack 1.3  86/12/20  01:23:45  wilhite@usceast.uucp
X * `009Bludgeoned into submission for VAX 11/780 BSD4.2
X *`009(ugly code, but fewer core dumps)
X *
X * Revision 1.2  86/07/15  07:54:25  turner
X *
X *
X * Revision 1.1  86/06/26  15:01:04  turner
X * initial version
X *
X *
X */
X
X/*  ARC - Archive utility - ARCUNP
X
X$define(tag,$$segment(@1,$$index(@1,=)+1))#
X$define(version,Version $tag(
XTED_VERSION DB =3.16), created on $tag(
XTED_DATE DB =02/03/86) at $tag(
XTED_TIME DB =23:01:16))#
X$undefine(tag)#
X    $version
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:  Thom Henderson
X
X    Description:
X         This file contains the routines used to expand a file
X         when taking it out of an archive.
X
X    Language:
X         Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
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 INT crcval;                     /* CRC check value */
Xstatic long size;                      /* bytes to read */
X
XINT unpack(f,t,hdr)                    /* unpack an archive entry */
XFILE *f, *t;                           /* source, destination */
Xstruct heads *hdr;                     /* pointer to file header data */
X{
X INT c;                             /* one char of stream */
X    INT putc_unp();
X    INT putc_ncr();
X    INT getc_unp();
X
X    /* setups common to all methods */
X
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    {
X    case 1:                            /* standard packing */
X    case 2:
X         while((c=getc_unp(f))!=EOF)
X              putc_unp(c,t);
X         break;
X
X    case 3:                            /* non-repeat packing */
X         while((c=getc_unp(f))!=EOF)
X              putc_ncr(c,t);
X         break;
X
X    case 4:                            /* Huffman squeezing */
X         init_usq(f);
X         while((c=getc_usq(f))!=EOF)
X              putc_ncr(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(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(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(c,t);
X         break;
X
X    case 8:                            /* dynamic Lempel-Zev */
X         decomp(f,t);
X         break;
X
X    case 9:
X`009 sqdecomp(f,t);
X`009 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&0xffff)!=(hdr->crc&0x0000ffff))
X    {    if(warn)
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/*  This routine is used to put bytes in the output file.  It also
X    performs various housekeeping functions, such as maintaining the
X    CRC check value.
X*/
X
XINT putc_unp(c,t)                   /* output an unpacked byte */
Xchar c;                                /* byte to output */
XFILE *t;                               /* file to output to */
X{
X    crcval = addcrc(crcval,c);         /* update the CRC check value */
X    putc_tst(c,t);
X}
X
X/*  This routine is used to decode non-repeat compression.  Bytes are
X    passed one at a time in coded format, and are written out uncoded.
X    The data is stored normally, except that runs of more than two
X    characters are represented as:
X
X         <char> <DLE> <count>
X
X    With a special case that a count of zero indicates a DLE as data,
X    not as a repeat marker.
X*/
X
XINT putc_ncr(c,t)                          /* put NCR coded bytes */
Xunsigned char c;                       /* next byte of stream */
XFILE *t;                               /* file to receive data */
X{
X    static INT lastc;                  /* last character seen */
X
X    switch(state)                      /* action depends on our state */
X    {
X    case NOHIST:                       /* no previous history */
X         if(c==DLE)                    /* if starting a series */
X              state = INREP;           /* then remember it next time */
X         else 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 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/*  This routine provides low-level byte input from an archive.  This
X    routine MUST be used, as end-of-file is simulated at the end of
X    the archive entry.
X*/
X
XINT getc_unp(f)                        /* get a byte from an archive */
XFILE *f;                               /* archive file to read */
X{
X    if(!size)                          /* if no data left */
X         return EOF;                   /* then pretend end of file */
X
X    size--;                            /* deduct from input counter */
X    return code(fgetc(f));             /* and return next decoded byte */
X}
X
$ GoSub Convert_File
$ File_is="ARCUSQ.C"
$ Check_Sum_is=85750201
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
Xstatic char *RCSid = "$Header: arcusq.c,v 1.2 86/07/15 07:54:30 turner Exp $";
X
X/*
X * $Log:`009arcusq.c,v $
X * Hack-attack 1.3  86/12/20  01:23:45  wilhite@usceast.uucp
X * `009Bludgeoned into submission for VAX 11/780 BSD4.2
X *`009(ugly code, but fewer core dumps)
X *
X * Revision 1.2  86/07/15  07:54:30  turner
X *
X *
X * Revision 1.1  86/06/26  15:01:07  turner
X * initial version
X *
X *
X */
X
X/*  ARC - Archive utility - ARCUSQ
X
X$define(tag,$$segment(@1,$$index(@1,=)+1))#
X$define(version,Version $tag(
XTED_VERSION DB =3.13), created on $tag(
XTED_DATE DB =01/30/86) at $tag(
XTED_TIME DB =20:11:42))#
X$undefine(tag)#
X    $version
X
X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
X
X    By:  Thom Henderson
X
X    Description:
X         This file contains the routines used to expand a file
X         which was packed using Huffman squeezing.
X
X         Most of this code is taken from an USQ program by Richard
X         Greenlaw, which was adapted to CI-C86 by Robert J. Beilstein.
X
X    Language:
X         Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
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 INT get_int(f)                  /* get an integer */
XFILE *f;                               /* file to get it from */
X{
X    INT i;
X
X    i = getc_unp(f);
X    return (short)(i | (getc_unp(f)<<8));
X}
X
XINT init_usq(f)                            /* initialize Huffman unsqueezing */
XFILE *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 file */
X    {    node[i].child[0] = get_int(f);
X         node[i].child[1] = get_int(f);
X    }
X}
X
XINT getc_usq(f)                        /* get byte from squeezed file */
XFILE *f;                               /* file containing squeezed data */
X{
X INT 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         }
X         else 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}
X
$ GoSub Convert_File
$ Goto Part18
