commit 54aaca2d308e8b1f76356abb30bac35907f5de90
parent b85fe016df137f5a661738d397167e6c6400afbc
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Thu, 16 Feb 2023 09:05:57 +0000
morse: Add decoder
Diffstat:
M | src/morse.c | | | 277 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
1 file changed, 197 insertions(+), 80 deletions(-)
diff --git a/src/morse.c b/src/morse.c
@@ -1,5 +1,111 @@
#include <stdio.h>
#include <ctype.h>
+#include <stdlib.h>
+
+#include <stdio.h>
+
+enum
+{
+ START,
+ BAD,
+ TTTT,
+ TTTE,
+ EETT,
+ ETET,
+ EETTE,
+ TTEET,
+ TETET,
+ ETEET,
+ ETTET,
+ EEETE,
+ EEETEE,
+};
+
+struct node
+{
+ unsigned char seq, dit, dah;
+} const nodes[] =
+{
+ [START] = {0, 'E', 'T'},
+ [BAD] = {0, BAD, BAD},
+
+ [TETET] = {0, ';', '!'},
+ [TTEET] = {0, BAD, ','},
+ [TTTE] = {0, '8', BAD},
+ [TTTT] = {0, '9', '0'},
+ [EEETE] = {0, EEETEE, BAD},
+ [EEETEE] = {0, BAD, '$'},
+ [EETT] = {0, EETTE, '2'},
+ [EETTE] = {0, '?', '_'},
+ [ETEET] = {0, '"', BAD},
+ [ETET] = {0, '+', BAD},
+ [ETTET] = {0, '@', BAD},
+
+ ['$'] = {0b10110111, BAD, BAD},
+ ['!'] = {0b1001010, BAD, BAD},
+ [','] = {0b1001100, BAD, BAD},
+ [')'] = {0b1010010, BAD, BAD},
+ ['_'] = {0b1010011, BAD, BAD},
+ ['.'] = {0b1010101, BAD, BAD},
+ ['='] = {0b101110, BAD, BAD},
+ ['-'] = {0b1011110, BAD, BAD},
+ ['\''] = {0b1100001, BAD, BAD},
+ ['('] = {0b110010, BAD, ')'},
+ ['@'] = {0b1101001, BAD, BAD},
+ [';'] = {0b1101010, BAD, BAD},
+ ['+'] = {0b110101, BAD, '.'},
+ ['"'] = {0b1101101, BAD, BAD},
+ ['/'] = {0b110110, BAD, BAD},
+ ['?'] = {0b1110011, BAD, BAD},
+ [':'] = {0b1111000, BAD, BAD},
+ ['&'] = {0b111101, BAD, BAD},
+ ['0'] = {0b100000, BAD, BAD},
+
+ ['1'] = {0b100001, '\'', BAD},
+ ['2'] = {0b100011, BAD, BAD},
+ ['3'] = {0b100111, BAD, BAD},
+ ['4'] = {0b101111, BAD, BAD},
+ ['5'] = {0b111111, BAD, BAD},
+ ['6'] = {0b111110, BAD, '-'},
+ ['7'] = {0b111100, BAD, BAD},
+ ['8'] = {0b111000, ':', BAD},
+ ['9'] = {0b110000, BAD, BAD},
+
+ ['A'] = {0b101, 'R', 'W'},
+ ['B'] = {0b11110, '6', '='},
+ ['C'] = {0b11010, BAD, TETET},
+ ['D'] = {0b1110, 'B', 'X'},
+ ['E'] = {0b11, 'I', 'A'},
+ ['F'] = {0b11011, BAD, BAD},
+ ['G'] = {0b1100, 'Z', 'Q'},
+ ['H'] = {0b11111, '5', '4'},
+ ['I'] = {0b111, 'S', 'U'},
+ ['J'] = {0b10001, BAD, '1'},
+ ['K'] = {0b1010, 'C', 'Y'},
+ ['L'] = {0b11101, '&', ETEET},
+ ['M'] = {0b100, 'G', 'O'},
+ ['N'] = {0b110, 'D', 'K'},
+ ['O'] = {0b1000, TTTE, TTTT},
+ ['P'] = {0b11001, BAD, ETTET},
+ ['Q'] = {0b10100, BAD, BAD},
+ ['R'] = {0b1101, 'L', ETET},
+ ['S'] = {0b1111, 'H', 'V'},
+ ['T'] = {0b10, 'N', 'M'},
+ ['U'] = {0b1011, 'F', EETT},
+ ['V'] = {0b10111, EEETE, '3'},
+ ['W'] = {0b1001, 'P', 'J'},
+ ['X'] = {0b10110, '/', BAD},
+ ['Y'] = {0b10010, '(', BAD},
+ ['Z'] = {0b11100, '7', TTEET},
+
+// [1] = 0b101010,
+// [2] = 0b101010,
+// [3] = 0b1010111,
+// [4] = 0b1010111,
+// [6] = 0b110111,
+};
+
+static char need_space;
void put_morse_char(unsigned dit)
{
@@ -8,113 +114,124 @@ void put_morse_char(unsigned dit)
void put_morse_seq(unsigned seq)
{
+ if (need_space)
+ putchar(' ');
while (seq > 1)
{
put_morse_char(seq & 1);
seq >>= 1;
}
- putchar(' ');
+ need_space = 1;
}
-unsigned char seqs[] =
-{
- ['1'] = 0b100001,
- ['2'] = 0b100011,
- ['3'] = 0b100111,
- ['4'] = 0b101111,
- ['5'] = 0b111111,
- ['6'] = 0b111110,
- ['7'] = 0b111100,
- ['8'] = 0b111000,
- ['9'] = 0b110000,
- ['0'] = 0b100000,
-
- ['A'] = 0b101,
- ['B'] = 0b11110,
- ['C'] = 0b11010,
- ['D'] = 0b1110,
- ['E'] = 0b11,
- ['F'] = 0b11011,
- ['G'] = 0b1100,
- ['H'] = 0b11111,
- ['I'] = 0b111,
- ['J'] = 0b10001,
- ['K'] = 0b1010,
- ['L'] = 0b11101,
- ['M'] = 0b100,
- ['N'] = 0b110,
- ['O'] = 0b1000,
- ['P'] = 0b11001,
- ['Q'] = 0b10100,
- ['R'] = 0b1101,
- ['S'] = 0b1111,
- ['T'] = 0b10,
- ['U'] = 0b1011,
- ['V'] = 0b10111,
- ['W'] = 0b1001,
- ['X'] = 0b10110,
- ['Y'] = 0b10010,
- ['Z'] = 0b11100,
-
- ['.'] = 0b1010101,
- [','] = 0b1001100,
- ['?'] = 0b1110011,
- ['\''] = 0b1100001,
- ['!'] = 0b1001010,
- ['/'] = 0b110110,
- ['('] = 0b110010,
- [')'] = 0b1010010,
- ['&'] = 0b111101,
- [':'] = 0b1111000,
- [';'] = 0b1101010,
- ['='] = 0b101110,
- ['+'] = 0b110101,
- ['-'] = 0b1011110,
- ['_'] = 0b1010011,
- ['"'] = 0b1101101,
- ['$'] = 0b10110111,
- ['@'] = 0b1101001,
-
- [1] = 0b101010,
- [2] = 0b101010,
- [3] = 0b1010111,
- [4] = 0b1010111,
- [6] = 0b110111,
-};
-
-void put_morse(char c)
+void put_morse(unsigned char c)
{
switch (c)
{
case ' ':
+ if (need_space)
+ putchar(c);
+ /*fallthrough*/
case '\n':
putchar(c);
+ need_space = 0;
break;
default:
- unsigned char m = seqs[toupper(c)];
+ unsigned char m = nodes[c].seq;
if (m)
put_morse_seq(m);
}
}
-void put_morse_str(char const* str)
-{
- while (*str)
- put_morse(*str++);
-}
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
-int main()
+void encode()
{
for (;;)
{
int c = getchar();
if (c == EOF)
break;
- if (c >= (int)sizeof(seqs))
- return 1;
- put_morse(c);
+
+ c = toupper(c);
+ if (c < (int)ARRAY_SIZE(nodes))
+ put_morse(c);
}
+}
-// putchar ('\n');
- return 0;
+void resolve(unsigned char c, int lower)
+{
+ if (!nodes[c].seq)
+ return;
+ if (lower)
+ putchar(tolower(c));
+ else
+ putchar(c);
+}
+
+void decode(int lower)
+{
+ unsigned char out = START;
+ for (;;)
+ {
+ int in = getchar();
+ switch (in)
+ {
+ case ' ':
+ resolve(out, lower);
+ if (out == START)
+ putchar(' ');
+ out = START;
+ continue;
+ case '\n':
+ resolve(out, lower);
+ out = START;
+ putchar('\n');
+ continue;
+ case '.':
+ out = nodes[out].dit;
+ continue;
+ case '_':
+ case '-':
+ out = nodes[out].dah;
+ continue;
+ case EOF:
+ resolve(out, lower);
+ return;
+ default:
+ resolve(out, lower);
+ out = START;
+ continue;
+ }
+ }
+}
+
+void usage(int code)
+{
+ fputs("Usage: morse [ e | d | D ]\n\n"
+ " e - encode ASCII to morse code\n"
+ " d - decode morse code to lowercase ASCII\n"
+ " D - decode morse code to uppercase ASCII\n", stderr);
+ exit(code);
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ usage(1);
+
+ char arg = argv[1][0];
+
+ switch (arg)
+ {
+ case 'e':
+ encode();
+ break;
+ case 'd':
+ case 'D':
+ decode(islower(arg));
+ break;
+ default:
+ usage(1);
+ }
}