BSD 4 release
[unix-history] / usr / src / cmd / compact / uncompact.c
/*
* Uncompact adaptive Huffman code input to output
*
* On - line algorithm
*
* Input file does not contain decoding tree
*
* Written by Colin L. Mc Master (UCB) February 14, 1979
*/
#include "compact.h"
main (argc, argv)
short argc;
char *argv [ ];
{
register short i;
register struct node *p;
register short j;
register int m;
union cio c, d;
char b;
longint ic, n;
char fname [LNAME], *cp;
dir [513] . next = NULL;
for (head = dir + (j = 513); j--; ) {
dirp = head--;
head -> next = dirp;
}
bottom = dirp -> pt = dict;
dict [0] . top [0] = dict [0] . top [1] = dirp;
dirq = dirp -> next;
in [EF] . flags = FBIT | SEEN;
for (i = 1; ; i++) {
ic = oc = 0;
(bottom -> top [1]) -> next = flist;
bottom -> top [1] = dirp;
flist = dirq;
if (i >= argc) {
uncfp = stdout;
cfp = stdin;
}
else {
m = -1;
cp = fname;
for (j = 0; j < (LNAME - 3) && (*cp = argv [i][j]); j++)
if (*cp++ == '/') m = j;
if (cp [-1] == 'C' && cp [-2] == '.') cp [-2] = 0;
else {
fprintf (stderr, "%s: File name must end with \".C\"\n", argv [i]);
if (i == argc - 1) break;
continue;
}
if (j >= (LNAME - 3) || (j - m) > 15) {
fprintf (stderr, "File name too long -- %s\n", argv [i]);
if (i == argc - 1) break;
continue;
}
if ((cfp = fopen (argv [i], "r")) == NULL) {
perror (argv [i]);
if (i == argc - 1) break;
continue;
}
if ((uncfp = fopen (fname, "w")) == NULL) {
perror (fname);
fclose (cfp);
if (i == argc - 1) break;
continue;
}
fstat (fileno (cfp), &status);
chmod (fname, status.st_mode & 07777);
}
if ((c . integ = getc (cfp)) != EOF) {
if ((d . integ = getc (cfp)) != EOF) {
c . chars . hib = d . integ & 0377;
c . integ &= 0177777;
if (c . integ != COMPACTED) goto notcompact;
if ((c . integ = getc (cfp)) != EOF) {
putc (c . chars . lob, uncfp);
ic = 3;
in [NC] . fp = in [EF] . fp = dict [0] . sp [0] . p = bottom = dict + 1;
bottom -> count [0] = bottom -> count [1] = dict [0] . count [1] = 1;
dirp -> next = dict [0] . top [1] = bottom -> top [0] = bottom -> top [1] = dirq = NEW;
dirq -> next = NULL;
dict [0] . fath . fp = NULL;
dirq -> pt = bottom -> fath . fp = in [c . integ] . fp = dict;
in [c . integ] . flags = (FBIT | SEEN);
in [NC] . flags = SEEN;
dict [0] . fath . flags = RLEAF;
bottom -> fath . flags = (LLEAF | RLEAF);
dict [0] . count [0] = 2;
dict [0] . sp [1] . ch = c . integ;
bottom -> sp [0] . ch = NC;
bottom -> sp [1] . ch = EF;
p = dict;
while ((c . integ = getc (cfp)) != EOF) {
ic++;
for (m = 0200; m; ) {
b = (m & c . integ ? 1 : 0);
m >>= 1;
if (p -> fath . flags & (b ? RLEAF : LLEAF)) {
d . integ = p -> sp [b] . ch;
if (d . integ == EF) break;
if (d . integ == NC) {
uptree (NC);
d . integ = 0;
for (j = 8; j--; m >>= 1) {
if (m == 0) {
c . integ = getc (cfp);
ic++;
m = 0200;
}
d . integ <<= 1;
if (m & c . integ) d . integ++;
}
insert (d . integ);
}
uptree (d . integ);
putc (d . chars . lob, uncfp);
oc++;
p = dict;
}
else p = p -> sp [b] . p;
}
}
}
}
else goto notcompact;
}
else {
notcompact : if (i < argc) {
fprintf (stderr, "%s: ", argv [i]);
unlink (fname);
}
if (c . integ == PACKED) fprintf (stderr, "File is packed. Use unpack.\n");
else fprintf (stderr, "Not a compacted file.\n");
if (i >= argc) break;
goto closeboth;
}
if (ferror (uncfp) || ferror (cfp))
if (i < argc) {
if (ferror (uncfp))
perror (fname);
else
perror (argv [i]);
fprintf (stderr, "Unable to uncompact %s\n", argv [i]);
unlink (fname);
goto closeboth;
}
if (i >= argc) break;
fprintf (stderr, "%s uncompacted to %s\n", argv [i], fname);
unlink (argv [i]);
closeboth : fclose (cfp);
closein : fclose (uncfp);
if (i == argc - 1) break;
for (j = 256; j--; ) in [j] . flags = 0;
continue;
fail : fprintf (stderr, "Unsuccessful uncompact of standard input to standard output.\n");
break;
}
}