#!/usr/bin/perl
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
#NAME
#  frMorse - convert from Morse Code to text
#
#SYNOPSIS
#  frMorse [file]..
#
#DESCRIPTION
#  Read one or more input files (default: STDIN), looking for embedded  Morse
#  Code.  When found, the Morse Code is converted to text.
#
#  The '/' char may be used as a spacer, with "/ /" used for a  newline.   Or
#  you  can just use spaces and newlines.  If you use both, you'll get double
#  spaces and newlines.
#
#OPTIONS
#
#EXAMPLES
#
#FILES
#
#BUGS
#
#SEE ALSO
#
#AUTHOR
#  John Chambers <jc@trillian.mit.edu> 2005
#  There were lots of Morse-Code converters online, but all of them were part
#  of some bigger package. I couldn't find one that ran standalone. So I just
#  wrote one.  It took less time than the search that failed.
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

$| = 1;
$exitstat = 0;
($P = $0) =~ s".*/"";
$V = $ENV{"V_$P"} || $ENV{"D_$P"} || 1;	# Verbose level.

%C2M = (
	"A" => ".-",
	"B" => "-...",
	"C" => "-.-.",
	"D" => "-..",
	"E" => ".",
	"F" => "..-.",
	"G" => "--.",
	"H" => "....",
	"I" => "..",
	"J" => ".---",
	"K" => "-.-",
	"L" => ".-..",
	"M" => "--",
	"N" => "-.",
	"O" => "---",
	"P" => ".--.",
	"Q" => "--.-",
	"R" => ".-.",
	"S" => "...",
	"T" => "-",
	"U" => "..-",
	"V" => "...-",
	"W" => ".--",
	"X" => "-..-",
	"Y" => "-.--",
	"Z" => "--..",
	"0" => "-----",
	"1" => ".----",
	"2" => "..---",
	"3" => "...--",
	"4" => "....-",
	"5" => ".....",
	"6" => "-....",
	"7" => "--...",
	"8" => "---..",
	"9" => "----.",
	"." => ".-.-.-",
	"," => "--..--",
	"?" => "..--.. ",
);

%M2C = (
	".-" => "A",
	"-..." => "B",
	"-.-." => "C",
	"-.." => "D",
	"." => "E",
	"..-." => "F",
	"--." => "G",
	"...." => "H",
	".." => "I",
	".---" => "J",
	"-.-" => "K",
	".-.." => "L",
	"--" => "M",
	"-." => "N",
	"---" => "O",
	".--." => "P",
	"--.-" => "Q",
	".-." => "R",
	"..." => "S",
	"-" => "T",
	"..-" => "U",
	"...-" => "V",
	".--" => "W",
	"-..-" => "X",
	"-.--" => "Y",
	"--.." => "Z",
	"-----" => "0",
	".----" => "1",
	"..---" => "2",
	"...--" => "3",
	"....-" => "4",
	"....." => "5",
	"-...." => "6",
	"--..." => "7",
	"---.." => "8",
	"----." => "9",
	".-.-.-" => ".",
	"--..--" => ",",
	"..--.. " => "?",
	"/" => " ",
);

for $arg (@ARGV) {
	if (($flag,$opts) = ($arg =~ /^([-+])(.*)$/)) {
	} else {
		++$files;	# Count the file names
		if (open(F,$arg)) {
			&onefile(*F);
		} else {
			print STDERR "$P: Can't read \"$arg\" ($!)\n";
		}
	}
}
unless ($files > 0) {
	&onefile(*STDIN);
}

print "$P: Exit with status $exitstat.\n" if $V>1;
exit $exitstat;

sub onefile { my $F='onefile';
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	local(*FIL) = @_;
	local($in,$out);
	while ($in = <FIL>) {
		$in =~ s/[\r\s]+$//;
		$in = " $in ";
		print "$P: $in\n" if $V>2;
		while (($init,$morse,$in) = ($in =~ m"^ (.*?)([-/.]+)( .*)")) {
			if ($c = $M2C{$morse}) {
				print STDERR "$P: \"$morse\" is '$c'\n" if $V>2;
				if ($morse eq '/') {
					if ($space) {$out .= $init . "\n"}
					      else  {$out .= $init . $c}
					++$space;
				} else {
					$out .= $init . $c;
					$space = 0;
				}
			} else {
				print STDERR "$P: \"$morse\" not known.\n" if $V>1;
				$out .= $init . $morse;
			}
		}
		$out .= $in if $in;
		print "$out\n";
		$out = '';
	}
}
