#!/usr/bin/perl

my ($source,$sNr,$destin) = (uc($ARGV[0]),uc($ARGV[1]),uc($ARGV[2]));
my $decimal,$dNr,$sDS,$dDS;

if(defined($ARGV[0])){

   if ($source eq 'H') {
      $sNr = (length($sNr)%2?"0":"").$sNr;
      $decimal = Hex2Dec($sNr);
      $sDS = "Hexidecimal";
   } elsif ($source eq 'HI') {
      $decimal = Hex2Dec(bHex2Hex($sNr));
      $sDS = "Hexidecimal (x86 format)";
   } elsif ($source eq 'D') {
      $decimal = Str2Dec($sNr);
      $sDS = "Unsigned Decimal Integer";
   } elsif ($source eq 'O') {
      $decimal = Oct2Dec($sNr);
      $sDS = "Octal";
   } elsif ($source eq 'B') {
      $decimal = Bin2Dec($sNr);
      $sDS = "Binary";
   } else {
      goto HELP;
   }

   if ($destin eq 'H') {
      $dNr = Dec2Hex($decimal);
      $dDS = "Hexidecimal";
   } elsif ($destin eq 'HI') {
      $dNr = Hex2bHex(Dec2Hex($decimal));
      $dDS = "Hexidecimal (x86 format)";
   } elsif ($destin eq 'D') {
      $dNr = $decimal;
      $dDS = "Unsigned Decimal Integer";
   } elsif ($destin eq 'O') {
      $dNr = Dec2Oct($decimal);
      $dDS = "Octal";
   } elsif ($destin eq 'B') {
      $dNr = Dec2Bin($decimal);
      $dDS = "Binary";
   } else {
      goto HELP;
   }

   $dNr="Error - odd length" if($source eq 'HI' && length($sNr)%2);

   print "\nConversion between number systems\n";
   print "$sDS: $sNr\n";
   print "$dDS: $dNr\n\n";

} else {
   HELP:
   print "Usage: nsconvert [source number system] [number] [destination number system]\n".
         "Convert between number systems ie. from Binary to Decimal.\n\n".
         "  Supported source/destination number systems\n".
         "  h  Hexidecimal\n".
         "  hi Hexidecimal (x86 format) found in disk/memory dumps\n".
         "  d  Unsigned Decimal Integer\n".
         "  o  Unsigned Octal Integer\n".
         "  b  Unsigned Binary Integer\n\n";
}

# End of main body of code

sub Hex2bHex {
   my ($i,$nr,$hn) = (0,uc(shift),"");

   if ($nr=~/^[0-9A-F]+$/) {
      for ($i = 0;$i <= length($nr)-2;$i += 2) {
         $hn = substr($nr,$i,1).substr($nr,$i+1,1).$hn;
      }
   }

   return $hn;
}

sub bHex2Hex {
   return Hex2bHex(shift);
}

sub Dec2Bin {
   my ($i,$nr,$bn) = (0,shift,"");

   for $i(0..31) {
      $bn .= int($nr/(2**(31-$i)))?"1":"0";
      $nr %= (2**(31-$i));
   }
   $bn =~ /[0]*([0-1]*)/;

   return $1;
}

sub Bin2Dec {
   my ($i,$nr,$dn) = (0,shift,0);

   if ($nr =~ /^[0-1]+$/) {
      for $i(0..(length($nr)-1)) {
         $dn += (ord(substr($nr,$i,1))-48)*(2**(length($nr)-1-$i));
      }
   }

   return $dn;
}

sub Dec2Hex {
   my $hn = uc(sprintf("%x",shift));

   return (length($hn)%2?"0":"").$hn;
}

sub Hex2Dec {
   return hex('0x'.shift);
}

sub Oct2Dec {
   my($i,$nr,$dn) = (0,shift,0);

   if ($nr=~/[0-7]+/) {
      for $i(0..(length($nr)-1)) {
         $dn += ord(substr($nr,$i,1))*(8**(length($nr)-$i));
      }
   }

   return $dn;
}

sub Dec2Oct {
   return sprintf("%o",shift);
}

sub Dec2Str {
   return sprintf("%d",shift);
}

sub Str2Dec {
   my ($i,$nr,$dn) = (0,shift,0);

   if ($nr =~ /^\d+$/) {
      for ($i = (length($nr)-1);$i >= 0;$i--) {
         if (substr($nr,$i,1)ge'0'&&substr($nr,$i,1)le'9') {
            $dn += (ord(substr($nr,$i,1))-48)*(10**((length($nr)-1)-$i));
         }
      }
   }

   return $dn;
}

sub identifier {
   my ($dNr,$id) = (shift,"");
   my $i,$tmp;

   if($dNr < (36**2)){
      for $i(0..1) {
         $tmp = int($dNr/(36**(1-$i)));
         if($tmp >= 0 && $tmp <= 9){
            $id.=chr($tmp+48);
         } else {
            $id .= chr($tmp+55);
         }
         $dNr = $dNr%(36**(1-$i));
      }
   }

   return $id;
}