#!/usr/local/bin/perl

use strict;
use warnings;

use Encode;
use Encode::Rad50;

my @cc = map {"<$_>"} qw{nul soh stx etx eot enq ack bel bs ht lf vt ff
    cr so si dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs
    us};
@cc[127 .. 159] = map {"<$_>"} qw{del pad hop bph nbh ind nel ssa esa
    hts htj vts pld plu ri ss2 ss3 dcs pu1 pu2 sts cch mw spa epa sos
    sgci sci csi st osc pm apc};

@ARGV or do {print <<eod; exit};

Re-implementation of the RSX-11 utility cvt, which converted data
among various radices.

usage: cvt data ...

where the data are:
   &xxxx represents a hexadecimal number
   %xxx represents rad50 characters
   "cc represents ASCII characters
   nnnnn. represents a decimal number
   nnnnn represents an octal number.

Copyright 2006 by Thomas R. Wyant, III. All rights reserved.

This script is free software; you can use it, redistribute it
and/or modify it under the same terms as Perl itself.
eod

foreach (@ARGV) {
    my $value = m/^\d+\.$/ ? $_ + 0 :
	m/^[0-7]+$/ ? oct ($_) :
	m/^&([[:xdigit:]]+)$/ ? oct ("0x$1") :
	m/^'(.)$/ ? ord ($1) :
	m/^"(.{1,2})$/ ? unpack ('n', $1) :
	m/^%(.{1,3})$/ ? unpack ('n', encode ('rad50', sprintf '%3s', $1)) :
	do {warn "Invalid input '$_'\n"; next};
    $value &= 0xffff;
    my $oct = sprintf '%o', $value;
    my $hex = sprintf '%X', $value;
    my $chr = join '', map {$cc[ord $_] || $_} split '', pack ('n', $value);
    my $r5 = decode ('rad50', pack 'n', $value);
    $r5 =~ s/^\s+//;
    print "$oct\t$value.\t&$hex\t\"$chr\t%$r5\n";
}
