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