Statistics
| Revision:

gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / console / dis.py @ 462

History | View | Annotate | Download (8.86 KB)

1
"""Disassembler of Python byte code into mnemonics."""
2

    
3
import sys
4
import types
5

    
6
__all__ = ["dis","disassemble","distb","disco","opname","cmp_op",
7
           "hasconst","hasname","hasjrel","hasjabs","haslocal",
8
           "hascompare", "hasfree"]
9

    
10
def dis(x=None):
11
    """Disassemble classes, methods, functions, or code.
12

13
    With no argument, disassemble the last traceback.
14

15
    """
16
    if not x:
17
        distb()
18
        return
19
    if type(x) is types.InstanceType:
20
        x = x.__class__
21
    if hasattr(x, 'im_func'):
22
        x = x.im_func
23
    if hasattr(x, 'func_code'):
24
        x = x.func_code
25
    if hasattr(x, '__dict__'):
26
        items = x.__dict__.items()
27
        items.sort()
28
        for name, x1 in items:
29
            if type(x1) in (types.MethodType,
30
                            types.FunctionType,
31
                            types.CodeType):
32
                print "Disassembly of %s:" % name
33
                try:
34
                    dis(x1)
35
                except TypeError, msg:
36
                    print "Sorry:", msg
37
                print
38
    elif hasattr(x, 'co_code'):
39
        disassemble(x)
40
    else:
41
        raise TypeError, \
42
              "don't know how to disassemble %s objects" % \
43
              type(x).__name__
44

    
45
def distb(tb=None):
46
    """Disassemble a traceback (default: last traceback)."""
47
    if not tb:
48
        try:
49
            tb = sys.last_traceback
50
        except AttributeError:
51
            raise RuntimeError, "no last traceback to disassemble"
52
        while tb.tb_next: tb = tb.tb_next
53
    disassemble(tb.tb_frame.f_code, tb.tb_lasti)
54

    
55
def disassemble(co, lasti=-1):
56
    """Disassemble a code object."""
57
    code = co.co_code
58
    labels = findlabels(code)
59
    n = len(code)
60
    i = 0
61
    extended_arg = 0
62
    free = None
63
    while i < n:
64
        c = code[i]
65
        op = ord(c)
66
        if op == SET_LINENO and i > 0: print # Extra blank line
67
        if i == lasti: print '-->',
68
        else: print '   ',
69
        if i in labels: print '>>',
70
        else: print '  ',
71
        print `i`.rjust(4),
72
        print opname[op].ljust(20),
73
        i = i+1
74
        if op >= HAVE_ARGUMENT:
75
            oparg = ord(code[i]) + ord(code[i+1])*256 + extended_arg
76
            extended_arg = 0
77
            i = i+2
78
            if op == EXTENDED_ARG:
79
                extended_arg = oparg*65536L
80
            print `oparg`.rjust(5),
81
            if op in hasconst:
82
                print '(' + `co.co_consts[oparg]` + ')',
83
            elif op in hasname:
84
                print '(' + co.co_names[oparg] + ')',
85
            elif op in hasjrel:
86
                print '(to ' + `i + oparg` + ')',
87
            elif op in haslocal:
88
                print '(' + co.co_varnames[oparg] + ')',
89
            elif op in hascompare:
90
                print '(' + cmp_op[oparg] + ')',
91
            elif op in hasfree:
92
                if free is None:
93
                    free = co.co_cellvars + co.co_freevars
94
                print '(' + free[oparg] + ')',
95
        print
96

    
97
disco = disassemble                     # XXX For backwards compatibility
98

    
99
def findlabels(code):
100
    """Detect all offsets in a byte code which are jump targets.
101

102
    Return the list of offsets.
103

104
    """
105
    labels = []
106
    n = len(code)
107
    i = 0
108
    while i < n:
109
        c = code[i]
110
        op = ord(c)
111
        i = i+1
112
        if op >= HAVE_ARGUMENT:
113
            oparg = ord(code[i]) + ord(code[i+1])*256
114
            i = i+2
115
            label = -1
116
            if op in hasjrel:
117
                label = i+oparg
118
            elif op in hasjabs:
119
                label = oparg
120
            if label >= 0:
121
                if label not in labels:
122
                    labels.append(label)
123
    return labels
124

    
125
cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
126
        'is not', 'exception match', 'BAD')
127

    
128
hasconst = []
129
hasname = []
130
hasjrel = []
131
hasjabs = []
132
haslocal = []
133
hascompare = []
134
hasfree = []
135

    
136
opname = [''] * 256
137
for op in range(256): opname[op] = '<' + `op` + '>'
138

    
139
def def_op(name, op):
140
    opname[op] = name
141

    
142
def name_op(name, op):
143
    opname[op] = name
144
    hasname.append(op)
145

    
146
def jrel_op(name, op):
147
    opname[op] = name
148
    hasjrel.append(op)
149

    
150
def jabs_op(name, op):
151
    opname[op] = name
152
    hasjabs.append(op)
153

    
154
# Instruction opcodes for compiled code
155

    
156
def_op('STOP_CODE', 0)
157
def_op('POP_TOP', 1)
158
def_op('ROT_TWO', 2)
159
def_op('ROT_THREE', 3)
160
def_op('DUP_TOP', 4)
161
def_op('ROT_FOUR', 5)
162

    
163
def_op('UNARY_POSITIVE', 10)
164
def_op('UNARY_NEGATIVE', 11)
165
def_op('UNARY_NOT', 12)
166
def_op('UNARY_CONVERT', 13)
167

    
168
def_op('UNARY_INVERT', 15)
169

    
170
def_op('BINARY_POWER', 19)
171

    
172
def_op('BINARY_MULTIPLY', 20)
173
def_op('BINARY_DIVIDE', 21)
174
def_op('BINARY_MODULO', 22)
175
def_op('BINARY_ADD', 23)
176
def_op('BINARY_SUBTRACT', 24)
177
def_op('BINARY_SUBSCR', 25)
178
def_op('BINARY_FLOOR_DIVIDE', 26)
179
def_op('BINARY_TRUE_DIVIDE', 27)
180
def_op('INPLACE_FLOOR_DIVIDE', 28)
181
def_op('INPLACE_TRUE_DIVIDE', 29)
182

    
183
def_op('SLICE+0', 30)
184
def_op('SLICE+1', 31)
185
def_op('SLICE+2', 32)
186
def_op('SLICE+3', 33)
187

    
188
def_op('STORE_SLICE+0', 40)
189
def_op('STORE_SLICE+1', 41)
190
def_op('STORE_SLICE+2', 42)
191
def_op('STORE_SLICE+3', 43)
192

    
193
def_op('DELETE_SLICE+0', 50)
194
def_op('DELETE_SLICE+1', 51)
195
def_op('DELETE_SLICE+2', 52)
196
def_op('DELETE_SLICE+3', 53)
197

    
198
def_op('INPLACE_ADD', 55)
199
def_op('INPLACE_SUBTRACT', 56)
200
def_op('INPLACE_MULTIPLY', 57)
201
def_op('INPLACE_DIVIDE', 58)
202
def_op('INPLACE_MODULO', 59)
203
def_op('STORE_SUBSCR', 60)
204
def_op('DELETE_SUBSCR', 61)
205

    
206
def_op('BINARY_LSHIFT', 62)
207
def_op('BINARY_RSHIFT', 63)
208
def_op('BINARY_AND', 64)
209
def_op('BINARY_XOR', 65)
210
def_op('BINARY_OR', 66)
211
def_op('INPLACE_POWER', 67)
212
def_op('GET_ITER', 68)
213

    
214
def_op('PRINT_EXPR', 70)
215
def_op('PRINT_ITEM', 71)
216
def_op('PRINT_NEWLINE', 72)
217
def_op('PRINT_ITEM_TO', 73)
218
def_op('PRINT_NEWLINE_TO', 74)
219
def_op('INPLACE_LSHIFT', 75)
220
def_op('INPLACE_RSHIFT', 76)
221
def_op('INPLACE_AND', 77)
222
def_op('INPLACE_XOR', 78)
223
def_op('INPLACE_OR', 79)
224
def_op('BREAK_LOOP', 80)
225

    
226
def_op('LOAD_LOCALS', 82)
227
def_op('RETURN_VALUE', 83)
228
def_op('IMPORT_STAR', 84)
229
def_op('EXEC_STMT', 85)
230
def_op('YIELD_STMT', 86)
231

    
232
def_op('POP_BLOCK', 87)
233
def_op('END_FINALLY', 88)
234
def_op('BUILD_CLASS', 89)
235

    
236
HAVE_ARGUMENT = 90              # Opcodes from here have an argument:
237

    
238
name_op('STORE_NAME', 90)       # Index in name list
239
name_op('DELETE_NAME', 91)      # ""
240
def_op('UNPACK_SEQUENCE', 92)   # Number of tuple items
241
jrel_op('FOR_ITER', 93)
242

    
243
name_op('STORE_ATTR', 95)       # Index in name list
244
name_op('DELETE_ATTR', 96)      # ""
245
name_op('STORE_GLOBAL', 97)     # ""
246
name_op('DELETE_GLOBAL', 98)    # ""
247
def_op('DUP_TOPX', 99)          # number of items to duplicate
248
def_op('LOAD_CONST', 100)       # Index in const list
249
hasconst.append(100)
250
name_op('LOAD_NAME', 101)       # Index in name list
251
def_op('BUILD_TUPLE', 102)      # Number of tuple items
252
def_op('BUILD_LIST', 103)       # Number of list items
253
def_op('BUILD_MAP', 104)        # Always zero for now
254
name_op('LOAD_ATTR', 105)       # Index in name list
255
def_op('COMPARE_OP', 106)       # Comparison operator
256
hascompare.append(106)
257
name_op('IMPORT_NAME', 107)     # Index in name list
258
name_op('IMPORT_FROM', 108)     # Index in name list
259

    
260
jrel_op('JUMP_FORWARD', 110)    # Number of bytes to skip
261
jrel_op('JUMP_IF_FALSE', 111)   # ""
262
jrel_op('JUMP_IF_TRUE', 112)    # ""
263
jabs_op('JUMP_ABSOLUTE', 113)   # Target byte offset from beginning of code
264
jrel_op('FOR_LOOP', 114)        # Number of bytes to skip
265

    
266
name_op('LOAD_GLOBAL', 116)     # Index in name list
267

    
268
jabs_op('CONTINUE_LOOP', 119)   # Target address
269
jrel_op('SETUP_LOOP', 120)      # Distance to target address
270
jrel_op('SETUP_EXCEPT', 121)    # ""
271
jrel_op('SETUP_FINALLY', 122)   # ""
272

    
273
def_op('LOAD_FAST', 124)        # Local variable number
274
haslocal.append(124)
275
def_op('STORE_FAST', 125)       # Local variable number
276
haslocal.append(125)
277
def_op('DELETE_FAST', 126)      # Local variable number
278
haslocal.append(126)
279

    
280
def_op('SET_LINENO', 127)       # Current line number
281
SET_LINENO = 127
282

    
283
def_op('RAISE_VARARGS', 130)    # Number of raise arguments (1, 2, or 3)
284
def_op('CALL_FUNCTION', 131)    # #args + (#kwargs << 8)
285
def_op('MAKE_FUNCTION', 132)    # Number of args with default values
286
def_op('BUILD_SLICE', 133)      # Number of items
287

    
288
def_op('MAKE_CLOSURE', 134)
289
def_op('LOAD_CLOSURE', 135)
290
hasfree.append(135)
291
def_op('LOAD_DEREF', 136)
292
hasfree.append(136)
293
def_op('STORE_DEREF', 137)
294
hasfree.append(137)
295

    
296
def_op('CALL_FUNCTION_VAR', 140)     # #args + (#kwargs << 8)
297
def_op('CALL_FUNCTION_KW', 141)      # #args + (#kwargs << 8)
298
def_op('CALL_FUNCTION_VAR_KW', 142)  # #args + (#kwargs << 8)
299

    
300
def_op('EXTENDED_ARG', 143)
301
EXTENDED_ARG = 143
302

    
303
def _test():
304
    """Simple test program to disassemble a file."""
305
    if sys.argv[1:]:
306
        if sys.argv[2:]:
307
            sys.stderr.write("usage: python dis.py [-|file]\n")
308
            sys.exit(2)
309
        fn = sys.argv[1]
310
        if not fn or fn == "-":
311
            fn = None
312
    else:
313
        fn = None
314
    if not fn:
315
        f = sys.stdin
316
    else:
317
        f = open(fn)
318
    source = f.read()
319
    if fn:
320
        f.close()
321
    else:
322
        fn = "<stdin>"
323
    code = compile(source, fn, "exec")
324
    dis(code)
325

    
326
if __name__ == "__main__":
327
    _test()