|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)compact.c 4.4 (Berkeley) 8/11/83";
3: #endif
4:
5: /*
6: * Adaptive Huffman code input to output
7: *
8: * On - line algorithm
9: *
10: * Does not prepend decoding tree
11: *
12: * Written by Colin L. Mc Master (UCB) February 28, 1979
13: */
14:
15:
16: #include "compact.h"
17:
18: union cio d;
19: int bits;
20:
21:
22: main (argc, argv)
23: short argc;
24: char *argv [ ];
25: {
26: register short i, j;
27: register int m;
28: union cio c;
29: short l;
30: longint ic, n;
31: char *cp, fname [LNAME];
32:
33: dir [513] . next = NULL;
34: for (head = dir + (j = 513); j--; ) {
35: dirp = head--;
36: head -> next = dirp;
37: }
38: bottom = dirp -> pt = dict;
39: dict [0] . top [0] = dict [0] . top [1] = dirp;
40: dirq = dirp -> next;
41: in [EF] . flags = FBIT | SEEN;
42:
43: for (i = 1; ; i++) {
44: ic = oc = 0;
45: (bottom -> top [1]) -> next = flist;
46: bottom -> top [1] = dirp;
47: flist = dirq;
48: if (i >= argc) {
49: uncfp = stdin;
50: cfp = stdout;
51: }
52: else {
53: m = -1;
54: cp = fname;
55: for (l = 0; l < (LNAME - 3) && (*cp = argv [i][l]); l++)
56: if (*cp++ == '/') m = l;
57: if (l >= (LNAME - 3) || (l - m) > MAXNAMLEN - 1) {
58: fprintf (stderr, "%s: File name too long\n", argv [i]);
59: if (i == argc - 1) break;
60: continue;
61: }
62: if ((uncfp = fopen (argv [i], "r")) == NULL) {
63: perror (argv [i]);
64: if (i == argc - 1) break;
65: continue;
66: }
67: }
68:
69: fstat (fileno (uncfp), &status);
70: if ((status.st_mode & 040000) == 040000) {
71: fprintf (stderr, "%s: Can't compact a directory\n", argv [i]);
72: if (i < argc) goto closein;
73: break;
74: }
75:
76: if ((d . integ = getc (uncfp)) != EOF) {
77: ic++;
78: if ((c . integ = getc (uncfp)) != EOF) {
79: d . chars . hib = c . integ & 0377;
80: if ((d . integ &= 0177777) == COMPACTED) {
81: fprintf (stderr, "%s: Already compacted.\n", argv [i]);
82: if (i < argc) goto closein;
83: break;
84: }
85: if (d . integ == PACKED) {
86: fprintf (stderr, "%s: Already packed using program pack. Use unpack.\n", argv [i]);
87: if (i < argc) goto closein;
88: break;
89: }
90: if (i < argc) {
91: *cp++ = '.'; *cp++ = 'C'; *cp = '\0';
92: if ((cfp = fopen (fname, "w")) == NULL) {
93: perror (fname);
94: goto closein;
95: }
96: chmod (fname, status.st_mode);
97: }
98: c . integ = COMPACTED;
99: putc (c . chars . lob, cfp);
100: putc (c . chars . hib, cfp);
101: if (ferror (cfp))
102: if (i < argc) {
103: perror (fname);
104: unlink (fname);
105: goto closeboth;
106: }
107: else goto fail;
108: bits = 8;
109: oc = 2;
110: c . integ = d . integ & 0377;
111:
112: in [NC] . fp = in [EF] . fp = dict [0] . sp [0] . p = bottom = dict + 1;
113: bottom -> count [0] = bottom -> count [1] = dict [0] . count [1] = 1;
114: dirp -> next = dict [0] . top [1] = bottom -> top [0] = bottom -> top [1] = dirq = NEW;
115: dirq -> next = NULL;
116: dict [0] . fath . fp = NULL;
117: dirq -> pt = bottom -> fath . fp = in [c . integ] . fp = dict;
118: in [c . integ] . flags = (FBIT | SEEN);
119: in [NC] . flags = SEEN;
120: dict [0] . fath . flags = RLEAF;
121: bottom -> fath . flags = (LLEAF | RLEAF);
122: dict [0] . count [0] = 2;
123:
124: dict [0] . sp [1] . ch = c . integ;
125: bottom -> sp [0] . ch = NC;
126: bottom -> sp [1] . ch = EF;
127:
128: for (c . integ = ((d . integ >> 8) & 0377); c . integ != EOF; c . integ = getc (uncfp)) {
129: ic++;
130: if (in [c . integ] . flags & SEEN) encode (c . integ);
131: else {
132: encode (NC);
133: uptree (NC);
134: insert (c . integ);
135:
136: m = 0200;
137: for (j = 8; j--; m >>= 1) {
138: d . integ <<= 1;
139: if (m & c . integ) d . integ++;
140: ++bits;
141: if ((bits &= 017) == 0) {
142: putc (d . chars . hib, cfp);
143: putc (d . chars . lob, cfp);
144: oc += 2;
145: }
146: }
147: }
148: if (ferror (cfp))
149: if (i < argc) {
150: perror (fname);
151: unlink (fname);
152: goto closeboth;
153: }
154: else goto fail;
155: uptree (c . integ);
156:
157: }
158:
159: if (ferror (uncfp))
160: if (i < argc) {
161: perror (argv [i]);
162: unlink (fname);
163: goto closeboth;
164: }
165: else goto fail;
166:
167: encode (EF);
168:
169: if (bits) {
170: d . integ <<= (16 - bits);
171: oc++;
172: putc (d . chars . hib, cfp);
173: if (bits > 8) {
174: oc++;
175: putc (d . chars . lob, cfp);
176: }
177: bits = 0;
178: }
179: }
180: else oc = ic;
181: }
182:
183: if (ferror (uncfp) || ferror (cfp))
184: if (i < argc) {
185: if (ferror (cfp))
186: perror (fname);
187: else
188: perror (argv [i]);
189: if (oc > 1) {
190: unlink (fname);
191: goto closeboth;
192: }
193: goto closein;
194: }
195: else goto fail;
196: else {
197: if (oc >= ic) {
198: if (i < argc) fprintf (stderr, "%s: ", argv [i]);
199: if (i < argc) fprintf (stderr, "Not compacted. ");
200: fprintf (stderr, "Does not save bytes.\n");
201: if (i < argc) {
202: if (oc > 1) {
203: unlink (fname);
204: goto closeboth;
205: }
206: goto closein;
207: }
208: else break;
209: }
210: while ((ic - oc) > 21474) {
211: ic /= 10;
212: oc /= 10;
213: }
214: n = 100000 * (ic - oc) / ic + 5;
215: m = (n % 1000) / 10;
216: bits = m % 10 + '0';
217: c . integ = m / 10 + '0';
218: if (i < argc) fprintf (stderr, "%s: ", argv [i]);
219: fprintf (stderr, "Compression : %4ld.%c%c%%\n", n / 1000, c . chars . lob, bits);
220: }
221:
222: if (i >= argc) break;
223: unlink (argv [i]);
224: closeboth : fclose (cfp);
225: closein : fclose (uncfp);
226: if (i == argc - 1) break;
227: for (j = 256; j--; ) in [j] . flags = 0;
228: continue;
229: fail : fprintf (stderr, "Unsuccessful compact of standard input to standard output.\n");
230: break;
231: }
232: }
233:
234: encode (ch)
235: int ch;
236: {
237:
238: register struct node *pp;
239: register char j;
240: union cio c;
241: int stack [17], stp, stbits;
242:
243: c . integ = ch;
244: stack [stp = 0] = in [c . integ] . flags & FBIT;
245: stbits = 1;
246: pp = in [c . integ] . fp;
247:
248: while (pp -> fath . fp) {
249: stack [stp] <<= 1;
250: if (pp -> fath . flags & FBIT) stack [stp]++;
251: stbits++;
252: if ((stbits &= 017) == 0) stp++;
253: pp = pp -> fath . fp;
254: }
255:
256: /* pop the output stack */
257:
258: for (stp++; stp--; ) {
259: for (j = 0; j < stbits; j++) {
260: d . integ <<= 1;
261: if (stack [stp] & 01) d . integ++;
262: ++bits;
263: if ((bits &= 017) == 0) {
264: putc (d . chars . hib, cfp);
265: putc (d . chars . lob, cfp);
266: if (ferror (cfp)) return;
267: oc += 2;
268: }
269: stack [stp] >>= 1;
270: }
271: stbits = 16;
272: }
273: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.