summaryrefslogtreecommitdiff
path: root/dumpbits.py
blob: a30afde427bd9a486c44d49764d9d6da8900b32e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/env python3
import sys, re, traceback
from argparse import ArgumentParser

def convert(s):
    if s.lower().startswith('0x'):
        return int(s, 16)
    elif s.lower().startswith('0b'):
        return int(s, 2)
    else:
        return int(s)

class Table:
    def __init__(self, value, numbers):
        self.value = value
        self.numbers = numbers

    def print(self):
        self.print_border()
        self.print_numbers()
        self.print_border()
        self.print_bits()
        self.print_border()

    def print_border(self):
        total_w = 4 * len(self.numbers) + 2
        for i in range(total_w):
            c = '+' if i == 0 or i == total_w-1 else '-'
            print(c, end='')
        print()

    def print_numbers(self):
        print('|', end='')
        for n in reversed(self.numbers):
            print(' %s ' % (str(n).rjust(2)), end='')
        print('|')

    def print_bits(self):
        print('|', end='')
        for n in reversed(self.numbers):
            b = (self.value >> n) & 1
            print(' %s ' % (str(b).rjust(2)), end='')
        print('|')

def main():
    parser = ArgumentParser(description='inspect values by bits')
    parser.add_argument('-s', '--size', type=int, default=32, choices=(4, 8, 16, 32, 64),
                        help='size')
    parser.add_argument('-r', '--range',
                        help='range (e.g. 31:28), numbers are inclusive')
    parser.add_argument('value')
    args = parser.parse_args()

    value = convert(args.value)

    if value.bit_length() > args.size:
        raise Exception('bit length of %s is %d which is larger than specified size %d'
                         % (args.value, value.bit_length(), args.size))

    if args.range:
        r = re.search('^(\d+):(\d+)$', args.range)
        if not r:
            raise Exception('invalid range specified')

        r_to = int(r.group(2))
        r_from = int(r.group(1))

        if r_to < 0 or r_from < 0 or r_to >= args.size or r_from >= args.size:
            raise Exception('specified range is out of bounds')
    else:
        r_to = 0
        r_from = args.size - 1

    numbers = range(r_to, r_from + 1)

    table = Table(value, numbers)
    table.print()

    print()
    print('  Input: %s' % args.value)
    print(' Binary: %s' % bin(value)[2:])
    print('Decimal: %d' % value)
    print('    Hex: %s' % hex(value)[2:])
    print()

    if args.range:
        new_value = value >> r_to
        mask = (2 ** (r_from - r_to + 1) - 1)
        new_value &= mask

        print('         [%d:%d]' % (r_from, r_to))
        print(' Binary: %s' % bin(new_value)[2:])
        print('Decimal: %d' % new_value)
        print('    Hex: %s' % hex(new_value)[2:])

if __name__ == '__main__':
    try:
        main()
    except Exception as e:
        print("error: %s" % str(e))
        traceback.print_tb(e.__traceback__)