Commit | Line | Data |
---|---|---|
524aa063 | 1 | #ifndef lint |
90b67bab | 2 | static char sccsid[] = "@(#)uncompact.c 4.8 (Berkeley) %G%"; |
524aa063 SL |
3 | #endif |
4 | ||
c3a7147a BS |
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 | */ | |
c3a7147a | 14 | #include "compact.h" |
3e76178c SL |
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 */ | |
c3a7147a | 22 | |
3e76178c | 23 | int verbose = 0; |
c3a7147a | 24 | |
3e76178c SL |
25 | main(argc, argv) |
26 | int argc; | |
27 | char *argv[]; | |
c3a7147a | 28 | { |
c3a7147a | 29 | register short j; |
c3a7147a | 30 | |
3e76178c SL |
31 | argc--, argv++; |
32 | if (argc > 0 && strcmp(*argv, "-v") == 0) { | |
33 | verbose++; | |
34 | argc--, argv++; | |
35 | } | |
36 | dir[513].next = NULL; | |
c3a7147a BS |
37 | for (head = dir + (j = 513); j--; ) { |
38 | dirp = head--; | |
3e76178c | 39 | head->next = dirp; |
c3a7147a | 40 | } |
3e76178c | 41 | bottom = dirp->pt = dict; |
7047739d | 42 | dict[0].sons[LEFT].top = dict[0].sons[RIGHT].top = dirp; |
3e76178c SL |
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 | } | |
c3a7147a | 55 | |
3e76178c SL |
56 | uncompact(file) |
57 | char *file; | |
58 | { | |
59 | int ignore; | |
60 | FILE *setup(); | |
61 | ||
7047739d SL |
62 | bottom->sons[RIGHT].top->next = flist; |
63 | bottom->sons[RIGHT].top = dirp; | |
3e76178c | 64 | flist = dirq; |
7047739d | 65 | uncfp = cfp = NULL; |
3e76178c SL |
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); | |
7047739d | 74 | goto bad; |
c3a7147a | 75 | } |
3e76178c SL |
76 | *cp = '\0'; |
77 | cfp = fopen(file, "r"); | |
78 | if (cfp == NULL) { | |
79 | fprintf(stderr, "uncompact: "), perror(file); | |
7047739d | 80 | goto bad; |
c3a7147a | 81 | } |
3e76178c SL |
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)) { | |
7047739d | 95 | fprintf(stderr, "uncompact: "); |
3e76178c SL |
96 | if (uncfp != stdout) { |
97 | if (ferror(uncfp)) | |
98 | perror(fname); | |
99 | else | |
100 | perror(infname); | |
101 | (void) unlink(fname); | |
7047739d SL |
102 | } else |
103 | fprintf(stderr, | |
104 | "Unsuccessful uncompact of standard input to standard output.\n"); | |
3e76178c SL |
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: | |
7047739d SL |
116 | if (cfp != NULL) |
117 | fclose(cfp); | |
3e76178c SL |
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; | |
90b67bab | 127 | register union cio *dp = &d; |
3e76178c | 128 | char b; |
c3a7147a | 129 | |
3e76178c SL |
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)) { | |
7047739d | 136 | dp->integ = p->sons[b].sp.ch; |
3e76178c SL |
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; | |
c3a7147a | 146 | } |
3e76178c SL |
147 | dp->integ <<= 1; |
148 | if (m & c.integ) | |
149 | dp->integ++; | |
c3a7147a | 150 | } |
3e76178c | 151 | insert(dp->integ); |
c3a7147a | 152 | } |
3e76178c SL |
153 | uptree(dp->integ); |
154 | putc(dp->chars.lob, uncfp); | |
155 | p = dict; | |
156 | } else | |
7047739d | 157 | p = p->sons[b].sp.p; |
c3a7147a | 158 | } |
3e76178c SL |
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 | ||
7047739d | 171 | *ignore = 0; |
3e76178c | 172 | dp->integ = getc(cfp); |
7047739d SL |
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; | |
3e76178c | 179 | if ((dp->integ &= 0177777) != COMPACTED) { |
7047739d | 180 | fprintf(stderr, "uncompact: "); |
3e76178c SL |
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"); | |
7047739d SL |
191 | if (uncfp == NULL) |
192 | goto bad2; | |
3e76178c SL |
193 | (void) fchmod(fileno(uncfp), status.st_mode); |
194 | } else | |
195 | uncfp = stdout; | |
196 | cp->integ = getc(cfp); | |
197 | if (cp->integ == EOF) | |
7047739d | 198 | goto bad2; |
3e76178c SL |
199 | putc(cp->chars.lob, uncfp); |
200 | ||
7047739d SL |
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; | |
3e76178c SL |
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); | |
7047739d | 213 | dict[0].sons[LEFT].count = 2; |
c3a7147a | 214 | |
7047739d SL |
215 | dict[0].sons[RIGHT].sp.ch = cp->integ; |
216 | bottom->sons[LEFT].sp.ch = NC; | |
217 | bottom->sons[RIGHT].sp.ch = EF; | |
3e76178c | 218 | return (uncfp); |
7047739d SL |
219 | bad2: |
220 | fprintf(stderr, "uncompact: "); | |
221 | perror(fname); | |
3e76178c SL |
222 | bad: |
223 | if (uncfp && uncfp != stdout) { | |
3e76178c SL |
224 | (void) unlink(fname); |
225 | fclose(uncfp); | |
c3a7147a | 226 | } |
3e76178c | 227 | return (NULL); |
c3a7147a | 228 | } |