|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)compact.c 4.7 (Berkeley) 8/25/84";
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: #include <strings.h>
15: #include "compact.h"
16:
17: union cio d;
18: union cio c;
19: int bits;
20: char *infname; /* input file's name */
21: char fname[MAXPATHLEN+1]; /* output file's name */
22: struct stat ucfstatus; /* uncompacted file status */
23:
24: int verbose = 0;
25:
26: main(argc, argv)
27: int argc;
28: char *argv[];
29: {
30: register short j;
31:
32: argc--, argv++;
33: if (argc > 0 && strcmp(*argv, "-v") == 0) {
34: verbose++;
35: argc--, argv++;
36: }
37: dir[513].next = NULL;
38: for (head = dir + (j = 513); j--; ) {
39: dirp = head--;
40: head->next = dirp;
41: }
42: bottom = dirp->pt = dict;
43: dict[0].sons[LEFT].top = dict[0].sons[RIGHT].top = dirp;
44: dirq = dirp->next;
45: in[EF].flags = FBIT | SEEN;
46: if (argc == 0)
47: exit(compact("-"));
48: for (j = 0; j < argc; j++) {
49: if (verbose && argc > 0)
50: printf("%s: ", argv[j]);
51: if (compact(argv[j]))
52: exit(1);
53: }
54: exit(0);
55: }
56:
57: /*
58: * Compact a single file ("-" implies stdin).
59: */
60: compact(file)
61: char *file;
62: {
63: int j, ignore;
64: FILE *setup();
65:
66: for (j = 256; j--; )
67: in[j].flags = 0;
68: bottom->sons[RIGHT].top->next = flist;
69: bottom->sons[RIGHT].top = dirp;
70: flist = dirq;
71: cfp = uncfp = NULL;
72: if (strcmp(file, "-") != 0) {
73: char *cp, *tp;
74:
75: /* verify .C suffix fits */
76: cp = rindex(file, '/');
77: if (cp == 0)
78: cp = file;
79: else
80: cp++;
81: tp = index(cp, '\0');
82: if (tp - cp > MAXNAMLEN || strlen(file) + 2 >= MAXPATHLEN) {
83: fprintf(stderr, "%s: File name too long\n", file);
84: goto bad;
85: }
86: uncfp = fopen(file, "r");
87: if (uncfp == NULL) {
88: fprintf(stderr, "compact: "), perror(file);
89: goto bad;
90: }
91: fstat(fileno(uncfp), &ucfstatus);
92: if ((ucfstatus.st_mode & S_IFMT) != S_IFREG) {
93: fprintf(stderr, "%s: Not a regular file.\n", file);
94: goto bad;
95: }
96: } else
97: uncfp = stdin;
98: infname = file;
99:
100: cfp = setup(uncfp, &ignore);
101: if (cfp == NULL) {
102: if (ignore)
103: goto done;
104: goto bad;
105: }
106: if (compress(uncfp, cfp)) {
107: if (cfp != stdout)
108: (void) unlink(fname);
109: goto bad2;
110: }
111: encode(EF);
112: if (bits) {
113: d.integ <<= 16 - bits;
114: putc(d.chars.hib, cfp);
115: if (bits > 8)
116: putc(d.chars.lob, cfp);
117: bits = 0;
118: }
119: fflush(cfp);
120: if (ferror(uncfp) || ferror(cfp)) {
121: if (cfp != stdout) {
122: fprintf(stderr, "compact: ");
123: if (ferror(cfp))
124: perror(fname);
125: else
126: perror(infname);
127: (void) unlink(fname);
128: }
129: goto bad;
130: }
131: if (cfp != stdout) {
132: struct stat cfstatus;
133: longint csize, ucsize;
134:
135: (void) fstat(fileno(cfp), &cfstatus);
136: csize = cfstatus.st_size;
137: ucsize = ucfstatus.st_size;
138: if (csize >= ucsize) {
139: fprintf("%s: ", infname);
140: (void) unlink(fname);
141: printf("Not compacted, does not save bytes.\n");
142: goto done;
143: }
144: if (verbose) {
145: FILE *fd;
146: longint n, m;
147:
148: while (ucsize - csize > 21474) {
149: ucsize /= 10;
150: csize /= 10;
151: }
152: n = 100000 * (ucsize - csize) / ucsize + 5;
153: m = (n % 1000) / 10;
154: bits = m % 10 + '0';
155: c.integ = m / 10 + '0';
156: printf("%ld.%c%c%% compression\n",
157: n / 1000, c.chars.lob, bits);
158: }
159: if (unlink(infname) < 0)
160: fprintf(stderr, "compact: "), perror(infname);
161: }
162: done:
163: if (cfp != NULL && cfp != stdout)
164: fclose(cfp);
165: if (uncfp != NULL)
166: fclose(uncfp);
167: return (0);
168: bad2:
169: fprintf(stderr, "compact: ");
170: if (cfp != stdout)
171: perror(infname);
172: else
173: fprintf(stderr,
174: "Unsuccessful compact of standard input to standard output.\n");
175: bad:
176: if (cfp != NULL && cfp != stdout)
177: fclose(cfp);
178: if (uncfp != NULL)
179: fclose(uncfp);
180: return (1);
181: }
182:
183: encode(ch)
184: int ch;
185: {
186: register struct node *pp;
187: int stack[17];
188: register int stbits = 1, *sp = &stack[0], rbits = bits;
189: register union cio *dp = &d;
190: union cio c;
191:
192: c.integ = ch;
193: *sp = in[ch].flags & FBIT;
194: pp = in[ch].fp;
195:
196: while (pp->fath.fp) {
197: *sp <<= 1;
198: if (pp->fath.flags & FBIT)
199: (*sp)++;
200: stbits++;
201: if ((stbits &= 017) == 0)
202: sp++;
203: pp = pp->fath.fp;
204: }
205:
206: /* pop the output stack */
207: do {
208: while (stbits-- > 0) {
209: dp->integ <<= 1;
210: if (*sp & 01)
211: dp->integ++;
212: ++rbits;
213: if ((rbits &= 017) == 0) {
214: putc(dp->chars.hib, cfp);
215: putc(dp->chars.lob, cfp);
216: if (ferror(cfp))
217: goto done;
218: }
219: *sp >>= 1;
220: }
221: stbits = 16;
222: } while (--sp >= &stack[0]);
223: done:
224: bits = rbits;
225: }
226:
227: compress(uncfp, cfp)
228: register FILE *uncfp, *cfp;
229: {
230: register union cio *dp = &d;
231: register union cio *cp = &c;
232:
233: cp->integ = (dp->integ >> 8) & 0377;
234: for (; cp->integ != EOF; cp->integ = getc(uncfp)) {
235: if ((in[cp->integ].flags & SEEN) == 0) {
236: register short j, m;
237:
238: encode(NC);
239: uptree(NC);
240: insert(cp->integ);
241:
242: m = 0200;
243: for (j = 8; j--; m >>= 1) {
244: dp->integ <<= 1;
245: if (m & cp->integ)
246: dp->integ++;
247: ++bits;
248: if ((bits &= 017) == 0) {
249: putc(dp->chars.hib, cfp);
250: putc(dp->chars.lob, cfp);
251: }
252: }
253: } else
254: encode(cp->integ);
255: if (ferror(cfp)) {
256: perror(fname);
257: return (1);
258: }
259: uptree(cp->integ);
260: }
261: if (ferror(uncfp)) {
262: perror(infname);
263: return (1);
264: }
265: return (0);
266: }
267:
268: FILE *
269: setup(uncfp, ignore)
270: FILE *uncfp;
271: int *ignore;
272: {
273: FILE *cfp = NULL;
274: register union cio *dp = &d;
275: register union cio *cp = &c;
276:
277: dp->integ = getc(uncfp);
278: if (*ignore = (dp->integ == EOF))
279: goto bad;
280: cp->integ = getc(uncfp);
281: if (*ignore = (cp->integ == EOF))
282: goto bad;
283: dp->chars.hib = cp->integ & 0377;
284: if ((dp->integ &= 0177777) == COMPACTED) {
285: fprintf(stderr, "%s: Already compacted.\n", infname);
286: *ignore = 1;
287: goto bad;
288: }
289: if (dp->integ == PACKED) {
290: fprintf(stderr,
291: "%s: Already packed using pack program, use unpack.\n",
292: infname);
293: *ignore = 1;
294: goto bad;
295: }
296: if (strcmp(infname, "-") != 0) {
297: sprintf(fname, "%s.C", infname);
298: cfp = fopen(fname, "w");
299: if (cfp == NULL)
300: goto bad2;
301: (void) fchmod(fileno(cfp), ucfstatus.st_mode);
302: } else
303: cfp = stdout;
304: cp->integ = COMPACTED;
305: putc(cp->chars.lob, cfp);
306: putc(cp->chars.hib, cfp);
307: if (ferror(cfp))
308: goto bad2;
309: bits = 8;
310: cp->integ = dp->integ & 0377;
311:
312: in[NC].fp = in[EF].fp = dict[0].sons[LEFT].sp.p = bottom = dict + 1;
313: bottom->sons[LEFT].count = bottom->sons[RIGHT].count =
314: dict[0].sons[RIGHT].count = 1;
315: dirp->next = dict[0].sons[RIGHT].top = bottom->sons[LEFT].top =
316: bottom->sons[RIGHT].top = dirq = NEW;
317: dirq->next = NULL;
318: dict[0].fath.fp = NULL;
319: dirq->pt = bottom->fath.fp = in[cp->integ].fp = dict;
320: in[cp->integ].flags = (FBIT | SEEN);
321: in[NC].flags = SEEN;
322: dict[0].fath.flags = RLEAF;
323: bottom->fath.flags = (LLEAF | RLEAF);
324: dict[0].sons[LEFT].count = 2;
325:
326: dict[0].sons[RIGHT].sp.ch = cp->integ;
327: bottom->sons[LEFT].sp.ch = NC;
328: bottom->sons[RIGHT].sp.ch = EF;
329: return (cfp);
330: bad2:
331: if (cfp && cfp != stdout) {
332: fprintf(stderr, "compact: "), perror(fname);
333: (void) unlink(fname);
334: }
335: bad:
336: if (cfp && cfp != stdout)
337: fclose(cfp);
338: return (NULL);
339: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.