File: encode.c

package info (click to toggle)
inn2 2.5.4-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 11,720 kB
  • ctags: 8,983
  • sloc: ansic: 92,499; sh: 13,509; perl: 12,921; makefile: 2,985; yacc: 842; python: 342; lex: 255
file content (116 lines) | stat: -rw-r--r-- 2,514 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*  $Id: encode.c 6119 2003-01-13 07:59:39Z rra $
**
**  Produce a seven-bit printable encoding of stdin on stdout.
**  From @(#)encode.c 1.3 5/15/85, distributed with B2.11 News.
**
**  The encoding uses characters from 0x20 (' ') through 0x7A ('z').
**  (That fits nicely into the UUCP 'f' protocol by Piet Beertema.) First,
**  expand three eight-bit charcters into four six-bit ones.  Collect
**  until we have 13, and spread the last one over the first 12, so that
**  we have 12 6.5-bit characters.  Since there are very few half-bit
**  machines, collect them into pairs, making six 13-bit characters.  We
**  can do this as A * 91 + B where A and B are less then 91 after we add
**  0x20 to make it printable.
**
**  And if you thought that was unclear, then we won't even get into the
**  terminating conditions!
*/

#include "config.h"
#include "clibrary.h"


/*
**  These characters can't appear in normal output, so we use them to
**  mark that the data that follows is the terminator.  The character
**  immediately following this pair is the length of the terminator (which
**  otherwise might be indeterminable)
*/
#define ENDMARK1	((90 * 91 + 90) / 91 + ' ')
#define ENDMARK2	((90 * 91 + 90) % 91 + ' ')

static char	Buffer[13];
static int	Count;


static void
dumpcode(char *p, int n)
{
    int	last;
    int	c;

    if (n == 13) {
	n--;
	last = p[12];
    }
    else if (n & 1)
	last = 1 << (6 - 1);
    else
	last = 0;

    for (; n > 0; n -= 2) {
	c = *p++ << 6;
	c |= *p++;
	if (last & (1 << (6 - 1)))
	    c |= (1 << 12);
	last <<= 1;

	putchar((c / 91) + ' ');
	putchar((c % 91) + ' ');
    }
}

static void
flushout(void)
{
    putchar(ENDMARK1);
    putchar(ENDMARK2);
    putchar(Count + ' ');
    dumpcode(Buffer, Count);
}


static void
encode(char *dest, int n)
{
    char	*p;
    int	i;
    int	j;
    char		b4[4];

    b4[0] = (dest[0] >> 2) & 0x3F;
    b4[1] = ((dest[0] & 0x03) << 4) | ((dest[1] >> 4) & 0x0F);
    b4[2] = ((dest[1] & 0x0F) << 2) | ((dest[2] >> 6) & 0x03);
    b4[3] = (char)(n == 3 ? dest[2] & 0x3F : n);

    for (p = b4, i = Count, dest = &Buffer[i], j = 4; --j >= 0; i++) {
	if (i == 13) {
	    dumpcode(Buffer, 13);
	    dest = Buffer;
	    i = 0;
	}
	*dest++ = *p++;
    }
    Count = i;
}


int
main(void)
{
    char	*p;
    int	c;
    char		b3[3];

    for (p = b3; (c = getchar()) != EOF; ) {
	*p++ = (char)c;
	if (p == &b3[3]) {
	    encode(b3, 3);
	    p = b3;
	}
    }
    encode(b3, (int)(p - b3));
    flushout();
    exit(0);
    /* NOTREACHED */
}