|
|
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.