xref: /netbsd-src/games/morse/morse.c (revision b76a7d7ed4dd3d0dd74e24d32797e92ef1c6066e)
1*b76a7d7eSrillig /*	$NetBSD: morse.c,v 1.23 2024/10/12 19:26:24 rillig Exp $	*/
242fb1b9dScgd 
361f28255Scgd /*
442fb1b9dScgd  * Copyright (c) 1988, 1993
542fb1b9dScgd  *	The Regents of the University of California.  All rights reserved.
661f28255Scgd  *
761f28255Scgd  * Redistribution and use in source and binary forms, with or without
861f28255Scgd  * modification, are permitted provided that the following conditions
961f28255Scgd  * are met:
1061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1461f28255Scgd  *    documentation and/or other materials provided with the distribution.
15e5aeb4eaSagc  * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd  *    may be used to endorse or promote products derived from this software
1761f28255Scgd  *    without specific prior written permission.
1861f28255Scgd  *
1961f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd  * SUCH DAMAGE.
3061f28255Scgd  */
3161f28255Scgd 
325ab1a671Slukem #include <sys/cdefs.h>
332fe2731dSlukem __COPYRIGHT("@(#) Copyright (c) 1988, 1993\
342fe2731dSlukem  The Regents of the University of California.  All rights reserved.");
35*b76a7d7eSrillig /*	@(#)morse.c	8.1 (Berkeley) 5/31/93	*/
36*b76a7d7eSrillig __RCSID("$NetBSD: morse.c,v 1.23 2024/10/12 19:26:24 rillig Exp $");
3761f28255Scgd 
3861f28255Scgd #include <ctype.h>
395ab1a671Slukem #include <stdio.h>
4032330650Smatt #include <stdlib.h>
41d5f8b67eShubertf #include <string.h>
425ab1a671Slukem #include <unistd.h>
4361f28255Scgd 
44508549b5Srillig static const char digit[][6] = {
4561f28255Scgd 	"-----",
4661f28255Scgd 	".----",
4761f28255Scgd 	"..---",
4861f28255Scgd 	"...--",
4961f28255Scgd 	"....-",
5061f28255Scgd 	".....",
5161f28255Scgd 	"-....",
5261f28255Scgd 	"--...",
5361f28255Scgd 	"---..",
5461f28255Scgd 	"----.",
55508549b5Srillig };
56508549b5Srillig 
57508549b5Srillig static const char alph[][5] = {
5861f28255Scgd 	".-",
5961f28255Scgd 	"-...",
6061f28255Scgd 	"-.-.",
6161f28255Scgd 	"-..",
6261f28255Scgd 	".",
6361f28255Scgd 	"..-.",
6461f28255Scgd 	"--.",
6561f28255Scgd 	"....",
6661f28255Scgd 	"..",
6761f28255Scgd 	".---",
6861f28255Scgd 	"-.-",
6961f28255Scgd 	".-..",
7061f28255Scgd 	"--",
7161f28255Scgd 	"-.",
7261f28255Scgd 	"---",
7361f28255Scgd 	".--.",
7461f28255Scgd 	"--.-",
7561f28255Scgd 	".-.",
7661f28255Scgd 	"...",
7761f28255Scgd 	"-",
7861f28255Scgd 	"..-",
7961f28255Scgd 	"...-",
8061f28255Scgd 	".--",
8161f28255Scgd 	"-..-",
8261f28255Scgd 	"-.--",
8361f28255Scgd 	"--..",
8461f28255Scgd };
8561f28255Scgd 
86*b76a7d7eSrillig static const struct {
871775f4feSjsm 	char c;
88508549b5Srillig 	const char morse[7];
891775f4feSjsm } other[] = {
901775f4feSjsm 	{ '.', ".-.-.-" },
911775f4feSjsm 	{ ',', "--..--" },
921775f4feSjsm 	{ ':', "---..." },
931775f4feSjsm 	{ '?', "..--.." },
941775f4feSjsm 	{ '\'', ".----." },
951775f4feSjsm 	{ '-', "-....-" },
961775f4feSjsm 	{ '/', "-..-." },
971775f4feSjsm 	{ '(', "-.--." },
981775f4feSjsm 	{ ')', "-.--.-" },
991775f4feSjsm 	{ '"', ".-..-." },
1001775f4feSjsm 	{ '=', "-...-" },
1011775f4feSjsm 	{ '+', ".-.-." },
102a3e52c51Smaya 	{ '_', "..--.-" },
103cefbb2f3Smrg 	{ '@', ".--.-." },
104508549b5Srillig 	{ '\0', "" }
1051775f4feSjsm };
1061775f4feSjsm 
107f2a20f5fSdholland static void morse(int);
108f2a20f5fSdholland static void decode(const char *);
109f2a20f5fSdholland static void show(const char *);
1105ab1a671Slukem 
11161f28255Scgd static int sflag;
112d5f8b67eShubertf static int dflag;
11361f28255Scgd 
1145ab1a671Slukem int
115277bd075Sdholland main(int argc, char **argv)
11661f28255Scgd {
1175ab1a671Slukem 	int ch;
1181775f4feSjsm 	char *p;
11961f28255Scgd 
1205367f340Sjsm 	/* Revoke setgid privileges */
121f9eca697Smycroft 	setgid(getgid());
1225367f340Sjsm 
123d5f8b67eShubertf 	while ((ch = getopt(argc, argv, "ds")) != -1)
12461f28255Scgd 		switch ((char)ch) {
125d5f8b67eShubertf 		case 'd':
126d5f8b67eShubertf 			dflag = 1;
127d5f8b67eShubertf 			break;
12861f28255Scgd 		case 's':
12961f28255Scgd 			sflag = 1;
13061f28255Scgd 			break;
13161f28255Scgd 		default:
132d5f8b67eShubertf 			fprintf(stderr, "usage: morse [-ds] [string ...]\n");
13361f28255Scgd 			exit(1);
13461f28255Scgd 		}
13561f28255Scgd 	argc -= optind;
13661f28255Scgd 	argv += optind;
13761f28255Scgd 
138d5f8b67eShubertf 	if (dflag) {
139d5f8b67eShubertf 		if (*argv) {
140d5f8b67eShubertf 			do {
141d5f8b67eShubertf 				decode(*argv);
142d5f8b67eShubertf 			} while (*++argv);
143d5f8b67eShubertf 		} else {
1441775f4feSjsm 			char foo[10];	/* All morse chars shorter than this */
1450f032c1fSdholland 			int is_blank, i;
146d5f8b67eShubertf 
1471775f4feSjsm 			i = 0;
1480f032c1fSdholland 			is_blank = 0;
1491775f4feSjsm 			while ((ch = getchar()) != EOF) {
1501775f4feSjsm 				if (ch == '-' || ch == '.') {
1511775f4feSjsm 					foo[i++] = ch;
1521775f4feSjsm 					if (i == 10) {
1531775f4feSjsm 						/* overrun means gibberish--print 'x' and
1541775f4feSjsm 						 * advance */
1551775f4feSjsm 						i = 0;
1561775f4feSjsm 						putchar('x');
1571775f4feSjsm 						while ((ch = getchar()) != EOF &&
1581775f4feSjsm 						    (ch == '.' || ch == '-'))
1591775f4feSjsm 							;
1600f032c1fSdholland 						is_blank = 1;
161d5f8b67eShubertf 					}
1621775f4feSjsm 				} else if (i) {
1631775f4feSjsm 					foo[i] = '\0';
1641775f4feSjsm 					decode(foo);
1651775f4feSjsm 					i = 0;
1660f032c1fSdholland 					is_blank = 0;
1671775f4feSjsm 				} else if (isspace(ch)) {
1680f032c1fSdholland 					if (is_blank) {
1691775f4feSjsm 						/* print whitespace for each double blank */
1701775f4feSjsm 						putchar(' ');
1710f032c1fSdholland 						is_blank = 0;
1721775f4feSjsm 					} else
1730f032c1fSdholland 						is_blank = 1;
174d5f8b67eShubertf 				}
175d5f8b67eShubertf 			}
176d5f8b67eShubertf 		}
177d5f8b67eShubertf 		putchar('\n');
178d5f8b67eShubertf 	} else {
17961f28255Scgd 		if (*argv)
18061f28255Scgd 			do {
18161f28255Scgd 				for (p = *argv; *p; ++p)
18220cc95c1Srillig 					morse((unsigned char)*p);
1831775f4feSjsm 				show("");
18461f28255Scgd 			} while (*++argv);
18561f28255Scgd 		else while ((ch = getchar()) != EOF)
18661f28255Scgd 			morse(ch);
1871775f4feSjsm 		show("...-.-");	/* SK */
188d5f8b67eShubertf 	}
189d5f8b67eShubertf 
190d5f8b67eShubertf 	return 0;
191d5f8b67eShubertf }
192d5f8b67eShubertf 
193d5f8b67eShubertf void
194277bd075Sdholland decode(const char *s)
195d5f8b67eShubertf {
196*b76a7d7eSrillig 	for (size_t i = 0; i < __arraycount(digit); i++)
1971775f4feSjsm 		if (strcmp(digit[i], s) == 0) {
198d5f8b67eShubertf 			putchar('0' + i);
199d5f8b67eShubertf 			return;
200d5f8b67eShubertf 		}
201d5f8b67eShubertf 
202*b76a7d7eSrillig 	for (size_t i = 0; i < __arraycount(alph); i++)
2031775f4feSjsm 		if (strcmp(alph[i], s) == 0) {
2041775f4feSjsm 			putchar('A' + i);
2051775f4feSjsm 			return;
206d5f8b67eShubertf 		}
207*b76a7d7eSrillig 
208*b76a7d7eSrillig 	for (size_t i = 0; other[i].c; i++)
2091775f4feSjsm 		if (strcmp(other[i].morse, s) == 0) {
2101775f4feSjsm 			putchar(other[i].c);
2111775f4feSjsm 			return;
212d5f8b67eShubertf 		}
213*b76a7d7eSrillig 
214*b76a7d7eSrillig 	if (strcmp("...-.-", s) == 0)	/* SK */
2151775f4feSjsm 		return;
216*b76a7d7eSrillig 
2171775f4feSjsm 	putchar('x');	/* line noise */
21861f28255Scgd }
21961f28255Scgd 
2205ab1a671Slukem void
221277bd075Sdholland morse(int c)
22261f28255Scgd {
22361f28255Scgd 	if (isalpha(c))
22461f28255Scgd 		show(alph[c - (isupper(c) ? 'A' : 'a')]);
22561f28255Scgd 	else if (isdigit(c))
22661f28255Scgd 		show(digit[c - '0']);
22761f28255Scgd 	else if (isspace(c))
2281775f4feSjsm 		show("");  /* could show BT for a pause */
229*b76a7d7eSrillig 	else
230*b76a7d7eSrillig 		for (int i = 0; other[i].c; i++)
2311775f4feSjsm 			if (other[i].c == c) {
2321775f4feSjsm 				show(other[i].morse);
2331775f4feSjsm 				break;
2341775f4feSjsm 			}
23561f28255Scgd }
23661f28255Scgd 
2375ab1a671Slukem void
238277bd075Sdholland show(const char *s)
23961f28255Scgd {
24061f28255Scgd 	if (sflag)
24161f28255Scgd 		printf(" %s", s);
24261f28255Scgd 	else for (; *s; ++s)
24361f28255Scgd 		printf(" %s", *s == '.' ? "dit" : "daw");
2441775f4feSjsm 	printf("\n");
24561f28255Scgd }
246