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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
/*
** Decode seven-bit input into full binary output.
** From @(#)decode.c 1.3 5/15/85, distributed with B2.11 News.
**
** Collect runs of 12 seven-bit characters. Combine them in pairs to
** make six 13-bit characters. Extract the top bit of each pair to make
** a 13th six-bit character, and split the remaining six 12-bit
** characters to form 12 six-bit characters. Collect four six-bit
** characters and convert it to three eight-bit characters.
**
** Got that? All the remaining work in this program is to get the
** ending conditions right.
*/
#include "config.h"
#include "clibrary.h"
#include "inn/messages.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[4];
static int count;
static void
pack6(int n, int last)
{
char *q;
int i;
char b3[3];
i = 3;
if (last && (i = Buffer[n - 1]) >= 3) {
/* Do the best we can. */
warn("badly-terminated file");
i = 3;
}
b3[0] = (Buffer[0] << 2) | ((Buffer[1] >> 4) & 0x03);
b3[1] = (Buffer[1] << 4) | ((Buffer[2] >> 2) & 0x0F);
b3[2] = (Buffer[2] << 6) | ( Buffer[3] & 0x3F);
for (q = b3; --i >= 0; )
putchar(*q++);
}
static void
pack12(char *p, int n, int last)
{
char *q;
int c13;
int c;
int i;
char b13[13];
char b3[3];
for (q = b13, c13 = 0, i = 0; i < n; i += 2) {
c = *p++ * 91;
c += *p++;
c13 <<= 1;
if (c & (1 << 12))
c13 |= 1;
*q++ = (c >> 6) & 0x3F;
*q++ = c & 0x3F;
}
*q++ = (char)c13;
if (last)
q = &b13[last];
for (p = b13, n = q - p, i = count, q = &Buffer[count]; --n > 0; ) {
*q++ = *p++;
if (++i == 4) {
/* Inline expansion of pack6. */
b3[0] = (Buffer[0] << 2) | ((Buffer[1] >> 4) & 0x03);
b3[1] = (Buffer[1] << 4) | ((Buffer[2] >> 2) & 0x0F);
b3[2] = (Buffer[2] << 6) | ( Buffer[3] & 0x3F);
putchar(b3[0]);
putchar(b3[1]);
putchar(b3[2]);
i = 0;
q = Buffer;
}
}
/* The last octet. */
*q++ = *p++;
i++;
if (last || i == 4) {
pack6(i, last);
i = 0;
}
count = i;
}
int
main(void)
{
int c;
char *p;
int i;
int first;
int cnt;
char *base;
char b12[12];
char c12[12];
message_program_name = "decode";
base = p = b12;
for (i = 12, cnt = 0, first = 1; (c = getchar()) != EOF; ) {
if (c < ' ' || c >= ' ' + 91)
die("bad data");
if (i == 10 && p[-1] == ENDMARK1 && p[-2] == ENDMARK2) {
cnt = c - ' ';
i = 12;
p -= 2;
continue;
}
*p++ = c - ' ';
if (--i == 0) {
if (p == &b12[12]) {
if (!first)
pack12(c12, 12, 0);
else
first = 0;
base = p = c12;
}
else {
pack12(b12, 12, 0);
base = p = b12;
}
i = 12;
}
}
if (base == b12) {
if (!first)
pack12(c12, 12, i == 12 ? cnt : 0);
}
else
pack12(b12, 12, i == 12 ? cnt : 0);
if (i != 12)
pack12(base, 12 - i, cnt);
exit(0);
/* NOTREACHED */
}
|