114544Ssam #ifndef lint 2*17017Ssam static char sccsid[] = "@(#)uncompact.c 4.7 (Berkeley) 08/25/84"; 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 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; 42*17017Ssam 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 5617016Ssam uncompact(file) 5717016Ssam char *file; 5817016Ssam { 5917016Ssam int ignore; 6017016Ssam FILE *setup(); 6117016Ssam 62*17017Ssam bottom->sons[RIGHT].top->next = flist; 63*17017Ssam bottom->sons[RIGHT].top = dirp; 6417016Ssam flist = dirq; 65*17017Ssam 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); 74*17017Ssam goto bad; 7510922Sshannon } 7617016Ssam *cp = '\0'; 7717016Ssam cfp = fopen(file, "r"); 7817016Ssam if (cfp == NULL) { 7917016Ssam fprintf(stderr, "uncompact: "), perror(file); 80*17017Ssam 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)) { 95*17017Ssam fprintf(stderr, "uncompact: "); 9617016Ssam if (uncfp != stdout) { 9717016Ssam if (ferror(uncfp)) 9817016Ssam perror(fname); 9917016Ssam else 10017016Ssam perror(infname); 10117016Ssam (void) unlink(fname); 102*17017Ssam } else 103*17017Ssam fprintf(stderr, 104*17017Ssam "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: 116*17017Ssam if (cfp != NULL) 117*17017Ssam fclose(cfp); 11817016Ssam return (1); 11917016Ssam } 12010922Sshannon 12117016Ssam decompress(cfp, uncfp) 12217016Ssam register FILE *cfp, *uncfp; 12317016Ssam { 12417016Ssam register struct node *p; 12517016Ssam register short j; 12617016Ssam register int m; 12717016Ssam register struct 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)) { 136*17017Ssam 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 157*17017Ssam p = p->sons[b].sp.p; 15810922Sshannon } 15917016Ssam } 16017016Ssam } 16117016Ssam 16217016Ssam FILE * 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 171*17017Ssam *ignore = 0; 17217016Ssam dp->integ = getc(cfp); 173*17017Ssam if (dp->integ != EOF) { 174*17017Ssam cp->integ = getc(cfp); 175*17017Ssam if (cp->integ != EOF) 176*17017Ssam dp->chars.hib = cp->integ & 0377; 177*17017Ssam } else 178*17017Ssam dp->integ = 0; 17917016Ssam if ((dp->integ &= 0177777) != COMPACTED) { 180*17017Ssam 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"); 191*17017Ssam if (uncfp == NULL) 192*17017Ssam 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) 198*17017Ssam goto bad2; 19917016Ssam putc(cp->chars.lob, uncfp); 20010922Sshannon 201*17017Ssam in[NC].fp = in[EF].fp = dict[0].sons[LEFT].sp.p = bottom = dict + 1; 202*17017Ssam bottom->sons[LEFT].count = bottom->sons[RIGHT].count = 203*17017Ssam dict[0].sons[RIGHT].count = 1; 204*17017Ssam dirp->next = dict[0].sons[RIGHT].top = bottom->sons[LEFT].top = 205*17017Ssam 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); 213*17017Ssam dict[0].sons[LEFT].count = 2; 21417016Ssam 215*17017Ssam dict[0].sons[RIGHT].sp.ch = cp->integ; 216*17017Ssam bottom->sons[LEFT].sp.ch = NC; 217*17017Ssam bottom->sons[RIGHT].sp.ch = EF; 21817016Ssam return (uncfp); 219*17017Ssam bad2: 220*17017Ssam fprintf(stderr, "uncompact: "); 221*17017Ssam perror(fname); 22217016Ssam bad: 22317016Ssam if (uncfp && uncfp != stdout) { 22417016Ssam (void) unlink(fname); 22517016Ssam fclose(uncfp); 22610922Sshannon } 22717016Ssam return (NULL); 22810922Sshannon } 229