/*
** 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 */
}
syntax highlighted by Code2HTML, v. 0.9.1