home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
cpm68k
/
arc68k.arc
/
ARCUNP.C
< prev
next >
Wrap
Text File
|
1987-11-27
|
7KB
|
183 lines
/*
* arcunp.c 1.1
*
* Author: Thom Henderson
* Original System V port: Mike Stump
* Enhancements, Bug fixes, and cleanup: Chris Seaman
* Date: Fri Mar 20 09:57:02 1987
* Last Mod. 3/21/87
*
*/
/*
* ARC - Archive utility - ARCUNP
*
* Version 3.16, created on 02/03/86 at 23:01:16
*
* (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
*
* Description:
* This file contains the routines used to expand a file
* when taking it out of an archive.
*/
#include "arc.h"
/* stuff for repeat unpacking */
#define DLE 0x90 /* repeat byte flag */
static INT state; /* repeat unpacking state */
/* repeat unpacking states */
#define NOHIST 0 /* no relevant history */
#define INREP 1 /* sending a repeated value */
static unsigned crcval; /* CRC check value */
static long size; /* bytes to read */
INT unpack(f,t,hdr) /* unpack an archive entry */
FILE *f, *t; /* source, destination */
struct heads *hdr; /* pointer to file header data */
{
INT c; /* one char of stream */
INT putc_unp();
INT putc_ncr();
INT getc_unp();
/* setups common to all methods */
crcval = 0; /* reset CRC check value */
size = hdr->size; /* set input byte counter */
state = NOHIST; /* initial repeat unpacking state */
setcode(); /* set up for decoding */
/* use whatever method is appropriate */
switch(hdrver) { /* choose proper unpack method */
case 1: /* standard packing */
case 2:
while ((c = getc_unp(f)) != EOF)
putc_unp(c,t);
break;
case 3: /* non-repeat packing */
while ((c = getc_unp(f)) != EOF)
putc_ncr(c,t);
break;
case 4: /* Huffman squeezing */
init_usq(f);
while ((c = getc_usq(f)) != EOF)
putc_ncr(c,t);
break;
case 5: /* Lempel-Zev compression */
init_ucr(0);
while ((c = getc_ucr(f)) != EOF)
putc_unp(c,t);
break;
case 6: /* Lempel-Zev plus non-repeat */
init_ucr(0);
while ((c = getc_ucr(f)) != EOF)
putc_ncr(c,t);
break;
case 7: /* L-Z plus ncr with new hash */
init_ucr(1);
while ((c = getc_ucr(f)) != EOF)
putc_ncr(c,t);
break;
case 8: /* dynamic Lempel-Zev */
decomp(f,t);
break;
default: /* unknown method */
if (warn)
{
printf("I don't know how to unpack file %s\n",hdr->name);
printf("I think you need a newer version of ARC\n");
nerrs++;
}
fseek(f,hdr->size,1); /* skip over bad file */
return(1); /* note defective file */
}
/* cleanups common to all methods */
if ((crcval & 0xffff) != (hdr->crc & 0x0000ffff)) {
if (warn) {
printf("WARNING: File %s fails CRC check\n",hdr->name);
printf("expected %04.4x got %04.4x\n",crcval,hdr->crc);
nerrs++;
}
return(1); /* note defective file */
}
return(0); /* file is okay */
}
/*
* This routine is used to put bytes in the output file. It also
* performs various housekeeping functions, such as maintaining the
* CRC check value.
*/
static INT putc_unp(c,t) /* output an unpacked byte */
char c; /* byte to output */
FILE *t; /* file to output to */
{
crcval = addcrc(crcval,(c & 255)); /* update the CRC check value */
putc_tst(c,t);
}
/*
* This routine is used to decode non-repeat compression. Bytes are
* passed one at a time in coded format, and are written out uncoded.
* The data is stored normally, except that runs of more than two
* characters are represented as:
*
* <char> <DLE> <count>
*
* With a special case that a count of zero indicates a DLE as data,
* not as a repeat marker.
*/
INT putc_ncr(c,t) /* put NCR coded bytes */
char c; /* next byte of stream */
FILE *t; /* file to receive data */
{
static INT lastc; /* last character seen */
switch(state) /* action depends on our state */
{
case NOHIST: /* no previous history */
if (c==DLE) /* if starting a series */
state = INREP; /* then remember it next time */
else
putc_unp(lastc=(c&0x00ff),t); /* else nothing unusual */
return;
case INREP: /* in a repeat */
if (c) /* if count is nonzero */
while (--c) /* then repeatedly ... */
putc_unp(lastc,t); /* ... output the byte */
else
putc_unp(DLE,t); /* else output DLE as data */
state = NOHIST; /* back to no history */
return;
default:
abort("Bad NCR unpacking state (%d)",state);
}
}
/*
* This routine provides low-level byte input from an archive. This
* routine MUST be used, as end-of-file is simulated at the end of
* the archive entry.
*/
INT getc_unp(f) /* get a byte from an archive */
FILE *f; /* archive file to read */
{
if (!size) /* if no data left */
return(EOF); /* then pretend end of file */
size--; /* deduct from input counter */
return(code(fgetc(f))); /* and return next decoded byte */
}