morse.c revision 54622
12490Sjkh/* 22490Sjkh * Copyright (c) 1988, 1993 32490Sjkh * The Regents of the University of California. All rights reserved. 42490Sjkh * 52490Sjkh * Redistribution and use in source and binary forms, with or without 62490Sjkh * modification, are permitted provided that the following conditions 72490Sjkh * are met: 82490Sjkh * 1. Redistributions of source code must retain the above copyright 92490Sjkh * notice, this list of conditions and the following disclaimer. 102490Sjkh * 2. Redistributions in binary form must reproduce the above copyright 112490Sjkh * notice, this list of conditions and the following disclaimer in the 122490Sjkh * documentation and/or other materials provided with the distribution. 132490Sjkh * 3. All advertising materials mentioning features or use of this software 142490Sjkh * must display the following acknowledgement: 152490Sjkh * This product includes software developed by the University of 162490Sjkh * California, Berkeley and its contributors. 172490Sjkh * 4. Neither the name of the University nor the names of its contributors 182490Sjkh * may be used to endorse or promote products derived from this software 192490Sjkh * without specific prior written permission. 202490Sjkh * 212490Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 222490Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 232490Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 242490Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 252490Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 262490Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 272490Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 282490Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 292490Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 302490Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 312490Sjkh * SUCH DAMAGE. 322490Sjkh */ 332490Sjkh 3410352Sjoerg/* 3510352Sjoerg * Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM) 3610352Sjoerg * <lyndon@orthanc.com> 3710352Sjoerg */ 3810352Sjoerg 392490Sjkh#ifndef lint 4053920Sbillfstatic const char copyright[] = 412490Sjkh"@(#) Copyright (c) 1988, 1993\n\ 422490Sjkh The Regents of the University of California. All rights reserved.\n"; 432490Sjkh#endif /* not lint */ 442490Sjkh 452490Sjkh#ifndef lint 4653920Sbillf#if 0 472490Sjkhstatic char sccsid[] = "@(#)morse.c 8.1 (Berkeley) 5/31/93"; 4853920Sbillf#endif 4953920Sbillfstatic const char rcsid[] = 5053920Sbillf "$FreeBSD: head/games/morse/morse.c 54622 1999-12-15 04:28:10Z billf $"; 512490Sjkh#endif /* not lint */ 522490Sjkh 532490Sjkh#include <stdio.h> 542490Sjkh#include <ctype.h> 5510352Sjoerg#include <locale.h> 5610352Sjoerg#include <stdlib.h> 5735857Sjb#include <string.h> 5854622Sbillf#include <unistd.h> 592490Sjkh 6010352Sjoerg#ifdef SPEAKER 6110352Sjoerg#include <machine/speaker.h> 6210352Sjoerg#include <fcntl.h> 6310352Sjoerg#endif 6410352Sjoerg 6510352Sjoergstruct morsetab { 6610352Sjoerg char inchar; 6710352Sjoerg char *morse; 682490Sjkh}; 692490Sjkh 7054622Sbillfstatic const struct morsetab mtab[] = { 712490Sjkh 7210352Sjoerg /* letters */ 7310352Sjoerg 7454622Sbillf {'a', ".-"}, 7554622Sbillf {'b', "-..."}, 7654622Sbillf {'c', "-.-."}, 7754622Sbillf {'d', "-.."}, 7854622Sbillf {'e', "."}, 7954622Sbillf {'f', "..-."}, 8054622Sbillf {'g', "--."}, 8154622Sbillf {'h', "...."}, 8254622Sbillf {'i', ".."}, 8354622Sbillf {'j', ".---"}, 8454622Sbillf {'k', "-.-"}, 8554622Sbillf {'l', ".-.."}, 8654622Sbillf {'m', "--"}, 8754622Sbillf {'n', "-."}, 8854622Sbillf {'o', "---"}, 8954622Sbillf {'p', ".--."}, 9054622Sbillf {'q', "--.-"}, 9154622Sbillf {'r', ".-."}, 9254622Sbillf {'s', "..."}, 9354622Sbillf {'t', "-"}, 9454622Sbillf {'u', "..-"}, 9554622Sbillf {'v', "...-"}, 9654622Sbillf {'w', ".--"}, 9754622Sbillf {'x', "-..-"}, 9854622Sbillf {'y', "-.--"}, 9954622Sbillf {'z', "--.."}, 10010352Sjoerg 10110352Sjoerg /* digits */ 10210352Sjoerg 10354622Sbillf {'0', "-----"}, 10454622Sbillf {'1', ".----"}, 10554622Sbillf {'2', "..---"}, 10654622Sbillf {'3', "...--"}, 10754622Sbillf {'4', "....-"}, 10854622Sbillf {'5', "....."}, 10954622Sbillf {'6', "-...."}, 11054622Sbillf {'7', "--..."}, 11154622Sbillf {'8', "---.."}, 11254622Sbillf {'9', "----."}, 11310352Sjoerg 11410352Sjoerg /* punctuation */ 11510352Sjoerg 11654622Sbillf {',', "--..--"}, 11754622Sbillf {'.', ".-.-.-"}, 11854622Sbillf {'?', "..--.."}, 11954622Sbillf {'/', "-..-."}, 12054622Sbillf {'-', "-....-"}, 12154622Sbillf {'=', "-...-"}, /* BT */ 12254622Sbillf {':', "---..."}, 12354622Sbillf {';', "-.-.-."}, 12454622Sbillf {'(', "-.--."}, /* KN */ 12554622Sbillf {')', "-.--.-"}, 12654622Sbillf {'$', "...-..-"}, 12754622Sbillf {'+', ".-.-."}, /* AR */ 12810352Sjoerg 12910352Sjoerg /* prosigns without already assigned values */ 13010352Sjoerg 13154622Sbillf {'#', ".-..."}, /* AS */ 13254622Sbillf {'@', "...-.-"}, /* SK */ 13354622Sbillf {'*', "...-."}, /* VE */ 13454622Sbillf {'%', "-...-.-"}, /* BK */ 13510352Sjoerg 13654622Sbillf {'\0', ""} 13710352Sjoerg}; 13810352Sjoerg 13910352Sjoerg 14054622Sbillfstatic const struct morsetab iso8859tab[] = { 14154622Sbillf {'�', ".--.-"}, 14254622Sbillf {'�', ".--.-"}, 14354622Sbillf {'�', ".--.-"}, 14454622Sbillf {'�', ".-.-"}, 14554622Sbillf {'�', "-.-.."}, 14654622Sbillf {'�', "..-.."}, 14754622Sbillf {'�', "..-.."}, 14854622Sbillf {'�', "-..-."}, 14954622Sbillf {'�', "---."}, 15054622Sbillf {'�', "..--"}, 15110352Sjoerg 15254622Sbillf {'\0', ""} 15310352Sjoerg}; 15410352Sjoerg 15554622Sbillfstatic const struct morsetab koi8rtab[] = { 15610352Sjoerg /* 15710352Sjoerg * the cyrillic alphabet; you'll need a KOI8R font in order 15810352Sjoerg * to see the actual characters 15910352Sjoerg */ 16054622Sbillf {'�', ".-"}, /* a */ 16154622Sbillf {'�', "-..."}, /* be */ 16254622Sbillf {'�', ".--"}, /* ve */ 16354622Sbillf {'�', "--."}, /* ge */ 16454622Sbillf {'�', "-.."}, /* de */ 16554622Sbillf {'�', "."}, /* ye */ 16654622Sbillf {'�', "."}, /* yo, the same as ye */ 16754622Sbillf {'�', "...-"}, /* she */ 16854622Sbillf {'�', "--.."}, /* ze */ 16954622Sbillf {'�', ".."}, /* i */ 17054622Sbillf {'�', ".---"}, /* i kratkoye */ 17154622Sbillf {'�', "-.-"}, /* ka */ 17254622Sbillf {'�', ".-.."}, /* el */ 17354622Sbillf {'�', "--"}, /* em */ 17454622Sbillf {'�', "-."}, /* en */ 17554622Sbillf {'�', "---"}, /* o */ 17654622Sbillf {'�', ".--."}, /* pe */ 17754622Sbillf {'�', ".-."}, /* er */ 17854622Sbillf {'�', "..."}, /* es */ 17954622Sbillf {'�', "-"}, /* te */ 18054622Sbillf {'�', "..-"}, /* u */ 18154622Sbillf {'�', "..-."}, /* ef */ 18254622Sbillf {'�', "...."}, /* kha */ 18354622Sbillf {'�', "-.-."}, /* ce */ 18454622Sbillf {'�', "---."}, /* che */ 18554622Sbillf {'�', "----"}, /* sha */ 18654622Sbillf {'�', "--.-"}, /* shcha */ 18754622Sbillf {'�', "-.--"}, /* yi */ 18854622Sbillf {'�', "-..-"}, /* myakhkij znak */ 18954622Sbillf {'�', "..-.."}, /* ae */ 19054622Sbillf {'�', "..--"}, /* yu */ 19154622Sbillf {'�', ".-.-"}, /* ya */ 19210352Sjoerg 19354622Sbillf {'\0', ""} 19410352Sjoerg}; 19510352Sjoerg 19610352Sjoergvoid show(const char *), play(const char *), morse(char); 19710352Sjoerg 19810352Sjoergstatic int pflag, sflag; 19910352Sjoergstatic int wpm = 20; /* words per minute */ 20010352Sjoerg#define FREQUENCY 600 20110352Sjoergstatic int freq = FREQUENCY; 20210352Sjoerg 20310352Sjoerg#ifdef SPEAKER 20410352Sjoerg#define DASH_LEN 3 20510352Sjoerg#define CHAR_SPACE 3 20610352Sjoerg#define WORD_SPACE (7 - CHAR_SPACE - 1) 20710352Sjoergstatic float dot_clock; 20810352Sjoergint spkr; 20910352Sjoergtone_t sound; 21010352Sjoerg#endif 21110352Sjoerg 21254622Sbillfstatic const struct morsetab *hightab = iso8859tab; 21310352Sjoerg 21410352Sjoergint 21510352Sjoergmain(int argc, char **argv) 2162490Sjkh{ 21753210Sbillf int ch; 21853210Sbillf char *p; 2192490Sjkh 22033937Sjkh while ((ch = getopt(argc, argv, "spw:f:")) != -1) 22110352Sjoerg switch ((char) ch) { 22210352Sjoerg case 'f': 22310352Sjoerg freq = atoi(optarg); 22410352Sjoerg break; 22510352Sjoerg case 'p': 22610352Sjoerg pflag = 1; 22710352Sjoerg break; 2282490Sjkh case 's': 2292490Sjkh sflag = 1; 2302490Sjkh break; 23110352Sjoerg case 'w': 23210352Sjoerg wpm = atoi(optarg); 23310352Sjoerg break; 2342490Sjkh case '?': 2352490Sjkh default: 23610352Sjoerg fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr); 2372490Sjkh exit(1); 2382490Sjkh } 23910352Sjoerg if (pflag && sflag) { 24010352Sjoerg fputs("morse: only one of -p and -s allowed\n", stderr); 24110352Sjoerg exit(1); 24210352Sjoerg } 24310352Sjoerg if (pflag && ((wpm < 1) || (wpm > 60))) { 24410352Sjoerg fputs("morse: insane speed\n", stderr); 24510352Sjoerg exit(1); 24610352Sjoerg } 24710352Sjoerg if (pflag && (freq == 0)) 24810352Sjoerg freq = FREQUENCY; 24910352Sjoerg 25010352Sjoerg#ifdef SPEAKER 25110352Sjoerg if (pflag) { 25210352Sjoerg if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) { 25310352Sjoerg perror(SPEAKER); 25410352Sjoerg exit(1); 25510352Sjoerg } 25610352Sjoerg dot_clock = wpm / 2.4; /* dots/sec */ 25710352Sjoerg dot_clock = 1 / dot_clock; /* duration of a dot */ 25810352Sjoerg dot_clock = dot_clock / 2; /* dot_clock runs at twice */ 25910352Sjoerg /* the dot rate */ 26010352Sjoerg dot_clock = dot_clock * 100; /* scale for ioctl */ 26110352Sjoerg } 26210352Sjoerg#endif 2632490Sjkh argc -= optind; 2642490Sjkh argv += optind; 2652490Sjkh 26629018Sache if((p = getenv("LC_CTYPE")) || 26729018Sache (p = getenv("LC_ALL")) || 26829018Sache (p = getenv("LANG"))) { 26929018Sache if(strlen(p) >= sizeof(".KOI8-R") && 27029018Sache strcasecmp(&p[strlen(p) + 1 - sizeof(".KOI8-R")], ".KOI8-R") == 0) 27110352Sjoerg hightab = koi8rtab; 27210352Sjoerg } 27329018Sache (void) setlocale(LC_CTYPE, ""); 27410352Sjoerg 27510352Sjoerg if (*argv) { 2762490Sjkh do { 27710352Sjoerg for (p = *argv; *p; ++p) { 27829018Sache morse(*p); 27910352Sjoerg } 28029018Sache morse(' '); 2812490Sjkh } while (*++argv); 28210352Sjoerg } else { 28310352Sjoerg while ((ch = getchar()) != EOF) 28410352Sjoerg morse(ch); 28510352Sjoerg } 28610352Sjoerg exit(0); 2872490Sjkh} 2882490Sjkh 28910352Sjoergvoid 29010352Sjoergmorse(char c) 2912490Sjkh{ 29254622Sbillf const struct morsetab *m; 29310352Sjoerg 29429018Sache if (isalpha((unsigned char)c)) 29529018Sache c = tolower((unsigned char)c); 29610352Sjoerg if ((c == '\r') || (c == '\n')) 29710352Sjoerg c = ' '; 29810352Sjoerg if (c == ' ') { 29910352Sjoerg if (pflag) { 30010352Sjoerg play(" "); 30110352Sjoerg return; 30210352Sjoerg } else { 30310352Sjoerg show(""); 30410352Sjoerg return; 30510352Sjoerg } 30610352Sjoerg } 30710352Sjoerg for (m = ((unsigned char)c < 0x80? mtab: hightab); 30810352Sjoerg m->inchar != '\0'; 30910352Sjoerg m++) { 31010352Sjoerg if (m->inchar == c) { 31110352Sjoerg if (pflag) { 31210352Sjoerg play(m->morse); 31310352Sjoerg } else 31410352Sjoerg show(m->morse); 31510352Sjoerg } 31610352Sjoerg } 3172490Sjkh} 3182490Sjkh 31910352Sjoergvoid 32010352Sjoergshow(const char *s) 3212490Sjkh{ 3222490Sjkh if (sflag) 3232490Sjkh printf(" %s", s); 32410352Sjoerg else 32510352Sjoerg for (; *s; ++s) 32610352Sjoerg printf(" %s", *s == '.' ? "dit" : "dah"); 32710352Sjoerg printf("\n"); 3282490Sjkh} 32910352Sjoerg 33010352Sjoergvoid 33110352Sjoergplay(const char *s) 33210352Sjoerg{ 33310352Sjoerg#ifdef SPEAKER 33410352Sjoerg const char *c; 33510352Sjoerg 33610352Sjoerg for (c = s; *c != '\0'; c++) { 33729018Sache switch (*c) { 33810352Sjoerg case '.': 33910352Sjoerg sound.frequency = freq; 34010352Sjoerg sound.duration = dot_clock; 34110352Sjoerg break; 34210352Sjoerg case '-': 34310352Sjoerg sound.frequency = freq; 34410352Sjoerg sound.duration = dot_clock * DASH_LEN; 34510352Sjoerg break; 34610352Sjoerg case ' ': 34710352Sjoerg sound.frequency = 0; 34810352Sjoerg sound.duration = dot_clock * WORD_SPACE; 34910352Sjoerg break; 35010352Sjoerg default: 35110352Sjoerg sound.duration = 0; 35210352Sjoerg } 35310352Sjoerg if (sound.duration) { 35410352Sjoerg if (ioctl(spkr, SPKRTONE, &sound) == -1) { 35510352Sjoerg perror("ioctl play"); 35610352Sjoerg exit(1); 35710352Sjoerg } 35810352Sjoerg } 35910352Sjoerg sound.frequency = 0; 36010352Sjoerg sound.duration = dot_clock; 36110352Sjoerg if (ioctl(spkr, SPKRTONE, &sound) == -1) { 36210352Sjoerg perror("ioctl rest"); 36310352Sjoerg exit(1); 36410352Sjoerg } 36510352Sjoerg } 36610352Sjoerg sound.frequency = 0; 36710352Sjoerg sound.duration = dot_clock * CHAR_SPACE; 36810352Sjoerg ioctl(spkr, SPKRTONE, &sound); 36910352Sjoerg#endif 37010352Sjoerg} 371