Annotation of 43BSD/contrib/news/src/encode.c, revision 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.