1*10922Sshannon /*	uncompact.c	4.1	83/02/11	*/
2*10922Sshannon /*
3*10922Sshannon  *  Uncompact adaptive Huffman code input to output
4*10922Sshannon  *
5*10922Sshannon  *  On - line algorithm
6*10922Sshannon  *
7*10922Sshannon  *  Input file does not contain decoding tree
8*10922Sshannon  *
9*10922Sshannon  *  Written by Colin L. Mc Master (UCB) February 14, 1979
10*10922Sshannon  */
11*10922Sshannon 
12*10922Sshannon #include "compact.h"
13*10922Sshannon 
14*10922Sshannon 
15*10922Sshannon main (argc, argv)
16*10922Sshannon short argc;
17*10922Sshannon char *argv [ ];
18*10922Sshannon {
19*10922Sshannon 	register short i;
20*10922Sshannon 	register struct node *p;
21*10922Sshannon 	register short j;
22*10922Sshannon 	register int m;
23*10922Sshannon 	union cio c, d;
24*10922Sshannon 	char b;
25*10922Sshannon 	longint ic, n;
26*10922Sshannon 	char fname [LNAME], *cp;
27*10922Sshannon 
28*10922Sshannon 	dir [513] . next = NULL;
29*10922Sshannon 	for (head = dir + (j = 513); j--; ) {
30*10922Sshannon 		dirp = head--;
31*10922Sshannon 		head -> next = dirp;
32*10922Sshannon 	}
33*10922Sshannon 	bottom = dirp -> pt = dict;
34*10922Sshannon 	dict [0] . top [0] = dict [0] . top [1] = dirp;
35*10922Sshannon 	dirq = dirp -> next;
36*10922Sshannon 	in [EF] . flags = FBIT | SEEN;
37*10922Sshannon 
38*10922Sshannon 	for (i = 1; ; i++) {
39*10922Sshannon 		ic = oc = 0;
40*10922Sshannon 		(bottom -> top [1]) -> next = flist;
41*10922Sshannon 		bottom -> top [1] = dirp;
42*10922Sshannon 		flist = dirq;
43*10922Sshannon 		if (i >= argc) {
44*10922Sshannon 			uncfp = stdout;
45*10922Sshannon 			cfp = stdin;
46*10922Sshannon 		}
47*10922Sshannon 		else {
48*10922Sshannon 			m = -1;
49*10922Sshannon 			cp = fname;
50*10922Sshannon 			for (j = 0; j < (LNAME - 3) && (*cp = argv [i][j]); j++)
51*10922Sshannon 				if (*cp++ == '/') m = j;
52*10922Sshannon 			if (cp [-1] == 'C' && cp [-2] == '.') cp [-2] = 0;
53*10922Sshannon 			else {
54*10922Sshannon 				fprintf (stderr, "%s: File name must end with \".C\"\n", argv [i]);
55*10922Sshannon 				if (i == argc - 1) break;
56*10922Sshannon 				continue;
57*10922Sshannon 			}
58*10922Sshannon 			if (j >= (LNAME - 3) || (j - m) > 15) {
59*10922Sshannon 				fprintf (stderr, "File name too long -- %s\n", argv [i]);
60*10922Sshannon 				if (i == argc - 1) break;
61*10922Sshannon 				continue;
62*10922Sshannon 			}
63*10922Sshannon 			if ((cfp = fopen (argv [i], "r")) == NULL) {
64*10922Sshannon 				perror (argv [i]);
65*10922Sshannon 				if (i == argc - 1) break;
66*10922Sshannon 				continue;
67*10922Sshannon 			}
68*10922Sshannon 			if ((uncfp = fopen (fname, "w")) == NULL) {
69*10922Sshannon 				perror (fname);
70*10922Sshannon 				fclose (cfp);
71*10922Sshannon 				if (i == argc - 1) break;
72*10922Sshannon 				continue;
73*10922Sshannon 			}
74*10922Sshannon 			fstat (fileno (cfp), &status);
75*10922Sshannon 			chmod (fname, status.st_mode & 07777);
76*10922Sshannon 		}
77*10922Sshannon 
78*10922Sshannon 		if ((c . integ = getc (cfp)) != EOF) {
79*10922Sshannon 			if ((d . integ = getc (cfp)) != EOF) {
80*10922Sshannon 				c . chars . hib = d . integ & 0377;
81*10922Sshannon 				c . integ &= 0177777;
82*10922Sshannon 				if (c . integ != COMPACTED) goto notcompact;
83*10922Sshannon 				if ((c . integ = getc (cfp)) != EOF) {
84*10922Sshannon 					putc (c . chars . lob, uncfp);
85*10922Sshannon 					ic = 3;
86*10922Sshannon 
87*10922Sshannon 					in [NC] . fp = in [EF] . fp = dict [0] . sp [0] . p = bottom = dict + 1;
88*10922Sshannon 					bottom -> count [0] = bottom -> count [1] = dict [0] . count [1] = 1;
89*10922Sshannon 					dirp -> next = dict [0] . top [1] = bottom -> top [0] = bottom -> top [1] = dirq = NEW;
90*10922Sshannon 					dirq -> next = NULL;
91*10922Sshannon 					dict [0] . fath . fp = NULL;
92*10922Sshannon 					dirq -> pt = bottom -> fath . fp = in [c . integ] . fp = dict;
93*10922Sshannon 					in [c . integ] . flags = (FBIT | SEEN);
94*10922Sshannon 					in [NC] . flags = SEEN;
95*10922Sshannon 					dict [0] . fath . flags = RLEAF;
96*10922Sshannon 					bottom -> fath . flags = (LLEAF | RLEAF);
97*10922Sshannon 					dict [0] . count [0] = 2;
98*10922Sshannon 
99*10922Sshannon 					dict [0] . sp [1] . ch = c . integ;
100*10922Sshannon 					bottom -> sp [0] . ch = NC;
101*10922Sshannon 					bottom -> sp [1] . ch = EF;
102*10922Sshannon 
103*10922Sshannon 					p = dict;
104*10922Sshannon 					while ((c . integ = getc (cfp)) != EOF) {
105*10922Sshannon 						ic++;
106*10922Sshannon 						for (m = 0200; m; ) {
107*10922Sshannon 							b = (m & c . integ ? 1 : 0);
108*10922Sshannon 							m >>= 1;
109*10922Sshannon 							if (p -> fath . flags & (b ? RLEAF : LLEAF)) {
110*10922Sshannon 								d . integ = p -> sp [b] . ch;
111*10922Sshannon 								if (d . integ == EF) break;
112*10922Sshannon 								if (d . integ == NC) {
113*10922Sshannon 									uptree (NC);
114*10922Sshannon 									d . integ = 0;
115*10922Sshannon 									for (j = 8; j--; m >>= 1) {
116*10922Sshannon 										if (m == 0) {
117*10922Sshannon 											c . integ = getc (cfp);
118*10922Sshannon 											ic++;
119*10922Sshannon 											m = 0200;
120*10922Sshannon 										}
121*10922Sshannon 										d . integ <<= 1;
122*10922Sshannon 										if (m & c . integ) d . integ++;
123*10922Sshannon 									}
124*10922Sshannon 									insert (d . integ);
125*10922Sshannon 								}
126*10922Sshannon 								uptree (d . integ);
127*10922Sshannon 								putc (d . chars . lob, uncfp);
128*10922Sshannon 								oc++;
129*10922Sshannon 								p = dict;
130*10922Sshannon 							}
131*10922Sshannon 							else p = p -> sp [b] . p;
132*10922Sshannon 						}
133*10922Sshannon 					}
134*10922Sshannon 				}
135*10922Sshannon 			}
136*10922Sshannon 			else goto notcompact;
137*10922Sshannon 		}
138*10922Sshannon 		else {
139*10922Sshannon 			notcompact : if (i < argc) {
140*10922Sshannon 					     fprintf (stderr, "%s: ", argv [i]);
141*10922Sshannon 					     unlink (fname);
142*10922Sshannon 				     }
143*10922Sshannon 				     if (c . integ == PACKED) fprintf (stderr, "File is packed. Use unpack.\n");
144*10922Sshannon 				     else fprintf (stderr, "Not a compacted file.\n");
145*10922Sshannon 				     if (i >= argc) break;
146*10922Sshannon 				     goto closeboth;
147*10922Sshannon 		}
148*10922Sshannon 
149*10922Sshannon 		if (ferror (uncfp) || ferror (cfp))
150*10922Sshannon 			if (i < argc) {
151*10922Sshannon 				if (ferror (uncfp))
152*10922Sshannon 					perror (fname);
153*10922Sshannon 				else
154*10922Sshannon 					perror (argv [i]);
155*10922Sshannon 				fprintf (stderr, "Unable to uncompact %s\n", argv [i]);
156*10922Sshannon 				unlink (fname);
157*10922Sshannon 				goto closeboth;
158*10922Sshannon 			}
159*10922Sshannon 			    if (i >= argc) break;
160*10922Sshannon 			    fprintf (stderr, "%s uncompacted to %s\n", argv [i], fname);
161*10922Sshannon 			    unlink (argv [i]);
162*10922Sshannon 		closeboth : fclose (cfp);
163*10922Sshannon 		closein   : fclose (uncfp);
164*10922Sshannon 			    if (i == argc - 1) break;
165*10922Sshannon 			    for (j = 256; j--; ) in [j] . flags = 0;
166*10922Sshannon 			    continue;
167*10922Sshannon 		fail 	  : fprintf (stderr, "Unsuccessful uncompact of standard input to standard output.\n");
168*10922Sshannon 		            break;
169*10922Sshannon 	}
170*10922Sshannon }
171