1 /* $OpenBSD: morse.c,v 1.22 2016/03/07 12:07:56 mestre Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <ctype.h>
33 #include <err.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 static char
40 *digit[] = {
41 "-----",
42 ".----",
43 "..---",
44 "...--",
45 "....-",
46 ".....",
47 "-....",
48 "--...",
49 "---..",
50 "----.",
51 },
52 *alph[] = {
53 ".-",
54 "-...",
55 "-.-.",
56 "-..",
57 ".",
58 "..-.",
59 "--.",
60 "....",
61 "..",
62 ".---",
63 "-.-",
64 ".-..",
65 "--",
66 "-.",
67 "---",
68 ".--.",
69 "--.-",
70 ".-.",
71 "...",
72 "-",
73 "..-",
74 "...-",
75 ".--",
76 "-..-",
77 "-.--",
78 "--..",
79 };
80
81 struct punc {
82 char c;
83 char *morse;
84 } other[] = {
85 { 'e', "..-.." }, /* accented e - only decodes */
86 { ',', "--..--" },
87 { '.', ".-.-.-" },
88 { '?', "..--.." },
89 { '/', "-..-." },
90 { '-', "-....-" },
91 { ':', "---..." },
92 { ';', "-.-.-." },
93 { '(', "-.--." }, /* KN */
94 { ')', "-.--.-" },
95 { '"', ".-..-." },
96 { '`', ".-..-." },
97 { '\'', ".----." },
98 { '+', ".-.-." }, /* AR \n\n\n */
99 { '=', "-...-" }, /* BT \n\n */
100 { '@', ".--.-." },
101 { '\n', ".-.-" }, /* AA (will only decode) */
102 { '\0', NULL }
103 };
104
105 struct prosign {
106 char *c;
107 char *morse;
108 } ps[] = {
109 { "<AS>", ".-..." }, /* wait */
110 { "<CL>", "-.-..-.." },
111 { "<CT>", "-.-.-" }, /* start */
112 { "<EE5>", "......" }, /* error */
113 { "<EE5>", "......." },
114 { "<EE5>", "........" },
115 { "<SK>", "...-.-" },
116 { "<SN>", "...-." }, /* understood */
117 { "<SOS>", "...---..." },
118 { NULL, NULL }
119 };
120
121 void morse(int);
122 void decode(char *);
123 void show(char *);
124
125 static int sflag = 0;
126 static int dflag = 0;
127
128 int
main(int argc,char * argv[])129 main(int argc, char *argv[])
130 {
131 int ch;
132 char *p;
133
134 if (pledge("stdio", NULL) == -1)
135 err(1, "pledge");
136
137 while ((ch = getopt(argc, argv, "dsh")) != -1)
138 switch(ch) {
139 case 'd':
140 dflag = 1;
141 break;
142 case 's':
143 sflag = 1;
144 break;
145 case 'h':
146 default:
147 fprintf(stderr, "usage: %s [-d | -s] [string ...]\n",
148 getprogname());
149 return 1;
150 }
151 argc -= optind;
152 argv += optind;
153
154 if (dflag) {
155 if (*argv) {
156 do {
157 decode(*argv);
158 } while (*++argv);
159 } else {
160 char foo[10]; /* All morse chars shorter than this */
161 int isblank, i;
162
163 i = 0;
164 isblank = 0;
165 while ((ch = getchar()) != EOF) {
166 if (ch == '-' || ch == '.') {
167 foo[i++] = ch;
168 if (i == 10) {
169 /* overrun means gibberish--print 'x' and
170 * advance */
171 i = 0;
172 putchar('x');
173 while ((ch = getchar()) != EOF &&
174 (ch == '.' || ch == '-'))
175 ;
176 isblank = 1;
177 }
178 } else if (i) {
179 foo[i] = '\0';
180 decode(foo);
181 i = 0;
182 isblank = 0;
183 } else if (isspace(ch)) {
184 if (isblank) {
185 /* print whitespace for each double blank */
186 putchar(' ');
187 isblank = 0;
188 } else
189 isblank = 1;
190 }
191 }
192 }
193 putchar('\n');
194 } else {
195 if (*argv)
196 do {
197 for (p = *argv; *p; ++p)
198 morse((int)*p);
199 show("");
200 } while (*++argv);
201 else while ((ch = getchar()) != EOF)
202 morse(ch);
203 show("...-.-"); /* SK */
204 }
205 return 0;
206 }
207
208 void
morse(int c)209 morse(int c)
210 {
211 int i;
212
213 if (isalpha(c))
214 show(alph[c - (isupper(c) ? 'A' : 'a')]);
215 else if (isdigit(c))
216 show(digit[c - '0']);
217 else if (isspace(c))
218 show(""); /* could show BT for a pause */
219 else {
220 i = 0;
221 while (other[i].c) {
222 if (other[i].c == c) {
223 show(other[i].morse);
224 break;
225 }
226 i++;
227 }
228 }
229 }
230
231 void
decode(char * s)232 decode(char *s)
233 {
234 int i;
235
236 for (i = 0; i < 10; i++)
237 if (strcmp(digit[i], s) == 0) {
238 putchar('0' + i);
239 return;
240 }
241
242 for (i = 0; i < 26; i++)
243 if (strcmp(alph[i], s) == 0) {
244 putchar('A' + i);
245 return;
246 }
247 i = 0;
248 while (other[i].c) {
249 if (strcmp(other[i].morse, s) == 0) {
250 putchar(other[i].c);
251 return;
252 }
253 i++;
254 }
255 i = 0;
256 while (ps[i].c) {
257 /* put whitespace around prosigns */
258 if (strcmp(ps[i].morse, s) == 0) {
259 printf(" %s ", ps[i].c);
260 return;
261 }
262 i++;
263 }
264 putchar('x'); /* line noise */
265 }
266
267
268
269 void
show(char * s)270 show(char *s)
271 {
272 if (sflag)
273 printf(" %s", s);
274 else for (; *s; ++s)
275 printf(" %s", *s == '.' ? "dit" : "daw");
276 printf("\n");
277 }
278