BSD 4_3_Tahoe release
[unix-history] / usr / src / old / compact / uncompact.c
#ifndef lint
static char sccsid[] = "@(#)uncompact.c 4.8 (Berkeley) 12/21/87";
#endif
/*
* 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"
#include <strings.h>
union cio c;
union cio d;
char *infname; /* input file's name */
char fname[MAXPATHLEN+1]; /* output file's name */
struct stat status; /* compacted file status */
int verbose = 0;
main(argc, argv)
int argc;
char *argv[];
{
register short j;
argc--, argv++;
if (argc > 0 && strcmp(*argv, "-v") == 0) {
verbose++;
argc--, argv++;
}
dir[513].next = NULL;
for (head = dir + (j = 513); j--; ) {
dirp = head--;
head->next = dirp;
}
bottom = dirp->pt = dict;
dict[0].sons[LEFT].top = dict[0].sons[RIGHT].top = dirp;
dirq = dirp->next;
in[EF].flags = FBIT | SEEN;
if (argc == 0)
exit(uncompact("-"));
for (j = 0; j < argc; j++) {
if (uncompact(argv[j]))
exit(1);
if (verbose && argc > 0)
printf("%s uncompacted to %s\n", argv[j], fname);
}
exit(0);
}
uncompact(file)
char *file;
{
int ignore;
FILE *setup();
bottom->sons[RIGHT].top->next = flist;
bottom->sons[RIGHT].top = dirp;
flist = dirq;
uncfp = cfp = NULL;
if (strcmp(file, "-") != 0) {
char *cp;
strcpy(fname, file);
cp = rindex(fname, '.');
if (cp == 0 || strcmp(cp, ".C") != 0) {
fprintf(stderr,
"uncompact: %s: File must have .C suffix.\n", file);
goto bad;
}
*cp = '\0';
cfp = fopen(file, "r");
if (cfp == NULL) {
fprintf(stderr, "uncompact: "), perror(file);
goto bad;
}
(void) fstat(fileno(cfp), &status);
} else
cfp = stdin;
infname = file;
uncfp = setup(cfp, &ignore);
if (uncfp == NULL) {
if (ignore)
goto done;
goto bad;
}
decompress(cfp, uncfp);
fflush(uncfp);
if (ferror(uncfp) || ferror(cfp)) {
fprintf(stderr, "uncompact: ");
if (uncfp != stdout) {
if (ferror(uncfp))
perror(fname);
else
perror(infname);
(void) unlink(fname);
} else
fprintf(stderr,
"Unsuccessful uncompact of standard input to standard output.\n");
goto bad;
}
if (uncfp != stdout && unlink(infname) < 0)
fprintf(stderr, "uncompact: "), perror(infname);
done:
if (uncfp != NULL && uncfp != stdout)
fclose(uncfp);
if (cfp != NULL)
fclose(cfp);
return (0);
bad:
if (cfp != NULL)
fclose(cfp);
return (1);
}
decompress(cfp, uncfp)
register FILE *cfp, *uncfp;
{
register struct node *p;
register short j;
register int m;
register union cio *dp = &d;
char b;
p = dict;
while ((c.integ = getc (cfp)) != EOF) {
for (m = 0200; m; ) {
b = (m & c.integ ? 1 : 0);
m >>= 1;
if (p->fath.flags & (b ? RLEAF : LLEAF)) {
dp->integ = p->sons[b].sp.ch;
if (dp->integ == EF)
break;
if (dp->integ == NC) {
uptree(NC);
dp->integ = 0;
for (j = 8; j--; m >>= 1) {
if (m == 0) {
c.integ = getc(cfp);
m = 0200;
}
dp->integ <<= 1;
if (m & c.integ)
dp->integ++;
}
insert(dp->integ);
}
uptree(dp->integ);
putc(dp->chars.lob, uncfp);
p = dict;
} else
p = p->sons[b].sp.p;
}
}
}
FILE *
setup(cfp, ignore)
FILE *cfp;
int *ignore;
{
FILE *uncfp = NULL;
register union cio *dp = &d;
register union cio *cp = &c;
*ignore = 0;
dp->integ = getc(cfp);
if (dp->integ != EOF) {
cp->integ = getc(cfp);
if (cp->integ != EOF)
dp->chars.hib = cp->integ & 0377;
} else
dp->integ = 0;
if ((dp->integ &= 0177777) != COMPACTED) {
fprintf(stderr, "uncompact: ");
if (dp->integ == PACKED)
fprintf(stderr, "%s: File is packed, use unpack.\n",
infname);
else
fprintf(stderr, "%s: Not a compacted file.\n", infname);
*ignore = 1;
goto bad;
}
if (strcmp(infname, "-") != 0) {
uncfp = fopen(fname, "w");
if (uncfp == NULL)
goto bad2;
(void) fchmod(fileno(uncfp), status.st_mode);
} else
uncfp = stdout;
cp->integ = getc(cfp);
if (cp->integ == EOF)
goto bad2;
putc(cp->chars.lob, uncfp);
in[NC].fp = in[EF].fp = dict[0].sons[LEFT].sp.p = bottom = dict + 1;
bottom->sons[LEFT].count = bottom->sons[RIGHT].count =
dict[0].sons[RIGHT].count = 1;
dirp->next = dict[0].sons[RIGHT].top = bottom->sons[LEFT].top =
bottom->sons[RIGHT].top = dirq = NEW;
dirq->next = NULL;
dict[0].fath.fp = NULL;
dirq->pt = bottom->fath.fp = in[cp->integ].fp = dict;
in[cp->integ].flags = (FBIT | SEEN);
in[NC].flags = SEEN;
dict[0].fath.flags = RLEAF;
bottom->fath.flags = (LLEAF | RLEAF);
dict[0].sons[LEFT].count = 2;
dict[0].sons[RIGHT].sp.ch = cp->integ;
bottom->sons[LEFT].sp.ch = NC;
bottom->sons[RIGHT].sp.ch = EF;
return (uncfp);
bad2:
fprintf(stderr, "uncompact: ");
perror(fname);
bad:
if (uncfp && uncfp != stdout) {
(void) unlink(fname);
fclose(uncfp);
}
return (NULL);
}