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: }

Defined functions

compact defined in line 60; used 2 times
compress defined in line 227; used 1 times
encode defined in line 183; used 3 times
main defined in line 26; never used
setup defined in line 268; used 2 times

Defined variables

bits defined in line 19; used 11 times
c defined in line 18; used 6 times
d defined in line 17; used 6 times
fname defined in line 21; used 9 times
infname defined in line 20; used 11 times
sccsid defined in line 2; never used
ucfstatus defined in line 22; used 4 times
verbose defined in line 24; used 3 times
Last modified: 1984-08-26
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1610
Valid CSS Valid XHTML 1.0 Strict