#!/usr/bin/perl # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # #NAME # deMorse - convert from Morse Code to text # #SYNOPSIS # deMorse [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 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', '.-.-.-' => '.', '--..--' => ',', '..--.. ' => '?', # '/' => ' ', # '.----.' => "'", '-.-.--' => '!', '-..-.' => '/', '-.--.-' => '()', '. ...' => '&', '---...' => ':', '-.-.-.' => ';', '-...-' => '=', '-..-.' => '/', # Fraction bar '-....-' => '-', '..--.-' => '_', '.-..-.' => '"', '.--.-.' => '@', ); for $arg (@ARGV) { if (($flag,$opts) = ($arg =~ /^([-+])(.*)$/)) { # No command-line options now } 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($c,$in,$init,$morse,$out,$space); while ($in = ) { $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 . ' '} ++$space; # Just count spaces } else { if ($space > 0) { $out .= ($space > 1) ? "\n" : ' '; $space = 0; } $out .= $init . $c; } } else { print STDERR "$P: \"$morse\" not known.\n" if $V>1; $out .= $init . $morse; } } $out .= $in if $in; print "$out\n"; $out = ''; } }