examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

commit 54aaca2d308e8b1f76356abb30bac35907f5de90
parent b85fe016df137f5a661738d397167e6c6400afbc
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Thu, 16 Feb 2023 09:05:57 +0000

morse: Add decoder

Diffstat:
Msrc/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); + } }