From:	CSBVAX::MRGATE!info-vax-RELAY@KL.SRI.COM@SMTP  8-JUL-1988 21:38
To:	ARISIA::EVERHART
Subj:	ARC_C.SHAR10_OF_19


Received: from CORNELLC.CCS.CORNELL.EDU by KL.SRI.COM with TCP; Fri, 24 Jun 88 18:17:50 PDT
Received: from UNCAEDU.BITnet by CORNELLC.CCS.CORNELL.EDU ; Fri, 24 Jun 88 21:18:01 EDT
Received: from Stasis.MRC.AdhocNet.CA by UcEdu.UNCA.AdhocNet.CA with DECNET ;
          Fri, 24 Jun 88 09:34:26 MDT
Date:    Fri, 24 Jun 88 09:26:05 MDT
From:     ewilts%Ins.MRC.AdhocNet.CA%Stasis.MRC.AdhocNet.CA%UNCAEDU.@CORNELLC.CCS.CORNELL.EDU
         BITnet (Ed Wilts)
Message-Id: <880624092609.02a@Ins.MRC.AdhocNet.CA>
Subject: ARC_C.SHAR10_OF_19
To:       info-vax@kl.sri.com
X-ST-Vmsmail-To: INFOVAX

$Part10:
$ File_is="ARCPACK.C"
$ Check_Sum_is=1782521406
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
Xstatic char *RCSid = "$Header: arcpack.c,v 1.2 86/07/15 07:53:48 turner Exp $";
X
X/*
X * $Log:`009arcpack.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:53:48  turner
X *
X *
X * Revision 1.1  86/06/26  15:00:37  turner
X * initial version
X *
X *
X */
X
X/*  ARC - Archive utility - ARCPACK
X
X$define(tag,$$segment(@1,$$index(@1,=)+1))#
X$define(version,Version $tag(
XTED_VERSION DB =3.37), created on $tag(
XTED_DATE DB =02/03/86) at $tag(
XTED_TIME DB =22:58:01))#
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 compress a file
X         when placing it in an archive.
X
X    Language:
X         Computer Innovations Optimizing C86
X*/
X#include <stdio.h>
X#include "arc.h"
X
X/* stuff for non-repeat packing */
X
X#define DLE 0x90                       /* repeat sequence marker */
X
Xstatic unsigned char state;            /* current packing state */
X
X/* non-repeat packing states */
X
X#define NOHIST  0                      /* don't consider previous input*/
X#define SENTCHAR 1                     /* lastchar set, no lookahead yet */
X#define SENDNEWC 2                     /* run over, send new char next */
X#define SENDCNT 3                      /* newchar set, send count next */
X
X/* packing results */
X
Xstatic long stdlen;                    /* length for standard packing */
Xstatic INT crcval;                     /* CRC check value */
X
XINT pack(f,t,hdr)                          /* pack file into an archive */
XFILE *f, *t;                           /* source, destination */
Xstruct heads *hdr;                     /* pointer to header data */
X{
X INT c;                             /* one character of stream */
X    long ncrlen;                       /* length after packing */
X    long huflen;                       /* length after squeezing */
X    long lzwlen;                       /* length after crunching */
X    long pred_sq(), file_sq();         /* stuff for squeezing */
X    long pred_cm(), sqpred_cm();       /* dynamic crunching cleanup */
X    char tnam[STRLEN];                /* temporary name buffer */
X    char *makefnam();                  /* filename fixer upper */
X    FILE *crn = NULL;                  /* temporary crunch file */
X    INT getch();
X    INT getc_ncr();
X    INT putc_pak();
X
X    /* first pass - see which method is best */
X
X    if(!nocomp)                        /* if storage kludge not active */
X    {    if(note)
X            { printf(" analyzing, "); fflush(stdout);}
X
X         if(arctemp)                   /* use temp area if specified */
X              sprintf(tnam,"%s.CRN",arctemp);
X         else makefnam("$ARCTEMP.CRN",arcname,tnam);
X#if MSDOS
X         crn = fopen(tnam,"wrb");
X#endif
X#if BSD | ST
X         crn = fopen(tnam,"w+");
X#endif
X         state = NOHIST;               /* initialize ncr packing */
X         stdlen =  ncrlen = 0;         /* reset size counters */
X         crcval = 0;                   /* initialize CRC check value */
X         setcode();                    /* initialize encryption */
X
X`009 if(dosquash)
X         sqinit_cm(f,crn);
X`009 else
X         init_cm(f,crn);               /* initialize for crunching */
X         init_sq();                    /* initialize for squeeze scan */
X
X`009 if(dosquash)
X         while((c=getch(f))!=EOF)   /* for each byte of file */
X         {    ncrlen++;                /* one more packed byte */
X              scan_sq(c);              /* see what squeezing can do */
X              sqputc_cm(c,crn);          /* see what crunching can do */
X         }
X         else
X         while((c=getc_ncr(f))!=EOF)   /* for each byte of file */
X         {    ncrlen++;                /* one more packed byte */
X              scan_sq(c);              /* see what squeezing can do */
X              putc_cm(c,crn);          /* see what crunching can do */
X         }
X         huflen = pred_sq();           /* finish up after squeezing */
X`009 if(dosquash)
X         lzwlen = sqpred_cm(crn);
X`009 else
X         lzwlen = pred_cm(crn);        /* finish up after crunching */
X    }
X    else                               /* else kludge the method */
X    {    stdlen = 0;                   /* make standard look best */
X         ncrlen = huflen = lzwlen = 1;
X    }
X
X    /* standard set-ups common to all methods */
X
X    fseek(f,0L,0);                     /* rewind input */
X    hdr->crc = crcval;                 /* note CRC check value */
X    hdr->length = stdlen;              /* set actual file length */
X    state = NOHIST;                    /* reinitialize ncr packing */
X    setcode();                         /* reinitialize encryption */
X
X    /* choose and use the shortest method */
X
X    if(stdlen<=ncrlen && stdlen<=huflen && stdlen<=lzwlen)
X    {    if(kludge)                    /*DEBUG*/
X              printf("(%ld) ",lzwlen-stdlen);
X         if(note)
X          { printf("storing, "); fflush(stdout);}/* store w/out compression */
X         hdrver = 2;                   /* note packing method */
X         stdlen = crcval = 0;          /* recalc these for kludge */
X         while((c=getch(f))!=EOF)      /* store it straight */
X              putc_pak(c,t);
X         hdr->crc = crcval;
X         hdr->length = hdr->size = stdlen;
X    }
X
X    else if(ncrlen<huflen && ncrlen<lzwlen)
X    {    if(kludge)                    /*DEBUG*/
X              printf("(%ld) ",lzwlen-ncrlen);
X         if(note)
X              { printf("packing, ");
X              fflush(stdout);} /* pack w/repeat suppression */
X         hdrver = 3;                   /* note packing method */
X         hdr->size = ncrlen;           /* set data length */
X         while((c=getc_ncr(f))!=EOF)
X              putc_pak(c,t);
X    }
X
X    else if(huflen<lzwlen)
X    {    if(kludge)                    /*DEBUG*/
X              printf("(%ld) ",lzwlen-huflen);
X         if(note)
X            { printf("squeezing, "); fflush(stdout);}
X         hdrver = 4;                   /* note packing method */
X         hdr->size = file_sq(f,t);     /* note final size */
X    }
X
X    else
X    {    if(kludge)                    /*DEBUG*/
X              printf("(%ld) ",huflen-lzwlen);
X         if(note)
V            { printf(dosquash ? "squashing, " : "crunching, "); fflush(stdout);
X}
X         hdrver = dosquash ? 9 : 8;
X         hdr->size = lzwlen;           /* size should not change */
X         if(crn)                       /* if temp was created */
X         {    fseek(crn,0L,0);         /* then copy over crunched temp */
X              while((c=fgetc(crn))!=EOF)
X                   putc_tst(c,t);
X         }
X         else                          /* else re-crunch */
X         {    if(dosquash)
X`009`009sqinit_cm(f, t);
X`009      else
X`009`009init_cm(f,t);
X`009   if(dosquash)
X              while((c=getc_ncr(f))!=EOF)
X`009`009`009putc_cm(c,t);
X`009   else
X              while((c=getch(f))!=EOF)
X`009`009`009sqputc_cm(c,t);
X`009      if(dosquash)
X`009`009sqpred_cm(t);
X`009      else
X`009`009pred_cm(t);              /* finish up after crunching */
X         }
X    }
X
X    /* standard cleanups common to all methods */
X
X    if(crn)                            /* get rid of crunch temporary */
X    {    fclose(crn);
X         if(unlink(tnam) && warn)
X         {    printf("Cannot delete temporary file %s\n",tnam);
X              nerrs++;
X         }
X    }
X    if(note)
X         printf("done.\n");
X}
X
X/*  Non-repeat compression - text is passed through normally, except that
X    a run of more than two is encoded as:
X
X         <char> <DLE> <count>
X
X    Special case: a count of zero indicates that the DLE is really a DLE,
X    not a repeat marker.
X*/
X
XINT getc_ncr(f)                        /* get bytes with collapsed runs */
XFILE *f;                               /* file to get from */
X{
X#if vaxc
X    INT getch();
X#endif
X    static INT lastc;                  /* value returned on last call */
X    static INT repcnt;                 /* repetition counter */
X    static INT c;                      /* latest value seen */
X
X    switch(state)                      /* depends on our state */
X    {
X    case NOHIST:                       /* no relevant history */
X         state = SENTCHAR;
X         return (lastc = getch(f));      /* remember the value next time */
X
X    case SENTCHAR:                     /* char was sent. look ahead */
X         switch(lastc)                 /* action depends on char */
X         {
X         case DLE:                     /* if we sent a real DLE */
X              state = NOHIST;          /* then start over again */
X              return 0;                /* but note that the DLE was real */
X
X         case EOF:                     /* EOF is always a special case */
X              return EOF;
X
X         default:                      /* else test for a repeat */
X              for(repcnt=1; (c=getch(f))==lastc && repcnt<255; repcnt++)
X                   ;                   /* find end of run */
X
X              switch(repcnt)           /* action depends on run size */
X              {
X              case 1:                  /* not a repeat */
X                   return lastc = c;   /* but remember value next time */
X
X              case 2:                  /* a repeat, but too short */
X                   state = SENDNEWC;   /* send the second one next time */
X                   return lastc;
X
X              default:                 /* a run - compress it */
X                   state = SENDCNT;    /* send repeat count next time */
X                   return DLE;         /* send repeat marker this time */
X              }
X         }
X
X    case SENDNEWC:                     /* send second char of short run */
X         state = SENTCHAR;
X         return lastc = c;
X
X    case SENDCNT:                      /* sent DLE, now send count */
X         state = SENDNEWC;
X         return repcnt;
X
X    default:
X         abort("Bug - bad ncr state\n");
X    }
X}
X
Xstatic INT getch(f)                    /* special get char for packing */
XFILE *f;                               /* file to get from */
X{
X register INT c;                             /* a char from the file */
X
X    if((c=fgetc(f))!=EOF)              /* if not the end of file */
X    {    crcval = addcrc(crcval,c);    /* then update CRC check value */
X         stdlen++;                     /* and bump length counter */
X    }
X
X    return c;
X}
X
XINT putc_pak(c,f)                          /* put a packed byte into archive */
Xchar c;                                /* byte to put */
XFILE *f;                               /* archive to put it in */
X{
X    putc_tst(code(c),f);               /* put encoded byte, with checks */
X}
X
$ GoSub Convert_File
$ Goto Part11
