date and time created 83/02/11 14:56:50 by shannon
authorBill Shannon <shannon@ucbvax.Berkeley.EDU>
Sat, 12 Feb 1983 06:56:50 +0000 (22:56 -0800)
committerBill Shannon <shannon@ucbvax.Berkeley.EDU>
Sat, 12 Feb 1983 06:56:50 +0000 (22:56 -0800)
SCCS-vsn: old/compact/compact/compact.c 4.1

usr/src/old/compact/compact/compact.c [new file with mode: 0644]

diff --git a/usr/src/old/compact/compact/compact.c b/usr/src/old/compact/compact/compact.c
new file mode 100644 (file)
index 0000000..b52eae1
--- /dev/null
@@ -0,0 +1,270 @@
+/*     compact.c       4.1     83/02/11        */
+/*
+ *  Adaptive Huffman code input to output
+ *
+ *  On - line algorithm
+ *
+ *  Does not prepend decoding tree
+ *
+ *  Written by Colin L. Mc Master (UCB) February 28, 1979
+ */
+
+
+#include "compact.h"
+
+union cio d;
+int bits;
+
+
+main (argc, argv)
+short argc;
+char *argv [ ];
+{
+       register short i, j;
+       register int m;
+       union cio c;
+       short l;
+       longint ic, n;
+       char *cp, fname [LNAME];
+
+       dir [513] . next = NULL;
+       for (head = dir + (j = 513); j--; ) {
+               dirp = head--;
+               head -> next = dirp;
+       }
+       bottom = dirp -> pt = dict;
+       dict [0] . top [0] = dict [0] . top [1] = dirp;
+       dirq = dirp -> next;
+       in [EF] . flags = FBIT | SEEN;
+
+       for (i = 1; ; i++) {
+               ic = oc =  0;
+               (bottom -> top [1]) -> next = flist;
+               bottom -> top [1] = dirp;
+               flist = dirq;
+               if (i >= argc) {
+                       uncfp = stdin;
+                       cfp = stdout;
+               }
+               else {
+                       m = -1;
+                       cp = fname;
+                       for (l = 0; l < (LNAME - 3) && (*cp = argv [i][l]); l++)
+                               if (*cp++ == '/') m = l;
+                       if (l >= (LNAME - 3) || (l - m) > 13) {
+                               fprintf (stderr, "%s: File name too long\n", argv [i]);
+                               if (i == argc - 1) break;
+                               continue;
+                       }
+                       if ((uncfp = fopen (argv [i], "r")) == NULL) {
+                               perror (argv [i]);
+                               if (i == argc - 1) break;
+                               continue;
+                       }
+               }
+
+               fstat (fileno (uncfp), &status);
+               if ((status.st_mode & 040000) == 040000) {
+                       fprintf (stderr, "%s: Can't compact a directory\n", argv [i]);
+                       if (i < argc) goto closein;
+                       break;
+               }
+
+               if ((d . integ = getc (uncfp)) != EOF) {
+                       ic++;
+                       if ((c . integ = getc (uncfp)) != EOF) {
+                               d . chars . hib = c . integ & 0377;
+                               if ((d . integ &= 0177777) == COMPACTED) {
+                                       fprintf (stderr, "%s: Already compacted.\n", argv [i]);
+                                       if (i < argc) goto closein;
+                                       break;
+                               }
+                               if (d . integ == PACKED) {
+                                       fprintf (stderr, "%s: Already packed using program pack.  Use unpack.\n", argv [i]);
+                                       if (i < argc) goto closein;
+                                       break;
+                               }
+                               if (i < argc) {
+                                       *cp++ = '.'; *cp++ = 'C'; *cp = '\0';
+                                       if ((cfp = fopen (fname, "w")) == NULL) {
+                                               perror (fname);
+                                               goto closein;
+                                       }
+                                       chmod (fname, status.st_mode);
+                               }
+                               c . integ = COMPACTED;
+                               putc (c . chars . lob, cfp);
+                               putc (c . chars . hib, cfp);
+                               if (ferror (cfp))
+                                       if (i < argc) {
+                                               perror (fname);
+                                               unlink (fname);
+                                               goto closeboth;
+                                       }
+                                       else goto fail;
+                               bits = 8;
+                               oc = 2;
+                               c . integ = d . integ & 0377;
+       
+                               in [NC] . fp = in [EF] . fp = dict [0] . sp [0] . p = bottom = dict + 1;
+                               bottom -> count [0] = bottom -> count [1] = dict [0] . count [1] = 1;
+                               dirp -> next = dict [0] . top [1] = bottom -> top [0] = bottom -> top [1] = dirq = NEW;
+                               dirq -> next = NULL;
+                               dict [0] . fath . fp = NULL;
+                               dirq -> pt = bottom -> fath . fp = in [c . integ] . fp = dict;
+                               in [c . integ] . flags = (FBIT | SEEN);
+                               in [NC] . flags = SEEN;
+                               dict [0] . fath . flags = RLEAF;
+                               bottom -> fath . flags = (LLEAF | RLEAF);
+                               dict [0] . count [0] = 2;
+       
+                               dict [0] . sp [1] . ch = c . integ;
+                               bottom -> sp [0] . ch = NC;
+                               bottom -> sp [1] . ch = EF;
+       
+                               for (c . integ = ((d . integ >> 8) & 0377); c . integ != EOF; c . integ = getc (uncfp)) {
+                                       ic++;
+                                       if (in [c . integ] . flags & SEEN) encode (c . integ);
+                                       else {
+                                               encode (NC);
+                                               uptree (NC);
+                                               insert (c . integ);
+       
+                                               m = 0200;
+                                               for (j = 8; j--; m >>= 1) {
+                                                       d . integ <<= 1;
+                                                       if (m & c . integ) d . integ++;
+                                                       ++bits;
+                                                       if ((bits &= 017) == 0) {
+                                                               putc (d . chars . hib, cfp);
+                                                               putc (d . chars . lob, cfp);
+                                                               oc += 2;
+                                                       }
+                                               }
+                                       }
+                                       if (ferror (cfp))
+                                               if (i < argc) {
+                                                       perror (fname);
+                                                       unlink (fname);
+                                                       goto closeboth;
+                                               }
+                                               else goto fail;
+                                       uptree (c . integ);
+       
+                               }
+
+                               if (ferror (uncfp))
+                                       if (i < argc) {
+                                               perror (argv [i]);
+                                               unlink (fname);
+                                               goto closeboth;
+                                       }
+                                       else goto fail;
+       
+                               encode (EF);
+       
+                               if (bits) {
+                                       d . integ <<= (16 - bits);
+                                       oc++;
+                                       putc (d . chars . hib, cfp);
+                                       if (bits > 8) {
+                                               oc++;
+                                               putc (d . chars . lob, cfp);
+                                       }
+                                       bits = 0;
+                               }
+                       }
+                       else oc = ic;
+               }
+
+               if (ferror (uncfp) || ferror (cfp))
+                       if (i < argc) {
+                               if (ferror (cfp))
+                                       perror (fname);
+                               else
+                                       perror (argv [i]);
+                               if (oc > 1) {
+                                       unlink (fname);
+                                       goto closeboth;
+                               }
+                               goto closein;
+                       }
+                       else goto fail;
+               else {
+                       if (oc >= ic) {
+                               if (i < argc) fprintf (stderr, "%s: ", argv [i]);
+                               if (i < argc) fprintf (stderr, "Not compacted.  ");
+                               fprintf (stderr, "Does not save bytes.\n");
+                               if (i < argc) {
+                                       if (oc > 1) {
+                                               unlink (fname);
+                                               goto closeboth;
+                                       }
+                                       goto closein;
+                               }
+                               else break;
+                       }
+                       while ((ic - oc) > 21474) {
+                               ic /= 10;
+                               oc /= 10;
+                       }
+                       n = 100000 * (ic - oc) / ic + 5;
+                       m = (n % 1000) / 10;
+                       bits = m % 10 + '0';
+                       c . integ = m / 10 + '0';
+                       if (i < argc) fprintf (stderr, "%s:  ", argv [i]);
+                       fprintf (stderr, "Compression : %4ld.%c%c%%\n", n / 1000, c . chars . lob, bits);
+               }
+
+                           if (i >= argc) break;
+                           unlink (argv [i]);
+               closeboth : fclose (cfp);
+               closein   : fclose (uncfp);
+                           if (i == argc - 1) break;
+                           for (j = 256; j--; ) in [j] . flags = 0;
+                           continue;
+               fail      : fprintf (stderr, "Unsuccessful compact of standard input to standard output.\n");
+                           break;
+       }
+}
+
+encode (ch)
+int ch;
+{
+
+       register struct node *pp;
+       register char j;
+       union cio c;
+       int stack [17], stp, stbits;
+
+       c . integ = ch;
+       stack [stp = 0] = in [c . integ] . flags & FBIT;
+       stbits = 1;
+       pp = in [c . integ] . fp;
+
+       while (pp -> fath . fp) {
+               stack [stp] <<= 1;
+               if (pp -> fath . flags & FBIT) stack [stp]++;
+               stbits++;
+               if ((stbits &= 017) == 0) stp++;
+               pp = pp ->  fath . fp;
+       }
+
+       /* pop the output stack */
+
+       for (stp++; stp--; ) {
+               for (j = 0; j < stbits; j++) {
+                       d . integ <<= 1;
+                       if (stack [stp] & 01) d . integ++;
+                       ++bits;
+                       if ((bits &= 017) == 0) {
+                               putc (d . chars . hib, cfp);
+                               putc (d . chars . lob, cfp);
+                               if (ferror (cfp)) return;
+                               oc += 2;
+                       }
+                       stack [stp] >>= 1;
+               }
+               stbits = 16;
+       }
+}