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