morse_encoder.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. /*
  2. * Morse encoder
  3. *
  4. * Copyright (C) 2011 Michael Buesch <m@bues.ch>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. */
  20. #include "util.h"
  21. #include "morse_encoder.h"
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26. #include <getopt.h>
  27. enum morse_encoding {
  28. ENC_BINARY,
  29. ENC_DASHDOT,
  30. ENC_DITDAH,
  31. };
  32. static int syms_bigendian;
  33. static int decode;
  34. static enum morse_encoding morse_encoding = ENC_DASHDOT;
  35. static char *input_text;
  36. static size_t input_text_len;
  37. /* The morse alphabet */
  38. enum morse_character {
  39. /* Characters */
  40. MORSE_A = 'A',
  41. MORSE_B = 'B',
  42. MORSE_C = 'C',
  43. MORSE_D = 'D',
  44. MORSE_E = 'E',
  45. MORSE_F = 'F',
  46. MORSE_G = 'G',
  47. MORSE_H = 'H',
  48. MORSE_I = 'I',
  49. MORSE_J = 'J',
  50. MORSE_K = 'K',
  51. MORSE_L = 'L',
  52. MORSE_M = 'M',
  53. MORSE_N = 'N',
  54. MORSE_O = 'O',
  55. MORSE_P = 'P',
  56. MORSE_Q = 'Q',
  57. MORSE_R = 'R',
  58. MORSE_S = 'S',
  59. MORSE_T = 'T',
  60. MORSE_U = 'U',
  61. MORSE_V = 'V',
  62. MORSE_W = 'W',
  63. MORSE_X = 'X',
  64. MORSE_Y = 'Y',
  65. MORSE_Z = 'Z',
  66. MORSE_CHARS_START = MORSE_A,
  67. MORSE_CHARS_END = MORSE_Z,
  68. /* Numbers */
  69. MORSE_0 = '0',
  70. MORSE_1 = '1',
  71. MORSE_2 = '2',
  72. MORSE_3 = '3',
  73. MORSE_4 = '4',
  74. MORSE_5 = '5',
  75. MORSE_6 = '6',
  76. MORSE_7 = '7',
  77. MORSE_8 = '8',
  78. MORSE_9 = '9',
  79. MORSE_NUMS_START = MORSE_0,
  80. MORSE_NUMS_END = MORSE_9,
  81. /* Special characters */
  82. MORSE_GACC_A = 128, /* grave accent A */
  83. MORSE_AE, /* Ä */
  84. MORSE_GACC_E, /* grave accent E */
  85. MORSE_AACC_E, /* acute accent E */
  86. MORSE_OE, /* Ö */
  87. MORSE_UE, /* Ü */
  88. MORSE_SZ, /* ß */
  89. MORSE_CH, /* CH */
  90. MORSE_TILDE_N, /* tilde N */
  91. MORSE_PERIOD, /* . */
  92. MORSE_COMMA, /* , */
  93. MORSE_COLON, /* : */
  94. MORSE_SEMICOLON, /* ; */
  95. MORSE_QUESTION, /* ? */
  96. MORSE_DASH, /* - */
  97. MORSE_UNDERSCORE, /* _ */
  98. MORSE_PAREN_OPEN, /* ( */
  99. MORSE_PAREN_CLOSE, /* ) */
  100. MORSE_TICK, /* ' */
  101. MORSE_EQUAL, /* = */
  102. MORSE_PLUS, /* + */
  103. MORSE_SLASH, /* / */
  104. MORSE_AT, /* @ */
  105. MORSE_SPACE, /* */
  106. MORSE_SPEC_START = MORSE_GACC_A,
  107. MORSE_SPEC_END = MORSE_SPACE,
  108. /* Signals */
  109. MORSE_SIG_KA = 192, /* Start */
  110. MORSE_SIG_BT, /* Pause */
  111. MORSE_SIG_AR, /* End */
  112. MORSE_SIG_VE, /* Understood */
  113. MORSE_SIG_SK, /* End of work */
  114. MORSE_SIG_SOS, /* SOS */
  115. MORSE_SIG_ERROR, /* Error */
  116. MORSE_SIG_START = MORSE_SIG_KA,
  117. MORSE_SIG_END = MORSE_SIG_ERROR,
  118. };
  119. #define dit MORSE_DIT
  120. #define dah MORSE_DAH
  121. #define CHAR_SYM(character, symbol) [(character) - MORSE_CHARS_START] = symbol
  122. #define NUM_SYM(number, symbol) [(number) - MORSE_NUMS_START] = symbol
  123. #define SPEC_SYM(spec, symbol) [(spec) - MORSE_SPEC_START] = symbol
  124. #define SIG_SYM(signal, symbol) [(signal) - MORSE_SIG_START] = symbol
  125. static const morse_sym_t character_symbols[] = {
  126. CHAR_SYM(MORSE_A, MORSE_SYM_2(dit, dah)),
  127. CHAR_SYM(MORSE_B, MORSE_SYM_4(dah, dit, dit, dit)),
  128. CHAR_SYM(MORSE_C, MORSE_SYM_4(dah, dit, dah, dit)),
  129. CHAR_SYM(MORSE_D, MORSE_SYM_3(dah, dit, dit)),
  130. CHAR_SYM(MORSE_E, MORSE_SYM_1(dit)),
  131. CHAR_SYM(MORSE_F, MORSE_SYM_4(dit, dit, dah, dit)),
  132. CHAR_SYM(MORSE_G, MORSE_SYM_3(dah, dah, dit)),
  133. CHAR_SYM(MORSE_H, MORSE_SYM_4(dit, dit, dit, dit)),
  134. CHAR_SYM(MORSE_I, MORSE_SYM_2(dit, dit)),
  135. CHAR_SYM(MORSE_J, MORSE_SYM_4(dit, dah, dah, dah)),
  136. CHAR_SYM(MORSE_K, MORSE_SYM_3(dah, dit, dah)),
  137. CHAR_SYM(MORSE_L, MORSE_SYM_4(dit, dah, dit, dit)),
  138. CHAR_SYM(MORSE_M, MORSE_SYM_2(dah, dah)),
  139. CHAR_SYM(MORSE_N, MORSE_SYM_2(dah, dit)),
  140. CHAR_SYM(MORSE_O, MORSE_SYM_3(dah, dah, dah)),
  141. CHAR_SYM(MORSE_P, MORSE_SYM_4(dit, dah, dah, dit)),
  142. CHAR_SYM(MORSE_Q, MORSE_SYM_4(dah, dah, dit, dah)),
  143. CHAR_SYM(MORSE_R, MORSE_SYM_3(dit, dah, dit)),
  144. CHAR_SYM(MORSE_S, MORSE_SYM_3(dit, dit, dit)),
  145. CHAR_SYM(MORSE_T, MORSE_SYM_1(dah)),
  146. CHAR_SYM(MORSE_U, MORSE_SYM_3(dit, dit, dah)),
  147. CHAR_SYM(MORSE_V, MORSE_SYM_4(dit, dit, dit, dah)),
  148. CHAR_SYM(MORSE_W, MORSE_SYM_3(dit, dah, dah)),
  149. CHAR_SYM(MORSE_X, MORSE_SYM_4(dah, dit, dit, dah)),
  150. CHAR_SYM(MORSE_Y, MORSE_SYM_4(dah, dit, dah, dah)),
  151. CHAR_SYM(MORSE_Z, MORSE_SYM_4(dah, dah, dit, dit)),
  152. };
  153. static const morse_sym_t number_symbols[] = {
  154. NUM_SYM(MORSE_0, MORSE_SYM_5(dah, dah, dah, dah, dah)),
  155. NUM_SYM(MORSE_1, MORSE_SYM_5(dit, dah, dah, dah, dah)),
  156. NUM_SYM(MORSE_2, MORSE_SYM_5(dit, dit, dah, dah, dah)),
  157. NUM_SYM(MORSE_3, MORSE_SYM_5(dit, dit, dit, dah, dah)),
  158. NUM_SYM(MORSE_4, MORSE_SYM_5(dit, dit, dit, dit, dah)),
  159. NUM_SYM(MORSE_5, MORSE_SYM_5(dit, dit, dit, dit, dit)),
  160. NUM_SYM(MORSE_6, MORSE_SYM_5(dah, dit, dit, dit, dit)),
  161. NUM_SYM(MORSE_7, MORSE_SYM_5(dah, dah, dit, dit, dit)),
  162. NUM_SYM(MORSE_8, MORSE_SYM_5(dah, dah, dah, dit, dit)),
  163. NUM_SYM(MORSE_9, MORSE_SYM_5(dah, dah, dah, dah, dit)),
  164. };
  165. static const morse_sym_t special_symbols[] = {
  166. SPEC_SYM(MORSE_GACC_A, MORSE_SYM_5(dit, dah, dah, dit, dah)),
  167. SPEC_SYM(MORSE_AE, MORSE_SYM_4(dit, dah, dit, dah)),
  168. SPEC_SYM(MORSE_GACC_E, MORSE_SYM_5(dit, dah, dit, dit, dah)),
  169. SPEC_SYM(MORSE_AACC_E, MORSE_SYM_5(dit, dit, dah, dit, dit)),
  170. SPEC_SYM(MORSE_OE, MORSE_SYM_4(dah, dah, dah, dit)),
  171. SPEC_SYM(MORSE_UE, MORSE_SYM_4(dit, dit, dah, dah)),
  172. SPEC_SYM(MORSE_SZ, MORSE_SYM_6(dit, dit, dit, dah, dah, dit)),
  173. SPEC_SYM(MORSE_CH, MORSE_SYM_4(dah, dah, dah, dah)),
  174. SPEC_SYM(MORSE_TILDE_N, MORSE_SYM_5(dah, dah, dit, dah, dah)),
  175. SPEC_SYM(MORSE_PERIOD, MORSE_SYM_6(dit, dah, dit, dah, dit, dah)),
  176. SPEC_SYM(MORSE_COMMA, MORSE_SYM_6(dah, dah, dit, dit, dah, dah)),
  177. SPEC_SYM(MORSE_COLON, MORSE_SYM_6(dah, dah, dah, dit, dit, dit)),
  178. SPEC_SYM(MORSE_SEMICOLON, MORSE_SYM_6(dah, dit, dah, dit, dah, dit)),
  179. SPEC_SYM(MORSE_QUESTION, MORSE_SYM_6(dit, dit, dah, dah, dit, dit)),
  180. SPEC_SYM(MORSE_DASH, MORSE_SYM_6(dah, dit, dit, dit, dit, dah)),
  181. SPEC_SYM(MORSE_UNDERSCORE, MORSE_SYM_6(dit, dit, dah, dah, dit, dah)),
  182. SPEC_SYM(MORSE_PAREN_OPEN, MORSE_SYM_5(dah, dit, dah, dah, dit)),
  183. SPEC_SYM(MORSE_PAREN_CLOSE, MORSE_SYM_6(dah, dit, dah, dah, dit, dah)),
  184. SPEC_SYM(MORSE_TICK, MORSE_SYM_6(dit, dah, dah, dah, dah, dit)),
  185. SPEC_SYM(MORSE_EQUAL, MORSE_SYM_5(dah, dit, dit, dit, dah)),
  186. SPEC_SYM(MORSE_PLUS, MORSE_SYM_5(dit, dah, dit, dah, dit)),
  187. SPEC_SYM(MORSE_SLASH, MORSE_SYM_5(dah, dit, dit, dah, dit)),
  188. SPEC_SYM(MORSE_AT, MORSE_SYM_6(dit, dah, dah, dit, dah, dit)),
  189. SPEC_SYM(MORSE_SPACE, 0),
  190. };
  191. static const morse_sym_t signal_symbols[] = {
  192. SIG_SYM(MORSE_SIG_KA, MORSE_SYM_5(dah, dit, dah, dit, dah)),
  193. SIG_SYM(MORSE_SIG_BT, MORSE_SYM_5(dah, dit, dit, dit, dah)),
  194. SIG_SYM(MORSE_SIG_AR, MORSE_SYM_5(dit, dah, dit, dah, dit)),
  195. SIG_SYM(MORSE_SIG_VE, MORSE_SYM_5(dit, dit, dit, dah, dit)),
  196. SIG_SYM(MORSE_SIG_SK, MORSE_SYM_6(dit, dit, dit, dah, dit, dah)),
  197. SIG_SYM(MORSE_SIG_SOS, MORSE_SYM_9(dit, dit, dit, dah, dah, dah, dit, dit, dit)),
  198. SIG_SYM(MORSE_SIG_ERROR, MORSE_SYM_8(dit, dit, dit, dit, dit, dit, dit, dit)),
  199. };
  200. static morse_sym_t morse_encode_character(enum morse_character c)
  201. {
  202. BUILD_BUG_ON(ARRAY_SIZE(character_symbols) != MORSE_CHARS_END - MORSE_CHARS_START + 1);
  203. BUILD_BUG_ON(ARRAY_SIZE(number_symbols) != MORSE_NUMS_END - MORSE_NUMS_START + 1);
  204. BUILD_BUG_ON(ARRAY_SIZE(special_symbols) != MORSE_SPEC_END - MORSE_SPEC_START + 1);
  205. BUILD_BUG_ON(ARRAY_SIZE(signal_symbols) != MORSE_SIG_END - MORSE_SIG_START + 1);
  206. if (c >= MORSE_CHARS_START && c <= MORSE_CHARS_END)
  207. return character_symbols[c - MORSE_CHARS_START];
  208. if (c >= MORSE_NUMS_START && c <= MORSE_NUMS_END)
  209. return number_symbols[c - MORSE_NUMS_START];
  210. if (c >= MORSE_SPEC_START && c <= MORSE_SPEC_END)
  211. return special_symbols[c - MORSE_SPEC_START];
  212. if (c >= MORSE_SIG_START && c <= MORSE_SIG_END)
  213. return signal_symbols[c - MORSE_SIG_START];
  214. return signal_symbols[MORSE_SIG_ERROR - MORSE_SIG_START];
  215. }
  216. static enum morse_character morse_decode_symbol(morse_sym_t sym)
  217. {
  218. unsigned int i;
  219. #define check_decode_tab(table, startchar) \
  220. for (i = 0; i < ARRAY_SIZE(table); i++) { \
  221. if (table[i] == sym) \
  222. return (enum morse_character)(i + startchar); \
  223. }
  224. check_decode_tab(character_symbols, MORSE_CHARS_START)
  225. check_decode_tab(number_symbols, MORSE_NUMS_START)
  226. check_decode_tab(special_symbols, MORSE_SPEC_START)
  227. check_decode_tab(signal_symbols, MORSE_SIG_START)
  228. #undef check_decode_tab
  229. return (enum morse_character)-1;
  230. }
  231. static enum morse_character ascii_to_morse(char ascii_char)
  232. {
  233. if (ascii_char >= 'a' && ascii_char <= 'z')
  234. return MORSE_A + (ascii_char - 'a');
  235. if (ascii_char >= 'A' && ascii_char <= 'Z')
  236. return MORSE_A + (ascii_char - 'A');
  237. if (ascii_char >= '0' && ascii_char <= '9')
  238. return MORSE_0 + (ascii_char - '0');
  239. switch (ascii_char) {
  240. case ' ':
  241. case '\t':
  242. case '\n':
  243. return MORSE_SPACE;
  244. case '.':
  245. return MORSE_PERIOD;
  246. case ',':
  247. return MORSE_COMMA;
  248. case ':':
  249. return MORSE_COLON;
  250. case ';':
  251. return MORSE_SEMICOLON;
  252. case '?':
  253. return MORSE_QUESTION;
  254. case '-':
  255. return MORSE_DASH;
  256. case '_':
  257. return MORSE_UNDERSCORE;
  258. case '(':
  259. return MORSE_PAREN_OPEN;
  260. case ')':
  261. return MORSE_PAREN_CLOSE;
  262. case '\'':
  263. return MORSE_TICK;
  264. case '=':
  265. return MORSE_EQUAL;
  266. case '+':
  267. return MORSE_PLUS;
  268. case '/':
  269. return MORSE_SLASH;
  270. case '@':
  271. return MORSE_AT;
  272. }
  273. return MORSE_SIG_ERROR;
  274. }
  275. static char morse_to_ascii(enum morse_character mchar)
  276. {
  277. if ((mchar >= MORSE_CHARS_START && mchar <= MORSE_CHARS_END) ||
  278. (mchar >= MORSE_NUMS_START && mchar <= MORSE_NUMS_END))
  279. return (char)mchar;
  280. switch (mchar) {
  281. case MORSE_SPACE:
  282. return ' ';
  283. case MORSE_PERIOD:
  284. return '.';
  285. case MORSE_COMMA:
  286. return ',';
  287. case MORSE_COLON:
  288. return ':';
  289. case MORSE_SEMICOLON:
  290. return ';';
  291. case MORSE_QUESTION:
  292. return '?';
  293. case MORSE_DASH:
  294. return '-';
  295. case MORSE_UNDERSCORE:
  296. return '_';
  297. case MORSE_PAREN_OPEN:
  298. return '(';
  299. case MORSE_PAREN_CLOSE:
  300. return ')';
  301. case MORSE_TICK:
  302. return '\'';
  303. case MORSE_EQUAL:
  304. return '=';
  305. case MORSE_PLUS:
  306. return '+';
  307. case MORSE_SLASH:
  308. return '/';
  309. case MORSE_AT:
  310. return '@';
  311. default:
  312. break;
  313. }
  314. return '\0';
  315. }
  316. static int morse_encode(void)
  317. {
  318. const char *ascii;
  319. enum morse_character morse;
  320. morse_sym_t sym;
  321. unsigned int i;
  322. for (ascii = input_text; *ascii; ascii++) {
  323. morse = ascii_to_morse(*ascii);
  324. if (morse == MORSE_SIG_ERROR) {
  325. fprintf(stderr, "Could not translate character: %c\n", *ascii);
  326. return -1;
  327. }
  328. sym = morse_encode_character(morse);
  329. switch (morse_encoding) {
  330. case ENC_DASHDOT:
  331. if (MORSE_SYM_IS_SPACE(sym)) {
  332. printf("/ ");
  333. } else {
  334. for (i = 0; i < MORSE_SYM_SIZE(sym); i++) {
  335. if (((MORSE_SYM_MARKS(sym) >> i) & 1) == MORSE_DIT)
  336. putchar('.');
  337. else
  338. putchar('-');
  339. }
  340. putchar(' ');
  341. putchar(' ');
  342. }
  343. break;
  344. case ENC_DITDAH:
  345. if (MORSE_SYM_IS_SPACE(sym)) {
  346. printf(", ");
  347. } else {
  348. for (i = 0; i < MORSE_SYM_SIZE(sym); i++) {
  349. if (((MORSE_SYM_MARKS(sym) >> i) & 1) == MORSE_DIT) {
  350. if (i == 0)
  351. printf("Di");
  352. else if (i == MORSE_SYM_SIZE(sym) - 1)
  353. printf("-dit");
  354. else
  355. printf("-di");
  356. } else {
  357. if (i == 0)
  358. printf("Dah");
  359. else
  360. printf("-dah");
  361. }
  362. }
  363. putchar(' ');
  364. }
  365. break;
  366. case ENC_BINARY:
  367. if (syms_bigendian) {
  368. putchar((sym >> 8) & 0xFF);
  369. putchar(sym & 0xFF);
  370. } else {
  371. putchar(sym & 0xFF);
  372. putchar((sym >> 8) & 0xFF);
  373. }
  374. break;
  375. }
  376. }
  377. if (morse_encoding != ENC_BINARY)
  378. putchar('\n');
  379. return 0;
  380. }
  381. static int decode_marks(unsigned int marks, unsigned int size)
  382. {
  383. morse_sym_t sym;
  384. enum morse_character mchar;
  385. char achar;
  386. sym = __MORSE_SYM(marks, size);
  387. mchar = morse_decode_symbol(sym);
  388. if (mchar == (enum morse_character)-1) {
  389. fprintf(stderr, "Could not decode symbol 0x%04X\n",
  390. (uint16_t)sym);
  391. return -1;
  392. }
  393. achar = morse_to_ascii(mchar);
  394. if (!achar) {
  395. fprintf(stderr, "Could not decode morse char 0x%02X\n",
  396. (uint8_t)mchar);
  397. return -1;
  398. }
  399. putchar(achar);
  400. return 0;
  401. }
  402. static int morse_decode_dashdot(void)
  403. {
  404. const char *input = input_text;
  405. char c;
  406. unsigned int i = 0;
  407. unsigned int marks = 0;
  408. int err;
  409. while (1) {
  410. c = *input;
  411. if (!c) {
  412. if (i) {
  413. err = decode_marks(marks, i);
  414. if (err)
  415. return err;
  416. }
  417. break;
  418. }
  419. input++;
  420. if (c == '.') {
  421. marks &= ~(1 << i);
  422. marks |= (MORSE_DIT << i);
  423. i++;
  424. } else if (c == '-' || c == '_') {
  425. marks &= ~(1 << i);
  426. marks |= (MORSE_DAH << i);
  427. i++;
  428. } else if (isspace(c)) { /* end of char */
  429. if (i) {
  430. err = decode_marks(marks, i);
  431. if (err)
  432. return err;
  433. i = 0;
  434. marks = 0;
  435. }
  436. } else /* end of word */
  437. putchar(' ');
  438. if (i > 9) {
  439. fprintf(stderr, "Too many marks\n");
  440. return -1;
  441. }
  442. }
  443. return 0;
  444. }
  445. static const char * eat(const char *str, char c)
  446. {
  447. while (*str == c)
  448. str++;
  449. return str;
  450. }
  451. static const char * eat_alpha(const char *str)
  452. {
  453. while (isalpha(*str))
  454. str++;
  455. return str;
  456. }
  457. static const char * eat_space(const char *str)
  458. {
  459. while (isspace(*str))
  460. str++;
  461. return str;
  462. }
  463. static int morse_decode_ditdah(void)
  464. {
  465. const char *input = input_text;
  466. unsigned int i = 0;
  467. unsigned int marks = 0;
  468. int err;
  469. while (1) {
  470. if (!(*input)) {
  471. if (i) {
  472. err = decode_marks(marks, i);
  473. if (err)
  474. return err;
  475. }
  476. break;
  477. }
  478. if (strncasecmp(input, "di", 2) == 0) {
  479. marks &= ~(1 << i);
  480. marks |= (MORSE_DIT << i);
  481. i++;
  482. input = eat_alpha(input);
  483. input = eat(input, '-');
  484. } else if (strncasecmp(input, "da", 2) == 0) {
  485. marks &= ~(1 << i);
  486. marks |= (MORSE_DAH << i);
  487. i++;
  488. input = eat_alpha(input);
  489. input = eat(input, '-');
  490. } else if (isspace(*input)) { /* end of char */
  491. if (i) {
  492. err = decode_marks(marks, i);
  493. if (err)
  494. return err;
  495. i = 0;
  496. marks = 0;
  497. }
  498. input = eat_space(input);
  499. } else { /* end of word */
  500. putchar(' ');
  501. input++;
  502. input = eat_space(input);
  503. }
  504. if (i > 9) {
  505. fprintf(stderr, "Too many marks\n");
  506. return -1;
  507. }
  508. }
  509. return 0;
  510. }
  511. static int morse_decode_binary(void)
  512. {
  513. size_t i;
  514. morse_sym_t sym;
  515. enum morse_character mchar;
  516. char achar;
  517. if (input_text_len % 2) {
  518. fprintf(stderr, "Invalid input length (odd length)\n");
  519. return -1;
  520. }
  521. for (i = 0; i < input_text_len; i += 2) {
  522. if (syms_bigendian) {
  523. sym = (uint16_t)input_text[i] << 8;
  524. sym |= (uint16_t)input_text[i + 1];
  525. } else {
  526. sym = (uint16_t)input_text[i];
  527. sym |= (uint16_t)input_text[i + 1] << 8;
  528. }
  529. mchar = morse_decode_symbol(sym);
  530. if (mchar == (enum morse_character)-1) {
  531. fprintf(stderr, "Could not decode symbol 0x%04X\n",
  532. (uint16_t)sym);
  533. return -1;
  534. }
  535. achar = morse_to_ascii(mchar);
  536. if (!achar) {
  537. fprintf(stderr, "Could not decode morse char 0x%02X\n",
  538. (uint8_t)mchar);
  539. return -1;
  540. }
  541. putchar(achar);
  542. }
  543. return 0;
  544. }
  545. static int morse_decode(void)
  546. {
  547. int err = -1;
  548. switch (morse_encoding) {
  549. case ENC_DASHDOT:
  550. err = morse_decode_dashdot();
  551. break;
  552. case ENC_DITDAH:
  553. err = morse_decode_ditdah();
  554. break;
  555. case ENC_BINARY:
  556. err = morse_decode_binary();
  557. break;
  558. }
  559. if (err)
  560. return err;
  561. putchar('\n');
  562. return 0;
  563. }
  564. static void * checked_realloc(void *buf, size_t size)
  565. {
  566. buf = realloc(buf, size);
  567. if (!buf) {
  568. fprintf(stderr, "Out of memory\n");
  569. exit(1);
  570. }
  571. return buf;
  572. }
  573. static void usage(int argc, char **argv)
  574. {
  575. printf("Usage: %s <options> [STRING]\n\n", argv[0]);
  576. printf("Options:\n");
  577. printf(" -b|--bigendian Bigendian symbols (default little endian)\n");
  578. printf(" -B|--binary Binary format\n");
  579. printf(" -d|--dashdot Human readable dash/dot format (default)\n");
  580. printf(" -D|--ditdah Human readable dit/dah format\n");
  581. printf(" -x|--decode Switch to decode mode\n");
  582. }
  583. static int parse_args(int argc, char **argv)
  584. {
  585. int i = 0, c;
  586. char *buf = NULL;
  587. size_t bufsize = 0, len;
  588. static const struct option long_opts[] = {
  589. { .name = "help", .has_arg = no_argument, .flag = NULL, .val = 'h' },
  590. { .name = "bigendian", .has_arg = no_argument, .flag = NULL, .val = 'b' },
  591. { .name = "binary", .has_arg = no_argument, .flag = NULL, .val = 'B' },
  592. { .name = "ditdah", .has_arg = no_argument, .flag = NULL, .val = 'D' },
  593. { .name = "dashdot", .has_arg = no_argument, .flag = NULL, .val = 'd' },
  594. { .name = "decode", .has_arg = no_argument, .flag = NULL, .val = 'x' },
  595. };
  596. while (1) {
  597. c = getopt_long(argc, argv, "hbBDdx", long_opts, &i);
  598. if (c == -1)
  599. break;
  600. switch (c) {
  601. case 'h':
  602. usage(argc, argv);
  603. return 1;
  604. case 'b':
  605. syms_bigendian = 1;
  606. break;
  607. case 'B':
  608. morse_encoding = ENC_BINARY;
  609. break;
  610. case 'd':
  611. morse_encoding = ENC_DASHDOT;
  612. break;
  613. case 'D':
  614. morse_encoding = ENC_DITDAH;
  615. break;
  616. case 'x':
  617. decode = 1;
  618. break;
  619. default:
  620. return -1;
  621. }
  622. }
  623. for (i = optind; i < argc; i++) {
  624. len = strlen(argv[i]) + 1;
  625. bufsize += len;
  626. buf = checked_realloc(buf, bufsize);
  627. strcpy(&buf[bufsize - len], argv[i]);
  628. buf[bufsize - 1] = ' ';
  629. }
  630. buf[bufsize - 1] = '\0';
  631. input_text = buf;
  632. return 0;
  633. }
  634. size_t stdin_read(char **buffer)
  635. {
  636. char *buf = NULL;
  637. size_t bufsize = 0, i = 0;
  638. int c;
  639. while (1) {
  640. c = fgetc(stdin);
  641. if (c == EOF)
  642. break;
  643. if (i + 1 >= bufsize) {
  644. bufsize += 32;
  645. buf = checked_realloc(buf, bufsize);
  646. }
  647. buf[i++] = c;
  648. }
  649. if (buf)
  650. buf[i] = '\0';
  651. *buffer = buf;
  652. return i;
  653. }
  654. int main(int argc, char **argv)
  655. {
  656. int err;
  657. err = parse_args(argc, argv);
  658. if (err > 0)
  659. return 0;
  660. if (err < 0)
  661. return 1;
  662. if (input_text)
  663. input_text_len = strlen(input_text);
  664. else
  665. input_text_len = stdin_read(&input_text);
  666. if (!input_text || !input_text_len)
  667. return 1;
  668. if (decode)
  669. err = morse_decode();
  670. else
  671. err = morse_encode();
  672. free(input_text);
  673. return err ? 1 : 0;
  674. }