xref: /openbsd-src/games/morse/morse.c (revision 6fa5e1da3490487b9d3a614457ba0b7c041eb1ac)
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