1 #ifndef lint
2 static char sccsid[] = "@(#)uncompact.c	4.6 (Berkeley) 08/25/84";
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].top[LEFT] = dict[0].top[RIGHT] = 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->top[1]->next = flist;
63 	bottom->top[1] = dirp;
64 	flist = dirq;
65 	if (strcmp(file, "-") != 0) {
66 		char *cp;
67 
68 		strcpy(fname, file);
69 		cp = rindex(fname, '.');
70 		if (cp == 0 || strcmp(cp, ".C") != 0) {
71 			fprintf(stderr,
72 			    "uncompact: %s: File must have .C suffix.\n", file);
73 			return;
74 		}
75 		*cp = '\0';
76 		cfp = fopen(file, "r");
77 		if (cfp == NULL) {
78 			fprintf(stderr, "uncompact: "), perror(file);
79 			return;
80 		}
81 		(void) fstat(fileno(cfp), &status);
82 	} else
83 		cfp = stdin;
84 	infname = file;
85 	uncfp = setup(cfp, &ignore);
86 	if (uncfp == NULL) {
87 		if (ignore)
88 			goto done;
89 		goto bad;
90 	}
91 	decompress(cfp, uncfp);
92 	fflush(uncfp);
93 	if (ferror(uncfp) || ferror(cfp)) {
94 		if (uncfp != stdout) {
95 			if (ferror(uncfp))
96 				perror(fname);
97 			else
98 				perror(infname);
99 			(void) unlink(fname);
100 		}
101 		goto bad;
102 	}
103 	if (uncfp != stdout && unlink(infname) < 0)
104 		fprintf(stderr, "uncompact: "), perror(infname);
105 done:
106 	if (uncfp != NULL && uncfp != stdout)
107 		fclose(uncfp);
108 	if (cfp != NULL)
109 		fclose(cfp);
110 	return (0);
111 bad:
112 	fprintf(stderr, "uncompact: ");
113 	if (strcmp(infname, "-") != 0)
114 		perror(infname);
115 	else
116 		fprintf(stderr,
117 	    "Unsuccessful uncompact of standard input to standard output.\n");
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 struct 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->sp[b].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->sp[b].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 	dp->integ = getc(cfp);
172 	if (*ignore = (dp->integ == EOF))
173 		goto bad;
174 	cp->integ = getc(cfp);
175 	if (*ignore = (cp->integ == EOF))
176 		goto bad;
177 	dp->chars.hib = cp->integ & 0377;
178 	if ((dp->integ &= 0177777) != COMPACTED) {
179 		if (dp->integ == PACKED)
180 			fprintf(stderr, "%s: File is packed, use unpack.\n",
181 			    infname);
182 		else
183 			fprintf(stderr, "%s: Not a compacted file.\n", infname);
184 		*ignore = 1;
185 		goto bad;
186 	}
187 	if (strcmp(infname, "-") != 0) {
188 		uncfp = fopen(fname, "w");
189 		if (uncfp == NULL) {
190 			perror(fname);
191 			goto bad;
192 		}
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 bad;
199 	putc(cp->chars.lob, uncfp);
200 
201 	in[NC].fp = in[EF].fp = dict[0].sp[LEFT].p = bottom = dict + 1;
202 	bottom->count[LEFT] = bottom->count[RIGHT] =
203 	    dict[0].count[RIGHT] = 1;
204 	dirp->next = dict[0].top[RIGHT] = bottom->top[LEFT] =
205 	    bottom->top[RIGHT] = 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].count[LEFT] = 2;
214 
215 	dict[0].sp[RIGHT].ch = cp->integ;
216 	bottom->sp[LEFT].ch = NC;
217 	bottom->sp[RIGHT].ch = EF;
218 	return (uncfp);
219 bad:
220 	if (uncfp && uncfp != stdout) {
221 		perror(fname);
222 		(void) unlink(fname);
223 		fclose(uncfp);
224 	}
225 	return (NULL);
226 }
227