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