chiark / gitweb /
more manpage, remove -h option
[innduct.git] / frontends / decode.c
1 /*
2 **  Decode seven-bit input into full binary output.
3 **  From @(#)decode.c 1.3 5/15/85, distributed with B2.11 News.
4 **
5 **  Collect runs of 12 seven-bit characters.  Combine them in pairs to
6 **  make six 13-bit characters.  Extract the top bit of each pair to make
7 **  a 13th six-bit character, and split the remaining six 12-bit
8 **  characters to form 12 six-bit characters.  Collect four six-bit
9 **  characters and convert it to three eight-bit characters.
10 **
11 **  Got that?  All the remaining work in this program is to get the
12 **  ending conditions right.
13 */
14
15 #include "config.h"
16 #include "clibrary.h"
17
18 #include "inn/messages.h"
19
20
21 /*
22 **  These characters can't appear in normal output, so we use them to
23 **  mark that the data that follows is the terminator.  The character
24 **  immediately following this pair is the length of the terminator (which
25 **  otherwise might be indeterminable)
26 */
27 #define ENDMARK1        ((90 * 91 + 90) / 91)
28 #define ENDMARK2        ((90 * 91 + 90) % 91)
29
30
31 static char     Buffer[4];
32 static int      count;
33
34
35 static void
36 pack6(int n, int last)
37 {
38     char        *q;
39     int i;
40     char                b3[3];
41
42     i = 3;
43     if (last && (i = Buffer[n - 1]) >= 3) {
44         /* Do the best we can. */
45         warn("badly-terminated file");
46         i = 3;
47     }
48
49     b3[0] = (Buffer[0] << 2) | ((Buffer[1] >> 4) & 0x03);
50     b3[1] = (Buffer[1] << 4) | ((Buffer[2] >> 2) & 0x0F);
51     b3[2] = (Buffer[2] << 6) | ( Buffer[3]       & 0x3F);
52     for (q = b3; --i >= 0; )
53         putchar(*q++);
54 }
55
56
57 static void
58 pack12(char *p, int n, int last)
59 {
60     char        *q;
61     int c13;
62     int c;
63     int i;
64     char                b13[13];
65     char                b3[3];
66
67     for (q = b13, c13 = 0, i = 0; i < n; i += 2) {
68         c = *p++ * 91;
69         c += *p++;
70         c13 <<= 1;
71         if (c & (1 << 12))
72             c13 |= 1;
73         *q++ = (c >> 6) & 0x3F;
74         *q++ = c & 0x3F;
75     }
76     *q++ = (char)c13;
77     if (last)
78         q = &b13[last];
79
80     for (p = b13, n = q - p, i = count, q = &Buffer[count]; --n > 0; ) {
81         *q++ = *p++;
82         if (++i == 4) {
83             /* Inline expansion of pack6. */
84             b3[0] = (Buffer[0] << 2) | ((Buffer[1] >> 4) & 0x03);
85             b3[1] = (Buffer[1] << 4) | ((Buffer[2] >> 2) & 0x0F);
86             b3[2] = (Buffer[2] << 6) | ( Buffer[3]       & 0x3F);
87             putchar(b3[0]);
88             putchar(b3[1]);
89             putchar(b3[2]);
90             i = 0;
91             q = Buffer;
92         }
93     }
94
95     /* The last octet. */
96     *q++ = *p++;
97     i++;
98
99     if (last || i == 4) {
100         pack6(i, last);
101         i = 0;
102     }
103
104     count = i;
105 }
106
107
108 int
109 main(void)
110 {
111     int c;
112     char        *p;
113     int i;
114     int first;
115     int cnt;
116     char                *base;
117     char                b12[12];
118     char                c12[12];
119
120     message_program_name = "decode";
121
122     base = p = b12;
123     for (i = 12, cnt = 0, first = 1; (c = getchar()) != EOF; ) {
124         if (c < ' ' || c >= ' ' + 91)
125             die("bad data");
126         if (i == 10 && p[-1] == ENDMARK1 && p[-2] == ENDMARK2) {
127             cnt = c - ' ';
128             i = 12;
129             p -= 2;
130             continue;
131         }
132         *p++ = c - ' ';
133         if (--i == 0) {
134             if (p == &b12[12]) {
135                 if (!first)
136                     pack12(c12, 12, 0);
137                 else
138                     first = 0;
139                 base = p = c12;
140             }
141             else {
142                 pack12(b12, 12, 0);
143                 base = p = b12;
144             }
145             i = 12;
146         }
147     }
148
149     if (base == b12) {
150         if (!first)
151             pack12(c12, 12, i == 12 ? cnt : 0);
152     }
153     else
154         pack12(b12, 12, i == 12 ? cnt : 0);
155
156     if (i != 12)
157         pack12(base, 12 - i, cnt);
158
159     exit(0);
160     /* NOTREACHED */
161 }