Path: utzoo!attcan!uunet!lll-winken!lll-tis!helios.ee.lbl.gov!pasteur!ucbvax!CORNELLC.CCS.CORNELL.EDU.BITNET!ewilts%Ins.MRC.AdhocNet.CA%Stasis.MRC.AdhocNet.CA%UNCAEDU.
From: ewilts%Ins.MRC.AdhocNet.CA%Stasis.MRC.AdhocNet.CA%UNCAEDU.@CORNELLC.CCS.CORNELL.EDU.BITNET (Ed Wilts)
Newsgroups: comp.os.vms
Subject: ARC_C.SHAR10_OF_19
Message-ID: <880624092609.02a@Ins.MRC.AdhocNet.CA>
Date: 24 Jun 88 15:26:05 GMT
Sender: daemon@ucbvax.BERKELEY.EDU
Organization: The Internet
Lines: 305
$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
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(ncrlensize = ncrlen; /* set data length */
X while((c=getc_ncr(f))!=EOF)
X putc_pak(c,t);
X }
X
X else if(huflensize = 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
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