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