endrilo.c
1#include <stdlib.h>
2#include <stdio.h>
3#include <getopt.h>
4
5static void print_octet(char, int, char);
6static void print_char(char, char, char);
7static void encode(void);
8static void decode(void);
9
10static const char *usage = "usage: endrilo [-dh]";
11static char working_char = 0;
12static char working_bit = 0;
13
14void
15print_octet(char octet, int o, char last)
16{
17 int i;
18
19 for (i = 0; i < 3; i++) {
20 if (1U & (octet >> (i % 8)))
21 working_char |= 1U << ((o * 3 + i) % 8);
22 if ((o * 3 + i) % 8 == 7 || (i == 2 && last)) {
23 fputc(working_char, stdout);
24 working_char = 0;
25 }
26 }
27}
28
29void
30print_char(char count, char zero, char last)
31{
32 int i;
33
34 for (i = 0; i < count; i++) {
35 if (!zero)
36 working_char |= 1U << working_bit;
37 if (working_bit++ == 7 || (i + 1 == count && last)) {
38 fputc(working_char, stdout);
39 working_char = 0;
40 working_bit = 0;
41 }
42 }
43}
44
45void
46encode(void)
47{
48 char input = 0;
49 char current = 0;
50 char last = 0;
51 int b, /* bit counter */
52 o, /* octet counter */
53 s; /* succession counter */
54
55 for (b = 0, o = 0, s = 0;; s++, b++) {
56 if (b == 8 || b == 0) {
57 input = fgetc(stdin);
58
59 /* last character, so print what's left */
60 if (feof(stdin)) {
61 print_octet(s, o++, 1);
62 break;
63 }
64 }
65 current = 1U & (input >> (b % 8));
66
67 if (current != last) {
68 do {
69 if (s > 7) {
70 print_octet(7, o++, 0);
71 print_octet(0, o++, 0);
72 } else {
73 print_octet(s, o++, 0);
74 }
75 s -= 7;
76 } while (s > 0);
77 last = current;
78 s = 0;
79 }
80
81 /* circulate counters */
82 if (o >= 8)
83 o %= 8;
84 if (b == 8)
85 b = 0;
86 }
87}
88
89void
90decode(void)
91{
92 char input = 0;
93 char current = 0;
94 char eof = 0;
95 int b, /* bit counter */
96 o; /* octet counter */
97
98 for (o = 0; !eof; current = 0, o++) {
99 for (b = 0; b < 3; b++) {
100 if ((o * 3 + b) % 8 == 0) {
101 input = fgetc(stdin);
102 if (feof(stdin)) {
103 eof = 1;
104 break;
105 }
106 }
107 current |= (1U & (input >> ((o * 3 + b) % 8))) << b;
108 }
109 print_char(current, o % 2 == 0, eof);
110
111 /* circulate counters */
112 if (o == 8)
113 o = 0;
114 }
115}
116
117int
118main(int argc, char *argv[])
119{
120 char c;
121 int doencode = 1;
122
123 while ((c = getopt(argc, argv, "dh")) != -1) {
124 switch (c) {
125 case 'd': doencode = 0; break;
126 case 'h': printf("%s\n", usage); exit(0); break;
127 }
128 }
129
130 if (doencode)
131 encode();
132 else
133 decode();
134}