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