morse.c revision 35857
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
402490Sjkhstatic 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
462490Sjkhstatic char sccsid[] = "@(#)morse.c	8.1 (Berkeley) 5/31/93";
472490Sjkh#endif /* not lint */
482490Sjkh
492490Sjkh#include <stdio.h>
502490Sjkh#include <ctype.h>
5110352Sjoerg#include <locale.h>
5210352Sjoerg#include <stdlib.h>
5335857Sjb#include <string.h>
542490Sjkh
5510352Sjoerg#ifdef SPEAKER
5610352Sjoerg#include <machine/speaker.h>
5710352Sjoerg#include <fcntl.h>
5810352Sjoerg#endif
5910352Sjoerg
6010352Sjoergstruct morsetab {
6110352Sjoerg	char            inchar;
6210352Sjoerg	char           *morse;
632490Sjkh};
642490Sjkh
6510352Sjoergstatic struct morsetab mtab[] = {
662490Sjkh
6710352Sjoerg	/* letters */
6810352Sjoerg
6910352Sjoerg	'a', ".-",
7010352Sjoerg	'b', "-...",
7110352Sjoerg	'c', "-.-.",
7210352Sjoerg	'd', "-..",
7310352Sjoerg	'e', ".",
7410352Sjoerg	'f', "..-.",
7510352Sjoerg	'g', "--.",
7610352Sjoerg	'h', "....",
7710352Sjoerg	'i', "..",
7810352Sjoerg	'j', ".---",
7910352Sjoerg	'k', "-.-",
8010352Sjoerg	'l', ".-..",
8110352Sjoerg	'm', "--",
8210352Sjoerg	'n', "-.",
8310352Sjoerg	'o', "---",
8410352Sjoerg	'p', ".--.",
8510352Sjoerg	'q', "--.-",
8610352Sjoerg	'r', ".-.",
8710352Sjoerg	's', "...",
8810352Sjoerg	't', "-",
8910352Sjoerg	'u', "..-",
9010352Sjoerg	'v', "...-",
9110352Sjoerg	'w', ".--",
9210352Sjoerg	'x', "-..-",
9310352Sjoerg	'y', "-.--",
9410352Sjoerg	'z', "--..",
9510352Sjoerg
9610352Sjoerg	/* digits */
9710352Sjoerg
9810352Sjoerg	'0', "-----",
9910352Sjoerg	'1', ".----",
10010352Sjoerg	'2', "..---",
10110352Sjoerg	'3', "...--",
10210352Sjoerg	'4', "....-",
10310352Sjoerg	'5', ".....",
10410352Sjoerg	'6', "-....",
10510352Sjoerg	'7', "--...",
10610352Sjoerg	'8', "---..",
10710352Sjoerg	'9', "----.",
10810352Sjoerg
10910352Sjoerg	/* punctuation */
11010352Sjoerg
11110352Sjoerg	',', "--..--",
11210352Sjoerg	'.', ".-.-.-",
11310352Sjoerg	'?', "..--..",
11410352Sjoerg	'/', "-..-.",
11510352Sjoerg	'-', "-....-",
11610352Sjoerg	'=', "-...-",		/* BT */
11710352Sjoerg	':', "---...",
11810352Sjoerg	';', "-.-.-.",
11910352Sjoerg	'(', "-.--.",		/* KN */
12010352Sjoerg	')', "-.--.-",
12110352Sjoerg	'$', "...-..-",
12210352Sjoerg	'+', ".-.-.",		/* AR */
12310352Sjoerg
12410352Sjoerg	/* prosigns without already assigned values */
12510352Sjoerg
12610352Sjoerg	'#', ".-...",		/* AS */
12710352Sjoerg	'@', "...-.-",		/* SK */
12810352Sjoerg	'*', "...-.",		/* VE */
12910352Sjoerg	'%', "-...-.-",		/* BK */
13010352Sjoerg
13110352Sjoerg	'\0', ""
13210352Sjoerg};
13310352Sjoerg
13410352Sjoerg
13510352Sjoergstatic struct morsetab iso8859tab[] = {
13610352Sjoerg	'�', ".--.-",
13710352Sjoerg	'�', ".--.-",
13810352Sjoerg	'�', ".--.-",
13910352Sjoerg	'�', ".-.-",
14010352Sjoerg	'�', "-.-..",
14110352Sjoerg	'�', "..-..",
14210352Sjoerg	'�', "..-..",
14310352Sjoerg	'�', "-..-.",
14410352Sjoerg	'�', "---.",
14510352Sjoerg	'�', "..--",
14610352Sjoerg
14710352Sjoerg	'\0', ""
14810352Sjoerg};
14910352Sjoerg
15010352Sjoergstatic struct morsetab koi8rtab[] = {
15110352Sjoerg	/*
15210352Sjoerg	 * the cyrillic alphabet; you'll need a KOI8R font in order
15310352Sjoerg	 * to see the actual characters
15410352Sjoerg	 */
15510352Sjoerg	'�', ".-",		/* a */
15610352Sjoerg	'�', "-...",		/* be */
15710352Sjoerg	'�', ".--",		/* ve */
15810352Sjoerg	'�', "--.",		/* ge */
15910352Sjoerg	'�', "-..",		/* de */
16010352Sjoerg	'�', ".",		/* ye */
16129018Sache	'�', ".",               /* yo, the same as ye */
16210352Sjoerg	'�', "...-",		/* she */
16310352Sjoerg	'�', "--..",		/* ze */
16410352Sjoerg	'�', "..",		/* i */
16510352Sjoerg	'�', ".---",		/* i kratkoye */
16610352Sjoerg	'�', "-.-",		/* ka */
16710352Sjoerg	'�', ".-..",		/* el */
16810352Sjoerg	'�', "--",		/* em */
16910352Sjoerg	'�', "-.",		/* en */
17010352Sjoerg	'�', "---",		/* o */
17110352Sjoerg	'�', ".--.",		/* pe */
17210352Sjoerg	'�', ".-.",		/* er */
17310352Sjoerg	'�', "...",		/* es */
17410352Sjoerg	'�', "-",		/* te */
17510352Sjoerg	'�', "..-",		/* u */
17610352Sjoerg	'�', "..-.",		/* ef */
17710352Sjoerg	'�', "....",		/* kha */
17810352Sjoerg	'�', "-.-.",		/* ce */
17910352Sjoerg	'�', "---.",		/* che */
18010352Sjoerg	'�', "----",		/* sha */
18110352Sjoerg	'�', "--.-",		/* shcha */
18210352Sjoerg	'�', "-.--",		/* yi */
18310352Sjoerg	'�', "-..-",		/* myakhkij znak */
18410352Sjoerg	'�', "..-..",		/* ae */
18510352Sjoerg	'�', "..--",		/* yu */
18610352Sjoerg	'�', ".-.-",		/* ya */
18710352Sjoerg
18810352Sjoerg	'\0', ""
18910352Sjoerg};
19010352Sjoerg
19110352Sjoergvoid            show(const char *), play(const char *), morse(char);
19210352Sjoerg
19310352Sjoergstatic int      pflag, sflag;
19410352Sjoergstatic int      wpm = 20;	/* words per minute */
19510352Sjoerg#define FREQUENCY 600
19610352Sjoergstatic int      freq = FREQUENCY;
19710352Sjoerg
19810352Sjoerg#ifdef SPEAKER
19910352Sjoerg#define DASH_LEN 3
20010352Sjoerg#define CHAR_SPACE 3
20110352Sjoerg#define WORD_SPACE (7 - CHAR_SPACE - 1)
20210352Sjoergstatic float    dot_clock;
20310352Sjoergint             spkr;
20410352Sjoergtone_t          sound;
20510352Sjoerg#endif
20610352Sjoerg
20710352Sjoergstatic struct morsetab *hightab = iso8859tab;
20810352Sjoerg
20910352Sjoergint
21010352Sjoergmain(int argc, char **argv)
2112490Sjkh{
21210352Sjoerg	extern char    *optarg;
21310352Sjoerg	extern int      optind;
21410352Sjoerg	register int    ch;
21510352Sjoerg	register char  *p;
2162490Sjkh
21733937Sjkh	while ((ch = getopt(argc, argv, "spw:f:")) != -1)
21810352Sjoerg		switch ((char) ch) {
21910352Sjoerg		case 'f':
22010352Sjoerg			freq = atoi(optarg);
22110352Sjoerg			break;
22210352Sjoerg		case 'p':
22310352Sjoerg			pflag = 1;
22410352Sjoerg			break;
2252490Sjkh		case 's':
2262490Sjkh			sflag = 1;
2272490Sjkh			break;
22810352Sjoerg		case 'w':
22910352Sjoerg			wpm = atoi(optarg);
23010352Sjoerg			break;
2312490Sjkh		case '?':
2322490Sjkh		default:
23310352Sjoerg			fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr);
2342490Sjkh			exit(1);
2352490Sjkh		}
23610352Sjoerg	if (pflag && sflag) {
23710352Sjoerg		fputs("morse: only one of -p and -s allowed\n", stderr);
23810352Sjoerg		exit(1);
23910352Sjoerg	}
24010352Sjoerg	if (pflag && ((wpm < 1) || (wpm > 60))) {
24110352Sjoerg		fputs("morse: insane speed\n", stderr);
24210352Sjoerg		exit(1);
24310352Sjoerg	}
24410352Sjoerg	if (pflag && (freq == 0))
24510352Sjoerg		freq = FREQUENCY;
24610352Sjoerg
24710352Sjoerg#ifdef SPEAKER
24810352Sjoerg	if (pflag) {
24910352Sjoerg		if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) {
25010352Sjoerg			perror(SPEAKER);
25110352Sjoerg			exit(1);
25210352Sjoerg		}
25310352Sjoerg		dot_clock = wpm / 2.4;		/* dots/sec */
25410352Sjoerg		dot_clock = 1 / dot_clock;	/* duration of a dot */
25510352Sjoerg		dot_clock = dot_clock / 2;	/* dot_clock runs at twice */
25610352Sjoerg						/* the dot rate */
25710352Sjoerg		dot_clock = dot_clock * 100;	/* scale for ioctl */
25810352Sjoerg	}
25910352Sjoerg#endif
2602490Sjkh	argc -= optind;
2612490Sjkh	argv += optind;
2622490Sjkh
26329018Sache	if((p = getenv("LC_CTYPE")) ||
26429018Sache	   (p = getenv("LC_ALL")) ||
26529018Sache	   (p = getenv("LANG"))) {
26629018Sache		if(strlen(p) >= sizeof(".KOI8-R") &&
26729018Sache		   strcasecmp(&p[strlen(p) + 1 - sizeof(".KOI8-R")], ".KOI8-R") == 0)
26810352Sjoerg			hightab = koi8rtab;
26910352Sjoerg	}
27029018Sache	(void) setlocale(LC_CTYPE, "");
27110352Sjoerg
27210352Sjoerg	if (*argv) {
2732490Sjkh		do {
27410352Sjoerg			for (p = *argv; *p; ++p) {
27529018Sache				morse(*p);
27610352Sjoerg			}
27729018Sache			morse(' ');
2782490Sjkh		} while (*++argv);
27910352Sjoerg	} else {
28010352Sjoerg		while ((ch = getchar()) != EOF)
28110352Sjoerg			morse(ch);
28210352Sjoerg	}
28310352Sjoerg	exit(0);
2842490Sjkh}
2852490Sjkh
28610352Sjoergvoid
28710352Sjoergmorse(char c)
2882490Sjkh{
28910352Sjoerg	struct morsetab *m;
29010352Sjoerg
29129018Sache	if (isalpha((unsigned char)c))
29229018Sache		c = tolower((unsigned char)c);
29310352Sjoerg	if ((c == '\r') || (c == '\n'))
29410352Sjoerg		c = ' ';
29510352Sjoerg	if (c == ' ') {
29610352Sjoerg		if (pflag) {
29710352Sjoerg			play(" ");
29810352Sjoerg			return;
29910352Sjoerg		} else {
30010352Sjoerg			show("");
30110352Sjoerg			return;
30210352Sjoerg		}
30310352Sjoerg	}
30410352Sjoerg	for (m = ((unsigned char)c < 0x80? mtab: hightab);
30510352Sjoerg	     m->inchar != '\0';
30610352Sjoerg	     m++) {
30710352Sjoerg		if (m->inchar == c) {
30810352Sjoerg			if (pflag) {
30910352Sjoerg				play(m->morse);
31010352Sjoerg			} else
31110352Sjoerg				show(m->morse);
31210352Sjoerg		}
31310352Sjoerg	}
3142490Sjkh}
3152490Sjkh
31610352Sjoergvoid
31710352Sjoergshow(const char *s)
3182490Sjkh{
3192490Sjkh	if (sflag)
3202490Sjkh		printf(" %s", s);
32110352Sjoerg	else
32210352Sjoerg		for (; *s; ++s)
32310352Sjoerg			printf(" %s", *s == '.' ? "dit" : "dah");
32410352Sjoerg	printf("\n");
3252490Sjkh}
32610352Sjoerg
32710352Sjoergvoid
32810352Sjoergplay(const char *s)
32910352Sjoerg{
33010352Sjoerg#ifdef SPEAKER
33110352Sjoerg	const char *c;
33210352Sjoerg
33310352Sjoerg	for (c = s; *c != '\0'; c++) {
33429018Sache		switch (*c) {
33510352Sjoerg		case '.':
33610352Sjoerg			sound.frequency = freq;
33710352Sjoerg			sound.duration = dot_clock;
33810352Sjoerg			break;
33910352Sjoerg		case '-':
34010352Sjoerg			sound.frequency = freq;
34110352Sjoerg			sound.duration = dot_clock * DASH_LEN;
34210352Sjoerg			break;
34310352Sjoerg		case ' ':
34410352Sjoerg			sound.frequency = 0;
34510352Sjoerg			sound.duration = dot_clock * WORD_SPACE;
34610352Sjoerg			break;
34710352Sjoerg		default:
34810352Sjoerg			sound.duration = 0;
34910352Sjoerg		}
35010352Sjoerg		if (sound.duration) {
35110352Sjoerg			if (ioctl(spkr, SPKRTONE, &sound) == -1) {
35210352Sjoerg				perror("ioctl play");
35310352Sjoerg				exit(1);
35410352Sjoerg			}
35510352Sjoerg		}
35610352Sjoerg		sound.frequency = 0;
35710352Sjoerg		sound.duration = dot_clock;
35810352Sjoerg		if (ioctl(spkr, SPKRTONE, &sound) == -1) {
35910352Sjoerg			perror("ioctl rest");
36010352Sjoerg			exit(1);
36110352Sjoerg		}
36210352Sjoerg	}
36310352Sjoerg	sound.frequency = 0;
36410352Sjoerg	sound.duration = dot_clock * CHAR_SPACE;
36510352Sjoerg	ioctl(spkr, SPKRTONE, &sound);
36610352Sjoerg#endif
36710352Sjoerg}
368