Annotation of 43BSD/contrib/news/src/encode.c, revision 1.1.1.1

1.1       root        1: #include <stdio.h>
                      2: 
                      3: #ifdef SCCSID
                      4: static char    *SccsId = "@(#)encode.c 1.3     5/15/85";
                      5: #endif /* SCCSID */
                      6: 
                      7: /*
                      8:  * Produce a 7 bit printable encoding of stdin on stdout.
                      9:  *
                     10:  * Encoding uses acsii chars from ' ' .. 'z'
                     11:  * (040 .. 0172) (0x20 - 0x7a) inclusive
                     12:  *
                     13:  * Method is to expand 3 chars -> 4 6 bit ones.
                     14:  * Then collect 13 6 bit chars, and spread the 13th over
                     15:  * the preceding 12, so that each of the 12 chars is now
                     16:  * 6.5 bits.  These 2 6.5 bit chars are a little hard
                     17:  * to represent on most common machines (one of these days
                     18:  * sane hosts will have 1/2 bits just for this program)
                     19:  * so we take a pair of them, and represent that in 13 bits.
                     20:  * 13 bits (max value 8191) can be represented as
                     21:  *     A * 91 + B
                     22:  * where A < 91, B < 91  (91^2 == 8281, so it fits!)
                     23:  *
                     24:  * Each of A and B is encoded as a character by adding 32
                     25:  * to make it printable (ie: 0x20).
                     26:  *
                     27:  * The termination conditions are foul beyond belief.  Don't
                     28:  * monkey with them!
                     29:  *
                     30:  * If you think its a fluke that 040 .. 0171 just happen to
                     31:  * be the chars that Piet Beertema's uucp 'f' protocol transmits
                     32:  * as single bytes, you're insane.  0172 chars are produced
                     33:  * with lower frequency than any other (given random data)
                     34:  * so the doubling that occurs with that we will just suffer.
                     35:  * (A newer 'f' proto, sometime, will probably not use 0172)
                     36:  */
                     37: 
                     38: /*
                     39:  * the following pair of characters cannot legally occur
                     40:  * in normal output (since 90*91 + 90 == 8280, which > 2^13)
                     41:  * so we use them to indicate that the data that follows is the
                     42:  * terminator.  The character immediately following this
                     43:  * pair is the length of the (expanded) terminator (which
                     44:  * otherwise might be indeterminable)
                     45:  */
                     46: #define        ENDMARK1        ((90*91 + 90) / 91 + ' ')
                     47: #define        ENDMARK2        ((90*91 + 90) % 91 + ' ')
                     48: 
                     49: main()
                     50: {
                     51:        register char *p;
                     52:        register char *e;
                     53:        register c;
                     54:        char b3[3];
                     55: 
                     56:        p = b3;
                     57:        e = b3 + 3;
                     58:        while ((c = getchar()) != EOF) {
                     59:                *p++ = c;
                     60:                if (p == e) {
                     61:                        encode(b3, 3);
                     62:                        p = b3;
                     63:                }
                     64:        }
                     65:        encode(b3, p - b3);
                     66:        flushout();
                     67:        exit(0);
                     68: }
                     69: 
                     70: static char b13[13];
                     71: static int cnt = 0;
                     72: 
                     73: encode(c, n)
                     74:        register char *c;
                     75:        int n;
                     76: {
                     77:        register char *p;
                     78:        register i = cnt;
                     79:        register j;
                     80:        char b4[4];
                     81: 
                     82:        p = b4;
                     83: 
                     84:        p[0] = (c[0] >> 2) & 0x3f;
                     85:        p[1] = ((c[0] & 0x3) << 4) | ((c[1] >> 4) & 0xf);
                     86:        p[2] = ((c[1] & 0xF) << 2) | ((c[2] >> 6) & 0x3);
                     87:        if (n == 3)
                     88:                p[3] = c[2] & 0x3f;
                     89:        else
                     90:                p[3] = n;
                     91: 
                     92:        c = &b13[i];
                     93:        for (j = 4; --j >= 0; i++) {
                     94:                if (i == 13) {
                     95:                        dumpcode(b13, 13);
                     96:                        c = b13;
                     97:                        i = 0;
                     98:                }
                     99:                *c++ = *p++;
                    100:        }
                    101:        cnt = i;
                    102: }
                    103: 
                    104: flushout()
                    105: {
                    106:        putchar(ENDMARK1);
                    107:        putchar(ENDMARK2);
                    108:        putchar(cnt + ' ');
                    109:        dumpcode(b13, cnt);
                    110: }
                    111: 
                    112: dumpcode(p, n)
                    113:        register char *p;
                    114:        register int n;
                    115: {
                    116:        register last;
                    117:        register c;
                    118: 
                    119:        if (n == 13)
                    120:                n--, last = p[12];
                    121:        else if (n & 1)
                    122:                last = (1 << (6-1));
                    123:        else
                    124:                last = 0;
                    125: 
                    126:        for ( ; n > 0; n -= 2) {
                    127:                c = *p++ << 6;
                    128:                c |= *p++;
                    129:                if (last & (1 << (6-1)))
                    130:                        c |= (1 << 12);
                    131:                last <<= 1;
                    132: 
                    133:                /*
                    134:                 * note: 91^2 > 2^13, 90^2 < 2^13, (91 + ' ') is printable
                    135:                 */
                    136: 
                    137:                /* oh for a compiler that would only do one division... */
                    138:                putchar((c / 91) + ' ');
                    139:                putchar((c % 91) + ' ');
                    140:        }
                    141: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.