home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
pub
/
vmskermit32
/
vmslz2.arc
< prev
next >
Wrap
Text File
|
2020-01-01
|
22KB
|
932 lines
-h- lzdcm1.c Wed Jul 24 11:49:34 1985 USER$A:[MINOW.LZ]LZDCM1.C;11
/*
* lzdcmp [-options] [infile [outfile]]
*/
#ifdef DOCUMENTATION
title lzdcmp File Decompression
index File decompression
synopsis
.s.nf
lzdcmp [-options] [infile [outfile]]
.s.f
description
lzdcmp decompresses files compressed by lzcomp. The
documentation for lzcomp describes the process in
greater detail.
Options may be given in either case.
.lm +8
.p -8
-B Output file is "binary", not text. (Ignored
in VMS private mode.)
.p -8
-X 3 To read files compressed by an old Unix version
that doesn't generate header records.
.p -8
-V val Verbose (print status messages and debugging
information). The value selects the amount of verbosity.
Author
This version by Martin Minow. See lzcomp for more
details.
#endif
/*
* Compatible with compress.c, v3.0 84/11/27
*/
/*)BUILD
* $(PROGRAM) = lzdcmp
* $(INCLUDE) = lz.h
* $(FILES) = { lzdcm1.c lzdcm2.c lzdcm3.c lzio.c lzvio.c }
*/
#include "lz.h"
/*
* These global parameters are read from the compressed file.
* The decompressor needs them.
*/
short maxbits = BITS; /* settable max # bits/code */
code_int maxmaxcode = 1 << BITS;
/*
* Note, if export is zero or 1, the "true" value will be set from
* the file header. If it is 2, no header will be read.
*/
#if VMS_V4
flag export = 0; /* Assume VMS private */
#else
flag export = 1; /* Assume Unix compatible */
#endif
flag binary = FALSE; /* Read text if false */
flag block_compress = TRUE; /* TRUE if CLEAR enabled */
flag noheader = FALSE; /* No magic header if TRUE */
flag verbose = VERBOSE_DEFAULT; /* Non-zero for status/debug */
flag background = FALSE; /* TRUE (Unix) if detached */
flag is_compress = FALSE; /* For lzio.c (?) */
char *infilename = NULL; /* For error printouts */
char *outfilename = NULL; /* For openoutput and errors */
int firstcode; /* First code after internals */
static long start_time; /* Time we started (in msec) */
extern long cputime(); /* Returns process time in msec */
jmp_buf failure;
STREAM instream;
STREAM outstream;
char_type inbuffer[MAXIO];
char_type outbuffer[MAXIO];
static STREAM mem_stream;
#if VMS_V4
#include <descrip.h>
#ifndef FDLSTUFF
#define FDLSTUFF char
#endif
FDLSTUFF *fdl_input;
FDLSTUFF *fdl_output;
static struct dsc$descriptor fdl_descriptor;
#endif
main(argc, argv)
int argc;
char *argv[];
/*
* Decompress mainline
*/
{
int result;
#ifndef decus
/*
* background is TRUE if running detached from the command terminal.
*/
background = (signal(SIGINT, SIG_IGN) == SIG_IGN) ? TRUE : FALSE;
if (!background)
background = !isatty(fileno(stderr));
if (!background) {
if (verbose > 0)
signal(SIGINT, abort);
else {
signal(SIGINT, interrupt);
signal(SIGSEGV, address_error);
}
}
#endif
if (setjmp(failure) == 0) {
setup(argc, argv);
openinput();
get_magic_header(); /* Sets export, etc. */
openoutput();
if (verbose > 0)
start_time = cputime();
init_decompress();
result = decompress(&outstream);
if (!export
&& result != LZ_ETX
&& getcode() != (code_int) LZ_ETX) {
fprintf(stderr, "Decompress didn't finish correctly.\n");
goto fail;
}
lz_flush(&outstream);
#if DEBUG
if ((verbose & 04) != 0)
dump_tab(stdout);
#endif
if (verbose > 0) {
start_time = cputime() - start_time;
fprintf(stderr,
"%ld.%02ld seconds (process time) for decompression.\n",
start_time / 1000L, (start_time % 1000L) / 10L);
}
exit(IO_SUCCESS);
}
else {
fail: fprintf(stderr, "Error when decompressing \"%s\" to \"%s\"\n",
(infilename == NULL) ?
"<input file unknown>" : infilename,
(outfilename == NULL) ?
"<no output file>" : outfilename);
if (errno != 0)
perror("lzdcmp fatal error");
exit(IO_ERROR);
}
}
static
get_magic_header()
{
int head1;
int head2;
int head3;
head2 = 0;
if (export != 2) {
if ((head1 = GET(&instream)) != HEAD1_MAGIC) {
fprintf(stderr, "Incorrect first header byte 0x%X\n",
head1);
FAIL("can't get header");
}
head2 = GET(&instream);
head3 = GET(&instream);
switch (head2) {
case HEAD2_MAGIC:
export = 1;
break;
case VMS_HEAD2_MAGIC:
export = 0;
break;
default:
fprintf(stderr, "Incorrect second header byte 0x%X\n",
head2);
FAIL("can't get header");
}
maxbits = head3 & BIT_MASK;
block_compress = ((head3 & BLOCK_MASK) != 0) ? TRUE : FALSE;
#if DEBUG
if (verbose > 1) {
fprintf(stderr, "%s: compressed with %d bits,",
infilename, maxbits);
fprintf(stderr, " block compression %s.\n",
(block_compress != 0) ? "enabled" : "disabled");
}
#endif
}
if (maxbits > BITS) {
fprintf(stderr, "%s: compressed with %d bits,",
infilename, maxbits);
fprintf(stderr, " lzdcmp can only handle %d bits\n", BITS);
FAIL("too many bits");
}
maxmaxcode = 1 << maxbits;
if (export == 0)
firstcode = GET(&instream) + 0x100; /* From compressed file */
else if (block_compress)
firstcode = LZ_CLEAR + 1; /* Default */
else
firstcode = 256; /* Backwards compatible */
#if VMS_V4
if (!export) {
register code_int code;
char text[256];
/*
* Get the attribute record.
*/
if ((code = getcode()) != LZ_SOH) {
fprintf(stderr, "Expected header, read 0x%X\n", code);
FAIL("can't get header (private)");
}
init_decompress();
code = mem_decompress(text, sizeof text);
text[code] = EOS;
if (strncmp(text, ATT_NAME, ATT_SIZE) != 0) {
fprintf(stderr, "Expected \"%s\", read \"%.*s\"\n",
ATT_NAME, code, text);
FAIL("can't get attribute block header");
}
code = atoi(text + ATT_SIZE);
fdl_descriptor.dsc$a_pointer = malloc(code);
fdl_descriptor.dsc$w_length = code;
if ((code = mem_decompress(fdl_descriptor.dsc$a_pointer, code))
!= fdl_descriptor.dsc$w_length) {
fprintf(stderr, "\nError reading fdl attributes block,");
fprintf(stderr, " expected %d bytes, read %d bytes\n",
fdl_descriptor.dsc$w_length, code);
FAIL("can't get attribute block data");
}
if (verbose > 1) {
fprintf(stderr, "\nFDL information read from \"%s\"\n",
infilename);
fdl_dump(&fdl_descriptor, stderr);
}
if ((code = getcode()) != LZ_STX) {
fprintf(stderr, "\nExpecting start of text, got 0x%X\n", code);
FAIL("no start of text");
}
}
#endif
}
int
mem_decompress(buffer, size)
char_type *buffer;
int size;
/*
* Decompress up to size bytes to buffer. Return actual size.
*/
{
int result;
mem_stream.bp = mem_stream.bstart = buffer;
mem_stream.bend = buffer + size;
mem_stream.bsize = size;
mem_stream.func = lz_fail;
if ((result = decompress(&mem_stream)) == LZ_EOR
|| result == LZ_ETX)
return (mem_stream.bp - buffer);
else {
fprintf(stderr, "Decompress to memory failed.\n");
FAIL("can't decompress to memory");
}
return (-1); /* Can't happen */
}
static readonly char *helptext[] = {
"The following options are valid:",
"-B\tBinary file (important on VMS/RSX, ignored on Unix)",
"-M val\tSet the maximum number of code bits (unless header present)",
"-V val\tPrint status information or debugging data.",
"-X val\tSet export (compatibility) mode:",
"-X 0\tVMS private mode",
"-X 1\tCompatibility with Unix compress",
"-X 2\tDo not read a header, disable \"block-compress\" mode",
"\t(If a header is present, lzdcmp will properly configure itself,",
"\toverriding the -X, -B and -M flag values.",
NULL,
};
static
setup(argc, argv)
int argc;
char *argv[];
/*
* Get parameters and open files. Exit fatally on errors.
*/
{
register char *ap;
register int c;
char **hp;
auto int i;
int j;
#ifdef vms
argc = getredirection(argc, argv);
#endif
for (i = j = 1; i < argc; i++) {
ap = argv[i];
if (*ap++ != '-' || *ap == EOS) /* Filename? */
argv[j++] = argv[i]; /* Just copy it */
else {
while ((c = *ap++) != EOS) {
if (islower(c))
c = toupper(c);
switch (c) {
case 'B':
binary = TRUE;
break;
case 'M':
maxbits = getvalue(ap, &i, argv);
if (maxbits < MIN_BITS) {
fprintf(stderr, "Illegal -M value\n");
goto usage;
}
break;
case 'V':
verbose = getvalue(ap, &i, argv);
break;
case 'X':
export = getvalue(ap, &i, argv);
if (export < 0 || export > 3) {
fprintf(stderr, "Illegal -X value: %d\n", export);
goto usage;
}
block_compress = (export < 2);
noheader = (export == 3);
break;
default:
fprintf(stderr, "Unknown option '%c' in \"%s\"\n",
*ap, argv[i]);
usage: for (hp = helptext; *hp != NULL; hp++)
fprintf(stderr, "%s\n", *hp);
FAIL("unknown option");
} /* Switch on options */
} /* Everything for -xxx */
} /* If -option */
} /* For all argc's */
/* infilename = NULL; */ /* Set "stdin" signal */
/* outfilename = NULL; */ /* Set "stdout" signal */
switch (j) { /* Any file arguments? */
case 3: /* both files given */
if (!streq(argv[2], "-")) /* But - means stdout */
outfilename = argv[2];
case 2: /* Input file given */
if (!streq(argv[1], "-")) {
infilename = argv[1];
}
break;
case 0: /* None! */
case 1: /* No file arguments */
break;
default:
fprintf(stderr, "Too many file arguments\n");
FAIL("too many files");
}
}
static int
getvalue(ap, ip, argv)
register char *ap;
int *ip;
char *argv[];
/*
* Compile a "value". We are currently scanning *ap, part of argv[*ip].
* The following are possible:
* -x123 return (123) and set *ap to EOS so the caller
* ap^ cycles to the next argument.
*
* -x 123 *ap == EOS and argv[*ip + 1][0] is a digit.
* return (123) and increment *i to skip over the
* next argument.
*
* -xy or -x y return(1), don't touch *ap or *ip.
*
* Note that the default for "flag option without value" is 1. This
* can only cause a problem for the -M option where the value is
* mandatory. However, the result of 1 is illegal as it is less
* than INIT_BITS.
*/
{
register int result;
register int i;
i = *ip + 1;
if (isdigit(*ap)) {
result = atoi(ap);
*ap = EOS;
}
else if (*ap == EOS
&& argv[i] != NULL
&& isdigit(argv[i][0])) {
result = atoi(argv[i]);
*ip = i;
}
else {
result = 1;
}
return (result);
}
openinput()
{
#ifdef decus
if (infilename == NULL) {
infilename = malloc(257);
fgetname(stdin, infilename);
infilename = realloc(infilename, strlen(infilename) + 1);
}
if (freopen(infilename, "rn", stdin) == NULL) {
perror(infilename);
FAIL("can't open compressed input");
}
#else
#ifdef vms
#if VMS_V4
if (!export) {
if (infilename == NULL) {
infilename = malloc(256 + 1);
fgetname(stdin, infilename);
infilename = realloc(infilename, strlen(infilename) + 1);
}
if ((fdl_input = fdl_open(infilename, NULL)) == NULL) {
fdl_message(NULL, infilename);
FAIL("can't open compressed input (vms private)");
}
}
else
#endif
{
if (infilename == NULL) {
infilename = malloc(256 + 1);
fgetname(stdin, infilename);
infilename = realloc(infilename, strlen(infilename) + 1);
}
else {
if (freopen(infilename, "r", stdin) == NULL) {
perror(infilename);
FAIL("can't open compressed input (export)");
}
}
}
#else
if (infilename == NULL)
infilename = "<stdin>";
else {
if (freopen(infilename, "r", stdin) == NULL) {
perror(infilename);
FAIL("can't open input");
}
}
#endif
#endif
instream.bp = instream.bend = NULL;
instream.bstart = inbuffer;
instream.bsize = sizeof inbuffer;
instream.func = lz_fill;
}
openoutput()
{
#ifdef vms
#if VMS_V4
if (!export) {
fclose(stdout);
stdout = NULL;
if ((fdl_output =
fdl_create(&fdl_descriptor, outfilename)) == NULL) {
fprintf(stderr, "Can't create output file\n");
if ((fdl_status & 01) == 0)
fdl_message(NULL, outfilename);
FAIL("can't create output (vms private)");
}
if (outfilename == NULL) {
outfilename = malloc(256 + 1);
fdl_getname(fdl_output, outfilename);
outfilename = realloc(outfilename, strlen(outfilename) + 1);
}
}
else
#endif
{
/*
* Not VMS Version 4, or export mode.
*/
if (outfilename == NULL) {
outfilename = malloc(256 + 1);
fgetname(stdout, outfilename);
outfilename = realloc(outfilename, strlen(outfilename) + 1);
if (!binary)
goto do_reopen;
}
else {
if (binary) {
if (freopen(outfilename, "w", stdout) == NULL) {
perror(outfilename);
FAIL("can't create output (binary)");
}
}
else {
int i;
do_reopen:
if ((i = creat(outfilename, 0, "rat=cr", "rfm=var")) == -1
|| dup2(i, fileno(stdout)) == -1) {
perror(outfilename);
FAIL("can't create output (text)");
}
}
}
}
#else
#ifdef decus
if (outfilename == NULL) {
outfilename = malloc(256 + 1);
fgetname(stdout, outfilename);
outfilename = realloc(outfilename, strlen(outfilename) + 1);
if (binary) {
if (freopen(outfilename, "wn", stdout) == NULL) {
perror(outfilename);
FAIL("can't create (binary)");
}
}
}
else {
if (freopen(outfilename, (binary) ? "wn" : "w", stdout) == NULL) {
perror(outfilename);
FAIL("can't create");
}
}
#else
if (outfilename == NULL)
outfilename = "<stdout>";
else {
if (freopen(outfilename, "w", stdout) == NULL) {
perror(outfilename);
FAIL("can't create");
}
}
#endif
#endif
outstream.bp = outstream.bstart = outbuffer;
outstream.bend = outbuffer + sizeof outbuffer;
outstream.bsize = sizeof outbuffer;
outstream.func = lz_flush;
}
-h- lzdcm2.c Wed Jul 24 11:49:34 1985 USER$A:[MINOW.LZ]LZDCM2.C;10
/*
* l z d c m 2 . c
*
* Actual decompression code
*/
#include "lz.h"
/*
* These global parameters are read from the compressed file.
* The decompressor needs them.
*/
extern short maxbits; /* settable max # bits/code */
extern code_int maxmaxcode; /* 1 << maxbits */
static flag first_clear = TRUE;
/*
* Big data storage stuff
*/
static char_type stack[MAXSTACK];
#define STACK_TOP (&stack[MAXSTACK])
static U_short tab_prefix[1 << BITS]; /* prefix code */
static char_type tab_suffix[1 << BITS]; /* last char in string */
code_int next_code;
#if DEBUG
#define CHECK(what) \
if (stp <= stack) { \
fprintf(stderr, "Stack overflow -- %s\n", what); \
abort(); \
}
#else
#define CHECK(what)
#endif
int
decompress(out)
STREAM *out;
/*
* Decompress instream (global) to out. Returns "end" signal:
* -1 end of file
* LZ_EOR end of record
* LZ_ETX end of segment
*/
{
register char_type *stp; /* Stack pointer */
register code_int code, oldcode, incode;
register int final; /* End of a sequence? */
extern code_int getcode();
stp = STACK_TOP;
final = oldcode = getcode();
PUT((char) final, out);
while ((code = getcode()) >= 0) {
test: if (code >= LZ_CLEAR && code < firstcode) {
lz_putbuf(stp, STACK_TOP - stp, out);
stp = STACK_TOP;
switch (code) {
case LZ_ETX:
case LZ_EOR:
goto finish;
case LZ_SOH: /* Unexpected */
case LZ_STX: /* Unexpected */
default:
fprintf(stderr, "\nUnexpected control 0x%X\n", code);
FAIL("Unexpected control");
case LZ_CLEAR:
init_decompress(); /* Before getcode() !! */
if ((code = getcode()) < 0
|| (export && code == LZ_CLEAR))
goto finish;
else {
/*
* init_decompress has set next_code to firstcode,
* however, for magical reasons, we want to toss
* the next substring, so we set next_code so
* that the tab_... entry is effectively ignored.
* Note below that tab_prefix[next_code] is set
* to the character before the LZ_CLEAR and
* tab_suffix to the character after the LZ_CLEAR.
* But, these values have no relationship to one
* another, so, by decrementing next_code, they
* will be ignored. (I think.)
*/
next_code--;
goto test;
}
}
}
incode = code;
/*
* Special case for KwKwK string.
*/
if (code >= next_code) {
CHECK("KwKwK");
*--stp = final;
code = oldcode;
}
/*
* Generate output characters in reverse order
*/
#ifdef interdata
while (((unsigned long) code) >= ((unsigned long) NBR_CHAR)) {
#else
while (code >= NBR_CHAR) {
#endif
CHECK("generate output");
*--stp = tab_suffix[code];
code = tab_prefix[code];
}
CHECK("final char");
*--stp = final = tab_suffix[code];
/*
* And put them out in forward order
*/
lz_putbuf(stp, STACK_TOP - stp, out);
stp = STACK_TOP;
/*
* Generate the new entry.
*/
if ((code = next_code) < maxmaxcode) {
tab_prefix[code] = (U_short) oldcode;
tab_suffix[code] = final;
next_code++;
}
/*
* Remember previous code.
*/
oldcode = incode;
}
finish:
return (code);
}
init_decompress()
/*
* Called on cold start, or on LZ_SOH, LZ_STX, LZ_CLEAR.
*/
{
register char_type *cp;
register U_short *up;
register int code;
if (first_clear) {
for (cp = &tab_suffix[0], code = 0; cp < &tab_suffix[NBR_CHAR];)
*cp++ = code++;
first_clear = FALSE;
}
else {
#if ((NBR_CHAR % 8) != 0)
<< error, the following won't work >>
#endif
for (up = &tab_prefix[0]; up < &tab_prefix[NBR_CHAR];) {
*up++ = 0;
*up++ = 0;
*up++ = 0;
*up++ = 0;
*up++ = 0;
*up++ = 0;
*up++ = 0;
*up++ = 0;
}
}
next_code = firstcode;
}
#if DEBUG
dump_tab(dumpfd)
FILE *dumpfd;
/*
* dump string table
*/
{
register char_type *stp; /* Stack pointer */
register int i;
register int ent;
extern char *dumpchar();
stp = STACK_TOP;
fprintf(dumpfd, "%d %s in string table\n",
next_code, (next_code == 1) ? "entry" : "entries");
for (i = 0; i < next_code; i++) {
fprintf(dumpfd, "%5d: %5d/'%s' ",
i, tab_prefix[i], dumpchar(tab_suffix[i]));
for (ent = i;;) {
*--stp = tab_suffix[ent];
if (ent < firstcode)
break;
ent = tab_prefix[ent];
}
dumptext(stp, STACK_TOP - stp, dumpfd);
stp = STACK_TOP;
}
}
#endif
-h- lzdcm3.c Wed Jul 24 11:49:34 1985 USER$A:[MINOW.LZ]LZDCM3.C;14
/*
* l z d c m 3 . c
*
* Read codes from the input stream.
*/
#include "lz.h"
#if !vax_asm
static readonly char_type rmask[9] = {
0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF
};
#endif
#if DEBUG
extern int col;
static int todump;
#endif
/*
* getcode()
*
* Read one code from the standard input. If EOF, return -1.
* Inputs:
* stdin (via GET)
* Outputs:
* code or -1 is returned.
*/
extern code_int next_code;
extern STREAM instream;
extern code_int maxmaxcode;
extern short maxbits;
static short n_bits = INIT_BITS;
static code_int maxcode = MAXCODE(INIT_BITS);
/*
* buf[] contains 8-bit data read from the input stream. getcode()
* treats buf[] as a vector of bits, repacking it into variable-bit codes.
*/
static char_type buf[BITS];
static int offset = 0; /* Offset into buf IN BITS */
static int size = 0; /* Actual size of buf IN BITS */
code_int
getcode()
{
/*
* On the VAX (4.2 bsd), it is important to have the register
* declarations in exactly the order given, or the asm will break.
*/
register code_int code;
register int r_off, bits;
register char_type *bp;
bp = buf;
if (next_code > maxcode) {
n_bits++;
if (n_bits == maxbits)
maxcode = maxmaxcode;
else {
maxcode = MAXCODE(n_bits);
}
size = 0;
#if DEBUG
if (verbose > 2) {
fprintf(stderr, "\nChange to %d bits", n_bits);
col = 74;
}
#endif
}
if (offset >= size) {
size = lz_getbuf(buf, n_bits, &instream);
#if DEBUG
if (verbose > 4 || todump > 0) {
dumphex(buf, size, stderr);
if (todump > 0)
todump -= size;
}
#endif
if (size <= 0)
return (-1); /* end of file */
offset = 0;
/*
* Round size down to integral number of codes in the buffer.
* (Expressed as a number of bits).
*/
size = (size << 3) - (n_bits - 1);
}
r_off = offset;
bits = n_bits;
#if vax_asm
asm("extzv r10,r9,(r8),r11");
#else
/*
* Get to the first byte.
*/
bp += (r_off >> 3);
r_off &= 7;
/*
* Get first part (low order bits)
*/
#if UCHAR
code = (*bp++ >> r_off);
#else
/*
* Don't touch the 0xFF; it prevents sign extension.
*/
code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xFF;
#endif
bits -= (8 - r_off);
r_off = 8 - r_off; /* now, offset into code word */
/*
* Get any 8 bit parts in the middle (<=1 for up to 16 bits).
*/
if (bits >= 8) {
#if UCHAR
code |= *bp++ << r_off;
#else
code |= (*bp++ & 0xFF) << r_off;
#endif
r_off += 8;
bits -= 8;
}
/* high order bits. */
#if UCHAR
code |= (*bp & rmask[bits]) << r_off;
#else
code |= (*bp & rmask[bits]) << r_off;
#endif
/*
* End of non-vax (Unix) specific code.
*/
#endif
offset += n_bits;
if (code >= LZ_CLEAR && code < firstcode) {
switch (code) {
case LZ_SOH:
case LZ_STX:
case LZ_CLEAR:
size = 0; /* Force read next time */
n_bits = INIT_BITS;
maxcode = MAXCODE(INIT_BITS);
#if DEBUG
if (verbose > 1) {
fprintf(stderr, "Read %s (%d)\n",
lz_names[code - LZ_CLEAR], code);
todump = 32;
}
#endif
break;
}
}
#if DEBUG
if (verbose > 3) {
fprintf(stderr, "%c%5d %5d",
((col += 12) >= 72) ? (col = 0, '\n') : ' ',
code, next_code);
if (code >= LZ_CLEAR && code < firstcode) {
fprintf(stderr, " = %s", lz_names[code - LZ_CLEAR]);
col = 74;
}
}
#endif
return (code);
}