114544Ssam #ifndef lint 2*17016Ssam static char sccsid[] = "@(#)uncompact.c 4.6 (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" 15*17016Ssam #include <strings.h> 1610922Sshannon 17*17016Ssam union cio c; 18*17016Ssam union cio d; 19*17016Ssam char *infname; /* input file's name */ 20*17016Ssam char fname[MAXPATHLEN+1]; /* output file's name */ 21*17016Ssam struct stat status; /* compacted file status */ 2210922Sshannon 23*17016Ssam int verbose = 0; 24*17016Ssam 25*17016Ssam main(argc, argv) 26*17016Ssam int argc; 27*17016Ssam char *argv[]; 2810922Sshannon { 2910922Sshannon register short j; 3010922Sshannon 31*17016Ssam argc--, argv++; 32*17016Ssam if (argc > 0 && strcmp(*argv, "-v") == 0) { 33*17016Ssam verbose++; 34*17016Ssam argc--, argv++; 35*17016Ssam } 36*17016Ssam dir[513].next = NULL; 3710922Sshannon for (head = dir + (j = 513); j--; ) { 3810922Sshannon dirp = head--; 39*17016Ssam head->next = dirp; 4010922Sshannon } 41*17016Ssam bottom = dirp->pt = dict; 42*17016Ssam dict[0].top[LEFT] = dict[0].top[RIGHT] = dirp; 43*17016Ssam dirq = dirp->next; 44*17016Ssam in[EF].flags = FBIT | SEEN; 45*17016Ssam if (argc == 0) 46*17016Ssam exit(uncompact("-")); 47*17016Ssam for (j = 0; j < argc; j++) { 48*17016Ssam if (uncompact(argv[j])) 49*17016Ssam exit(1); 50*17016Ssam if (verbose && argc > 0) 51*17016Ssam printf("%s uncompacted to %s\n", argv[j], fname); 52*17016Ssam } 53*17016Ssam exit(0); 54*17016Ssam } 5510922Sshannon 56*17016Ssam uncompact(file) 57*17016Ssam char *file; 58*17016Ssam { 59*17016Ssam int ignore; 60*17016Ssam FILE *setup(); 61*17016Ssam 62*17016Ssam bottom->top[1]->next = flist; 63*17016Ssam bottom->top[1] = dirp; 64*17016Ssam flist = dirq; 65*17016Ssam if (strcmp(file, "-") != 0) { 66*17016Ssam char *cp; 67*17016Ssam 68*17016Ssam strcpy(fname, file); 69*17016Ssam cp = rindex(fname, '.'); 70*17016Ssam if (cp == 0 || strcmp(cp, ".C") != 0) { 71*17016Ssam fprintf(stderr, 72*17016Ssam "uncompact: %s: File must have .C suffix.\n", file); 73*17016Ssam return; 7410922Sshannon } 75*17016Ssam *cp = '\0'; 76*17016Ssam cfp = fopen(file, "r"); 77*17016Ssam if (cfp == NULL) { 78*17016Ssam fprintf(stderr, "uncompact: "), perror(file); 79*17016Ssam return; 8010922Sshannon } 81*17016Ssam (void) fstat(fileno(cfp), &status); 82*17016Ssam } else 83*17016Ssam cfp = stdin; 84*17016Ssam infname = file; 85*17016Ssam uncfp = setup(cfp, &ignore); 86*17016Ssam if (uncfp == NULL) { 87*17016Ssam if (ignore) 88*17016Ssam goto done; 89*17016Ssam goto bad; 90*17016Ssam } 91*17016Ssam decompress(cfp, uncfp); 92*17016Ssam fflush(uncfp); 93*17016Ssam if (ferror(uncfp) || ferror(cfp)) { 94*17016Ssam if (uncfp != stdout) { 95*17016Ssam if (ferror(uncfp)) 96*17016Ssam perror(fname); 97*17016Ssam else 98*17016Ssam perror(infname); 99*17016Ssam (void) unlink(fname); 100*17016Ssam } 101*17016Ssam goto bad; 102*17016Ssam } 103*17016Ssam if (uncfp != stdout && unlink(infname) < 0) 104*17016Ssam fprintf(stderr, "uncompact: "), perror(infname); 105*17016Ssam done: 106*17016Ssam if (uncfp != NULL && uncfp != stdout) 107*17016Ssam fclose(uncfp); 108*17016Ssam if (cfp != NULL) 109*17016Ssam fclose(cfp); 110*17016Ssam return (0); 111*17016Ssam bad: 112*17016Ssam fprintf(stderr, "uncompact: "); 113*17016Ssam if (strcmp(infname, "-") != 0) 114*17016Ssam perror(infname); 115*17016Ssam else 116*17016Ssam fprintf(stderr, 117*17016Ssam "Unsuccessful uncompact of standard input to standard output.\n"); 118*17016Ssam return (1); 119*17016Ssam } 12010922Sshannon 121*17016Ssam decompress(cfp, uncfp) 122*17016Ssam register FILE *cfp, *uncfp; 123*17016Ssam { 124*17016Ssam register struct node *p; 125*17016Ssam register short j; 126*17016Ssam register int m; 127*17016Ssam register struct cio *dp = &d; 128*17016Ssam char b; 129*17016Ssam 130*17016Ssam p = dict; 131*17016Ssam while ((c.integ = getc (cfp)) != EOF) { 132*17016Ssam for (m = 0200; m; ) { 133*17016Ssam b = (m & c.integ ? 1 : 0); 134*17016Ssam m >>= 1; 135*17016Ssam if (p->fath.flags & (b ? RLEAF : LLEAF)) { 136*17016Ssam dp->integ = p->sp[b].ch; 137*17016Ssam if (dp->integ == EF) 138*17016Ssam break; 139*17016Ssam if (dp->integ == NC) { 140*17016Ssam uptree(NC); 141*17016Ssam dp->integ = 0; 142*17016Ssam for (j = 8; j--; m >>= 1) { 143*17016Ssam if (m == 0) { 144*17016Ssam c.integ = getc(cfp); 145*17016Ssam m = 0200; 14610922Sshannon } 147*17016Ssam dp->integ <<= 1; 148*17016Ssam if (m & c.integ) 149*17016Ssam dp->integ++; 15010922Sshannon } 151*17016Ssam insert(dp->integ); 15210922Sshannon } 153*17016Ssam uptree(dp->integ); 154*17016Ssam putc(dp->chars.lob, uncfp); 155*17016Ssam p = dict; 156*17016Ssam } else 157*17016Ssam p = p->sp[b].p; 15810922Sshannon } 159*17016Ssam } 160*17016Ssam } 161*17016Ssam 162*17016Ssam FILE * 163*17016Ssam setup(cfp, ignore) 164*17016Ssam FILE *cfp; 165*17016Ssam int *ignore; 166*17016Ssam { 167*17016Ssam FILE *uncfp = NULL; 168*17016Ssam register union cio *dp = &d; 169*17016Ssam register union cio *cp = &c; 170*17016Ssam 171*17016Ssam dp->integ = getc(cfp); 172*17016Ssam if (*ignore = (dp->integ == EOF)) 173*17016Ssam goto bad; 174*17016Ssam cp->integ = getc(cfp); 175*17016Ssam if (*ignore = (cp->integ == EOF)) 176*17016Ssam goto bad; 177*17016Ssam dp->chars.hib = cp->integ & 0377; 178*17016Ssam if ((dp->integ &= 0177777) != COMPACTED) { 179*17016Ssam if (dp->integ == PACKED) 180*17016Ssam fprintf(stderr, "%s: File is packed, use unpack.\n", 181*17016Ssam infname); 182*17016Ssam else 183*17016Ssam fprintf(stderr, "%s: Not a compacted file.\n", infname); 184*17016Ssam *ignore = 1; 185*17016Ssam goto bad; 186*17016Ssam } 187*17016Ssam if (strcmp(infname, "-") != 0) { 188*17016Ssam uncfp = fopen(fname, "w"); 189*17016Ssam if (uncfp == NULL) { 190*17016Ssam perror(fname); 191*17016Ssam goto bad; 19210922Sshannon } 193*17016Ssam (void) fchmod(fileno(uncfp), status.st_mode); 194*17016Ssam } else 195*17016Ssam uncfp = stdout; 196*17016Ssam cp->integ = getc(cfp); 197*17016Ssam if (cp->integ == EOF) 198*17016Ssam goto bad; 199*17016Ssam putc(cp->chars.lob, uncfp); 20010922Sshannon 201*17016Ssam in[NC].fp = in[EF].fp = dict[0].sp[LEFT].p = bottom = dict + 1; 202*17016Ssam bottom->count[LEFT] = bottom->count[RIGHT] = 203*17016Ssam dict[0].count[RIGHT] = 1; 204*17016Ssam dirp->next = dict[0].top[RIGHT] = bottom->top[LEFT] = 205*17016Ssam bottom->top[RIGHT] = dirq = NEW; 206*17016Ssam dirq->next = NULL; 207*17016Ssam dict[0].fath.fp = NULL; 208*17016Ssam dirq->pt = bottom->fath.fp = in[cp->integ].fp = dict; 209*17016Ssam in[cp->integ].flags = (FBIT | SEEN); 210*17016Ssam in[NC].flags = SEEN; 211*17016Ssam dict[0].fath.flags = RLEAF; 212*17016Ssam bottom->fath.flags = (LLEAF | RLEAF); 213*17016Ssam dict[0].count[LEFT] = 2; 214*17016Ssam 215*17016Ssam dict[0].sp[RIGHT].ch = cp->integ; 216*17016Ssam bottom->sp[LEFT].ch = NC; 217*17016Ssam bottom->sp[RIGHT].ch = EF; 218*17016Ssam return (uncfp); 219*17016Ssam bad: 220*17016Ssam if (uncfp && uncfp != stdout) { 221*17016Ssam perror(fname); 222*17016Ssam (void) unlink(fname); 223*17016Ssam fclose(uncfp); 22410922Sshannon } 225*17016Ssam return (NULL); 22610922Sshannon } 227