Skip to content

Instantly share code, notes, and snippets.

@mr-salty
Last active January 2, 2021 05:17
Show Gist options
  • Save mr-salty/c225dadbfd5708f6ef7347b294f56527 to your computer and use it in GitHub Desktop.
Save mr-salty/c225dadbfd5708f6ef7347b294f56527 to your computer and use it in GitHub Desktop.
script to convert numbers/expressions to hex/oct/dec/binary
#! /usr/bin/perl
sub Usage {
$0 =~ s#.*/##g;
die <<EOM;
Usage: $0 [-hodsbn] expr [...]
expr may contain decimal/hex/octal numbers and operators, unless expr
is suffixed with b, in which case it is interpreted as a binary number
and operators are not allowed.
Converts to hex, octal, signed decimal, unsigned decimal, and binary,
and also indicates which bits are set. Flags may be used to turn off
specific conversions:
h = hex, o = oct, d = dec, s = signed dec, b = binary, n = set bits
EOM
}
use Getopt::Std;
Usage() unless (getopts("hodsbn"));
Usage() if ($#ARGV == -1);
foreach $arg (@ARGV) {
if ($arg =~ /^[01]*b$/) {
# convert from binary.
$num = 0;
$idx = 0;
chop $arg;
while ($arg ne "")
{
$bit = chop $arg;
last if (($bit ne "0") && ($bit ne "1"));
$num |= (1 << $idx) if ($bit eq "1");
++$idx;
}
} else {
# TODO this can produce perl error messages on the tty; it might be
# nice to be a little cleaner about it.
$num = eval "$arg";
}
printf "0x%08x ", $num unless $opt_h;
printf "%012o ", $num unless $opt_o;
printf "%10u ", $num unless $opt_d;
printf "%11d ", $num unless $opt_s;
# convert to binary
undef $bits;
for ($i = 31; $i >= 0; --$i) {
if ($num & (1 << $i)) {
$bits .= " $i";
print "1" unless $opt_b;
} else {
print "0" unless $opt_b;
}
}
print "\n";
print "set:$bits\n\n" unless $opt_n;
}
@mr-salty
Copy link
Author

Here's an example... the input can be decimal, hex, octal, binary (with b suffix), or an expression (expressions cannot contain binary)

 $ bits 100 -100 0xfe 0235 0110011b 0x234-100
0x00000064 000000000144        100         100 00000000000000000000000001100100
set: 6 5 2

0xffffffffffffff9c 1777777777777777777634 18446744073709551516        -100 11111111111111111111111110011100
set: 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 4 3 2

0x000000fe 000000000376        254         254 00000000000000000000000011111110
set: 7 6 5 4 3 2 1

0x0000009d 000000000235        157         157 00000000000000000000000010011101
set: 7 4 3 2 0

0x00000033 000000000063         51          51 00000000000000000000000000110011
set: 5 4 1 0

0x000001d0 000000000720        464         464 00000000000000000000000111010000
set: 8 7 6 4

@mr-salty
Copy link
Author

mr-salty commented Jan 2, 2021

TODO: I wrote this a long time ago and it assumes 32 bits, which affects 2 things (see the example for -100 above):

  • binary conversion (and bits set:) only looks at the lowest 32 bits
  • the other conversions do use 64 bits on a 64 bit machine, but it throws off the column widths which were chosen to be wide enough for 32 bit numbers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment