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

dumpcode defined in line 112; used 2 times
encode defined in line 73; used 2 times
flushout defined in line 104; used 1 times
  • in line 66
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

ENDMARK1 defined in line 46; used 1 times
ENDMARK2 defined in line 47; used 1 times
Last modified: 1986-01-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1033
Valid CSS Valid XHTML 1.0 Strict