1"Collection of tools for displaying bit representation of numbers."""
2
3from __future__ import print_function
4
5def binary(n, width=None):
6    """
7    Return a list of (0|1)'s for the binary representation of n where n >= 0.
8    If you specify a width, it must be > 0, otherwise it is ignored.  The list
9    could be padded with 0 bits if width is specified.
10    """
11    l = []
12    if width and width <= 0:
13        width = None
14    while n > 0:
15        l.append(1 if n & 1 else 0)
16        n = n >> 1
17
18    if width:
19        for i in range(width - len(l)):
20            l.append(0)
21
22    l.reverse()
23    return l
24
25
26def twos_complement(n, width):
27    """
28    Return a list of (0|1)'s for the binary representation of a width-bit two's
29    complement numeral system of an integer n which may be negative.
30    """
31    val = 2**(width - 1)
32    if n >= 0:
33        if n > (val - 1):
34            return None
35        # It is safe to represent n with width-bits.
36        return binary(n, width)
37
38    if n < 0:
39        if abs(n) > val:
40            return None
41        # It is safe to represent n (a negative int) with width-bits.
42        return binary(val * 2 - abs(n))
43
44# print binary(0xABCD)
45# [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1]
46# print binary(0x1F, 8)
47# [0, 0, 0, 1, 1, 1, 1, 1]
48# print twos_complement(-5, 4)
49# [1, 0, 1, 1]
50# print twos_complement(7, 4)
51# [0, 1, 1, 1]
52# print binary(7)
53# [1, 1, 1]
54# print twos_complement(-5, 64)
55# [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1]
56
57
58def positions(width):
59    """Helper function returning a list describing the bit positions.
60    Bit positions greater than 99 are truncated to 2 digits, for example,
61    100 -> 00 and 127 -> 27."""
62    return ['{0:2}'.format(i)[-2:] for i in reversed(range(width))]
63
64
65def utob(debugger, command_line, result, dict):
66    """Convert the unsigned integer to print its binary representation.
67    args[0] (mandatory) is the unsigned integer to be converted
68    args[1] (optional) is the bit width of the binary representation
69    args[2] (optional) if specified, turns on verbose printing"""
70    args = command_line.split()
71    try:
72        n = int(args[0], 0)
73        width = None
74        if len(args) > 1:
75            width = int(args[1], 0)
76            if width < 0:
77                width = 0
78    except:
79        print(utob.__doc__)
80        return
81
82    if len(args) > 2:
83        verbose = True
84    else:
85        verbose = False
86
87    bits = binary(n, width)
88    if not bits:
89        print("insufficient width value: %d" % width)
90        return
91    if verbose and width > 0:
92        pos = positions(width)
93        print(' ' + ' '.join(pos))
94    print(' %s' % str(bits))
95
96
97def itob(debugger, command_line, result, dict):
98    """Convert the integer to print its two's complement representation.
99    args[0] (mandatory) is the integer to be converted
100    args[1] (mandatory) is the bit width of the two's complement representation
101    args[2] (optional) if specified, turns on verbose printing"""
102    args = command_line.split()
103    try:
104        n = int(args[0], 0)
105        width = int(args[1], 0)
106        if width < 0:
107            width = 0
108    except:
109        print(itob.__doc__)
110        return
111
112    if len(args) > 2:
113        verbose = True
114    else:
115        verbose = False
116
117    bits = twos_complement(n, width)
118    if not bits:
119        print("insufficient width value: %d" % width)
120        return
121    if verbose and width > 0:
122        pos = positions(width)
123        print(' ' + ' '.join(pos))
124    print(' %s' % str(bits))
125