114544Ssam #ifndef lint
2*33072Sbostic static char sccsid[] = "@(#)uncompact.c 4.8 (Berkeley) 12/21/87";
314544Ssam #endif
414544Ssam
510922Sshannon /*
610922Sshannon * Uncompact adaptive Huffman code input to output
710922Sshannon *
810922Sshannon * On - line algorithm
910922Sshannon *
1010922Sshannon * Input file does not contain decoding tree
1110922Sshannon *
1210922Sshannon * Written by Colin L. Mc Master (UCB) February 14, 1979
1310922Sshannon */
1410922Sshannon #include "compact.h"
1517016Ssam #include <strings.h>
1610922Sshannon
1717016Ssam union cio c;
1817016Ssam union cio d;
1917016Ssam char *infname; /* input file's name */
2017016Ssam char fname[MAXPATHLEN+1]; /* output file's name */
2117016Ssam struct stat status; /* compacted file status */
2210922Sshannon
2317016Ssam int verbose = 0;
2417016Ssam
main(argc,argv)2517016Ssam main(argc, argv)
2617016Ssam int argc;
2717016Ssam char *argv[];
2810922Sshannon {
2910922Sshannon register short j;
3010922Sshannon
3117016Ssam argc--, argv++;
3217016Ssam if (argc > 0 && strcmp(*argv, "-v") == 0) {
3317016Ssam verbose++;
3417016Ssam argc--, argv++;
3517016Ssam }
3617016Ssam dir[513].next = NULL;
3710922Sshannon for (head = dir + (j = 513); j--; ) {
3810922Sshannon dirp = head--;
3917016Ssam head->next = dirp;
4010922Sshannon }
4117016Ssam bottom = dirp->pt = dict;
4217017Ssam dict[0].sons[LEFT].top = dict[0].sons[RIGHT].top = dirp;
4317016Ssam dirq = dirp->next;
4417016Ssam in[EF].flags = FBIT | SEEN;
4517016Ssam if (argc == 0)
4617016Ssam exit(uncompact("-"));
4717016Ssam for (j = 0; j < argc; j++) {
4817016Ssam if (uncompact(argv[j]))
4917016Ssam exit(1);
5017016Ssam if (verbose && argc > 0)
5117016Ssam printf("%s uncompacted to %s\n", argv[j], fname);
5217016Ssam }
5317016Ssam exit(0);
5417016Ssam }
5510922Sshannon
uncompact(file)5617016Ssam uncompact(file)
5717016Ssam char *file;
5817016Ssam {
5917016Ssam int ignore;
6017016Ssam FILE *setup();
6117016Ssam
6217017Ssam bottom->sons[RIGHT].top->next = flist;
6317017Ssam bottom->sons[RIGHT].top = dirp;
6417016Ssam flist = dirq;
6517017Ssam uncfp = cfp = NULL;
6617016Ssam if (strcmp(file, "-") != 0) {
6717016Ssam char *cp;
6817016Ssam
6917016Ssam strcpy(fname, file);
7017016Ssam cp = rindex(fname, '.');
7117016Ssam if (cp == 0 || strcmp(cp, ".C") != 0) {
7217016Ssam fprintf(stderr,
7317016Ssam "uncompact: %s: File must have .C suffix.\n", file);
7417017Ssam goto bad;
7510922Sshannon }
7617016Ssam *cp = '\0';
7717016Ssam cfp = fopen(file, "r");
7817016Ssam if (cfp == NULL) {
7917016Ssam fprintf(stderr, "uncompact: "), perror(file);
8017017Ssam goto bad;
8110922Sshannon }
8217016Ssam (void) fstat(fileno(cfp), &status);
8317016Ssam } else
8417016Ssam cfp = stdin;
8517016Ssam infname = file;
8617016Ssam uncfp = setup(cfp, &ignore);
8717016Ssam if (uncfp == NULL) {
8817016Ssam if (ignore)
8917016Ssam goto done;
9017016Ssam goto bad;
9117016Ssam }
9217016Ssam decompress(cfp, uncfp);
9317016Ssam fflush(uncfp);
9417016Ssam if (ferror(uncfp) || ferror(cfp)) {
9517017Ssam fprintf(stderr, "uncompact: ");
9617016Ssam if (uncfp != stdout) {
9717016Ssam if (ferror(uncfp))
9817016Ssam perror(fname);
9917016Ssam else
10017016Ssam perror(infname);
10117016Ssam (void) unlink(fname);
10217017Ssam } else
10317017Ssam fprintf(stderr,
10417017Ssam "Unsuccessful uncompact of standard input to standard output.\n");
10517016Ssam goto bad;
10617016Ssam }
10717016Ssam if (uncfp != stdout && unlink(infname) < 0)
10817016Ssam fprintf(stderr, "uncompact: "), perror(infname);
10917016Ssam done:
11017016Ssam if (uncfp != NULL && uncfp != stdout)
11117016Ssam fclose(uncfp);
11217016Ssam if (cfp != NULL)
11317016Ssam fclose(cfp);
11417016Ssam return (0);
11517016Ssam bad:
11617017Ssam if (cfp != NULL)
11717017Ssam fclose(cfp);
11817016Ssam return (1);
11917016Ssam }
12010922Sshannon
decompress(cfp,uncfp)12117016Ssam decompress(cfp, uncfp)
12217016Ssam register FILE *cfp, *uncfp;
12317016Ssam {
12417016Ssam register struct node *p;
12517016Ssam register short j;
12617016Ssam register int m;
127*33072Sbostic register union cio *dp = &d;
12817016Ssam char b;
12917016Ssam
13017016Ssam p = dict;
13117016Ssam while ((c.integ = getc (cfp)) != EOF) {
13217016Ssam for (m = 0200; m; ) {
13317016Ssam b = (m & c.integ ? 1 : 0);
13417016Ssam m >>= 1;
13517016Ssam if (p->fath.flags & (b ? RLEAF : LLEAF)) {
13617017Ssam dp->integ = p->sons[b].sp.ch;
13717016Ssam if (dp->integ == EF)
13817016Ssam break;
13917016Ssam if (dp->integ == NC) {
14017016Ssam uptree(NC);
14117016Ssam dp->integ = 0;
14217016Ssam for (j = 8; j--; m >>= 1) {
14317016Ssam if (m == 0) {
14417016Ssam c.integ = getc(cfp);
14517016Ssam m = 0200;
14610922Sshannon }
14717016Ssam dp->integ <<= 1;
14817016Ssam if (m & c.integ)
14917016Ssam dp->integ++;
15010922Sshannon }
15117016Ssam insert(dp->integ);
15210922Sshannon }
15317016Ssam uptree(dp->integ);
15417016Ssam putc(dp->chars.lob, uncfp);
15517016Ssam p = dict;
15617016Ssam } else
15717017Ssam p = p->sons[b].sp.p;
15810922Sshannon }
15917016Ssam }
16017016Ssam }
16117016Ssam
16217016Ssam FILE *
setup(cfp,ignore)16317016Ssam setup(cfp, ignore)
16417016Ssam FILE *cfp;
16517016Ssam int *ignore;
16617016Ssam {
16717016Ssam FILE *uncfp = NULL;
16817016Ssam register union cio *dp = &d;
16917016Ssam register union cio *cp = &c;
17017016Ssam
17117017Ssam *ignore = 0;
17217016Ssam dp->integ = getc(cfp);
17317017Ssam if (dp->integ != EOF) {
17417017Ssam cp->integ = getc(cfp);
17517017Ssam if (cp->integ != EOF)
17617017Ssam dp->chars.hib = cp->integ & 0377;
17717017Ssam } else
17817017Ssam dp->integ = 0;
17917016Ssam if ((dp->integ &= 0177777) != COMPACTED) {
18017017Ssam fprintf(stderr, "uncompact: ");
18117016Ssam if (dp->integ == PACKED)
18217016Ssam fprintf(stderr, "%s: File is packed, use unpack.\n",
18317016Ssam infname);
18417016Ssam else
18517016Ssam fprintf(stderr, "%s: Not a compacted file.\n", infname);
18617016Ssam *ignore = 1;
18717016Ssam goto bad;
18817016Ssam }
18917016Ssam if (strcmp(infname, "-") != 0) {
19017016Ssam uncfp = fopen(fname, "w");
19117017Ssam if (uncfp == NULL)
19217017Ssam goto bad2;
19317016Ssam (void) fchmod(fileno(uncfp), status.st_mode);
19417016Ssam } else
19517016Ssam uncfp = stdout;
19617016Ssam cp->integ = getc(cfp);
19717016Ssam if (cp->integ == EOF)
19817017Ssam goto bad2;
19917016Ssam putc(cp->chars.lob, uncfp);
20010922Sshannon
20117017Ssam in[NC].fp = in[EF].fp = dict[0].sons[LEFT].sp.p = bottom = dict + 1;
20217017Ssam bottom->sons[LEFT].count = bottom->sons[RIGHT].count =
20317017Ssam dict[0].sons[RIGHT].count = 1;
20417017Ssam dirp->next = dict[0].sons[RIGHT].top = bottom->sons[LEFT].top =
20517017Ssam bottom->sons[RIGHT].top = dirq = NEW;
20617016Ssam dirq->next = NULL;
20717016Ssam dict[0].fath.fp = NULL;
20817016Ssam dirq->pt = bottom->fath.fp = in[cp->integ].fp = dict;
20917016Ssam in[cp->integ].flags = (FBIT | SEEN);
21017016Ssam in[NC].flags = SEEN;
21117016Ssam dict[0].fath.flags = RLEAF;
21217016Ssam bottom->fath.flags = (LLEAF | RLEAF);
21317017Ssam dict[0].sons[LEFT].count = 2;
21417016Ssam
21517017Ssam dict[0].sons[RIGHT].sp.ch = cp->integ;
21617017Ssam bottom->sons[LEFT].sp.ch = NC;
21717017Ssam bottom->sons[RIGHT].sp.ch = EF;
21817016Ssam return (uncfp);
21917017Ssam bad2:
22017017Ssam fprintf(stderr, "uncompact: ");
22117017Ssam perror(fname);
22217016Ssam bad:
22317016Ssam if (uncfp && uncfp != stdout) {
22417016Ssam (void) unlink(fname);
22517016Ssam fclose(uncfp);
22610922Sshannon }
22717016Ssam return (NULL);
22810922Sshannon }
229