xref: /openbsd/games/morse/morse.c (revision 7b36286a)
1 /*	$OpenBSD: morse.c,v 1.13 2005/11/07 19:09:33 jmc 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 #ifndef lint
33 static char copyright[] =
34 "@(#) Copyright (c) 1988, 1993\n\
35 	The Regents of the University of California.  All rights reserved.\n";
36 #endif /* not lint */
37 
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)morse.c	8.1 (Berkeley) 5/31/93";
41 #else
42 static char rcsid[] = "$OpenBSD: morse.c,v 1.13 2005/11/07 19:09:33 jmc Exp $";
43 #endif
44 #endif /* not lint */
45 
46 #include <ctype.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 
52 static char
53 	*digit[] = {
54 	"-----",
55 	".----",
56 	"..---",
57 	"...--",
58 	"....-",
59 	".....",
60 	"-....",
61 	"--...",
62 	"---..",
63 	"----.",
64 },
65 	*alph[] = {
66 	".-",
67 	"-...",
68 	"-.-.",
69 	"-..",
70 	".",
71 	"..-.",
72 	"--.",
73 	"....",
74 	"..",
75 	".---",
76 	"-.-",
77 	".-..",
78 	"--",
79 	"-.",
80 	"---",
81 	".--.",
82 	"--.-",
83 	".-.",
84 	"...",
85 	"-",
86 	"..-",
87 	"...-",
88 	".--",
89 	"-..-",
90 	"-.--",
91 	"--..",
92 };
93 
94 struct punc {
95 	char c;
96 	char *morse;
97 } other[] = {
98 	{ ',', "--..--" },
99 	{ '.', ".-.-.-" },
100 	{ '?', "..--.." },
101 	{ '/', "-..-." },
102 	{ '-', "-....-" },
103 	{ ':', "---..." },
104 	{ ';', "-.-.-." },
105 	{ '(', "-.--.-." },	/* When converting from Morse, can't tell */
106 	{ ')', "-.--.-." },	/* '(' and ')' apart                      */
107 	{ '"', ".-..-." },
108 	{ '`', ".-..-." },
109 	{ '\'', ".----." },
110 	{ '+', ".-.-." },	/* AR */
111 	{ '=', "-...-" },	/* BT */
112 	{ '@', "...-.-" },	/* SK */
113 	{ '\0', NULL }
114 };
115 
116 void	morse(int);
117 void	decode(char *);
118 void	show(char *);
119 
120 static int sflag = 0;
121 static int dflag = 0;
122 
123 int
124 main(int argc, char *argv[])
125 {
126 	int ch;
127 	char *p;
128 
129 	while ((ch = getopt(argc, argv, "dsh")) != -1)
130 		switch((char)ch) {
131 		case 'd':
132 			dflag = 1;
133 			break;
134 		case 's':
135 			sflag = 1;
136 			break;
137 		case '?': case 'h':
138 		default:
139 			fprintf(stderr, "usage: morse [-d | -s] [string ...]\n");
140 			exit(1);
141 		}
142 	argc -= optind;
143 	argv += optind;
144 
145 	if (dflag) {
146 		if (*argv) {
147 			do {
148 				decode(*argv);
149 			} while (*++argv);
150 		} else {
151 			char foo[10];	/* All morse chars shorter than this */
152 			int isblank, i;
153 
154 			i = 0;
155 			isblank = 0;
156 			while ((ch = getchar()) != EOF) {
157 				if (ch == '-' || ch == '.') {
158 					foo[i++] = ch;
159 					if (i == 10) {
160 						/* overrun means gibberish--print 'x' and
161 						 * advance */
162 						i = 0;
163 						putchar('x');
164 						while ((ch = getchar()) != EOF &&
165 						    (ch == '.' || ch == '-'))
166 							;
167 						isblank = 1;
168 					}
169 				} else if (i) {
170 					foo[i] = '\0';
171 					decode(foo);
172 					i = 0;
173 					isblank = 0;
174 				} else if (isspace(ch)) {
175 					if (isblank) {
176 						/* print whitespace for each double blank */
177 						putchar(' ');
178 						isblank = 0;
179 					} else
180 						isblank = 1;
181 				}
182 			}
183 		}
184 		putchar('\n');
185 	} else {
186 		if (*argv)
187 			do {
188 				for (p = *argv; *p; ++p)
189 					morse((int)*p);
190 				show("");
191 			} while (*++argv);
192 		else while ((ch = getchar()) != EOF)
193 			morse(ch);
194 		show("...-.-");	/* SK */
195 	}
196 	exit(0);
197 }
198 
199 void
200 morse(int c)
201 {
202 	int i;
203 
204 	if (isalpha(c))
205 		show(alph[c - (isupper(c) ? 'A' : 'a')]);
206 	else if (isdigit(c))
207 		show(digit[c - '0']);
208 	else if (isspace(c))
209 		show("");  /* could show BT for a pause */
210 	else {
211 		i = 0;
212 		while (other[i].c) {
213 			if (other[i].c == c) {
214 				show(other[i].morse);
215 				break;
216 			}
217 			i++;
218 		}
219 	}
220 }
221 
222 void
223 decode(char *s)
224 {
225 	int i;
226 
227 	for (i = 0; i < 10; i++)
228 		if (strcmp(digit[i], s) == 0) {
229 			putchar('0' + i);
230 			return;
231 		}
232 
233 	for (i = 0; i < 26; i++)
234 		if (strcmp(alph[i], s) == 0) {
235 			putchar('A' + i);
236 			return;
237 		}
238 	i = 0;
239 	while (other[i].c) {
240 		if (strcmp(other[i].morse, s) == 0) {
241 			putchar(other[i].c);
242 			return;
243 		}
244 		i++;
245 	}
246 	putchar('x');	/* line noise */
247 }
248 
249 
250 
251 void
252 show(char *s)
253 {
254 	if (sflag)
255 		printf(" %s", s);
256 	else for (; *s; ++s)
257 		printf(" %s", *s == '.' ? "dit" : "daw");
258 	printf("\n");
259 }
260