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