|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.