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