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: }
Defined functions
main
defined in line
49;
never used
Defined variables
SccsId
defined in line
4;
never used
b13
defined in line
70; used 4 times
cnt
defined in line
71; used 4 times
Defined macros