chiark / gitweb /
1 /*  \$Id: encode.c 6119 2003-01-13 07:59:39Z rra \$
2 **
3 **  Produce a seven-bit printable encoding of stdin on stdout.
4 **  From @(#)encode.c 1.3 5/15/85, distributed with B2.11 News.
5 **
6 **  The encoding uses characters from 0x20 (' ') through 0x7A ('z').
7 **  (That fits nicely into the UUCP 'f' protocol by Piet Beertema.) First,
8 **  expand three eight-bit charcters into four six-bit ones.  Collect
9 **  until we have 13, and spread the last one over the first 12, so that
10 **  we have 12 6.5-bit characters.  Since there are very few half-bit
11 **  machines, collect them into pairs, making six 13-bit characters.  We
12 **  can do this as A * 91 + B where A and B are less then 91 after we add
13 **  0x20 to make it printable.
14 **
15 **  And if you thought that was unclear, then we won't even get into the
16 **  terminating conditions!
17 */
19 #include "config.h"
20 #include "clibrary.h"
23 /*
24 **  These characters can't appear in normal output, so we use them to
25 **  mark that the data that follows is the terminator.  The character
26 **  immediately following this pair is the length of the terminator (which
27 **  otherwise might be indeterminable)
28 */
29 #define ENDMARK1        ((90 * 91 + 90) / 91 + ' ')
30 #define ENDMARK2        ((90 * 91 + 90) % 91 + ' ')
32 static char     Buffer;
33 static int      Count;
36 static void
37 dumpcode(char *p, int n)
38 {
39     int last;
40     int c;
42     if (n == 13) {
43         n--;
44         last = p;
45     }
46     else if (n & 1)
47         last = 1 << (6 - 1);
48     else
49         last = 0;
51     for (; n > 0; n -= 2) {
52         c = *p++ << 6;
53         c |= *p++;
54         if (last & (1 << (6 - 1)))
55             c |= (1 << 12);
56         last <<= 1;
58         putchar((c / 91) + ' ');
59         putchar((c % 91) + ' ');
60     }
61 }
63 static void
64 flushout(void)
65 {
66     putchar(ENDMARK1);
67     putchar(ENDMARK2);
68     putchar(Count + ' ');
69     dumpcode(Buffer, Count);
70 }
73 static void
74 encode(char *dest, int n)
75 {
76     char        *p;
77     int i;
78     int j;
79     char                b4;
81     b4 = (dest >> 2) & 0x3F;
82     b4 = ((dest & 0x03) << 4) | ((dest >> 4) & 0x0F);
83     b4 = ((dest & 0x0F) << 2) | ((dest >> 6) & 0x03);
84     b4 = (char)(n == 3 ? dest & 0x3F : n);
86     for (p = b4, i = Count, dest = &Buffer[i], j = 4; --j >= 0; i++) {
87         if (i == 13) {
88             dumpcode(Buffer, 13);
89             dest = Buffer;
90             i = 0;
91         }
92         *dest++ = *p++;
93     }
94     Count = i;
95 }
98 int
99 main(void)
100 {
101     char        *p;
102     int c;
103     char                b3;
105     for (p = b3; (c = getchar()) != EOF; ) {
106         *p++ = (char)c;
107         if (p == &b3) {
108             encode(b3, 3);
109             p = b3;
110         }
111     }
112     encode(b3, (int)(p - b3));
113     flushout();
114     exit(0);
115     /* NOTREACHED */
116 }