PyXR

c:\python24\lib \ dis.py



0001 """Disassembler of Python byte code into mnemonics."""
0002 
0003 import sys
0004 import types
0005 
0006 from opcode import *
0007 from opcode import __all__ as _opcodes_all
0008 
0009 __all__ = ["dis","disassemble","distb","disco"] + _opcodes_all
0010 del _opcodes_all
0011 
0012 def dis(x=None):
0013     """Disassemble classes, methods, functions, or code.
0014 
0015     With no argument, disassemble the last traceback.
0016 
0017     """
0018     if x is None:
0019         distb()
0020         return
0021     if type(x) is types.InstanceType:
0022         x = x.__class__
0023     if hasattr(x, 'im_func'):
0024         x = x.im_func
0025     if hasattr(x, 'func_code'):
0026         x = x.func_code
0027     if hasattr(x, '__dict__'):
0028         items = x.__dict__.items()
0029         items.sort()
0030         for name, x1 in items:
0031             if type(x1) in (types.MethodType,
0032                             types.FunctionType,
0033                             types.CodeType,
0034                             types.ClassType):
0035                 print "Disassembly of %s:" % name
0036                 try:
0037                     dis(x1)
0038                 except TypeError, msg:
0039                     print "Sorry:", msg
0040                 print
0041     elif hasattr(x, 'co_code'):
0042         disassemble(x)
0043     elif isinstance(x, str):
0044         disassemble_string(x)
0045     else:
0046         raise TypeError, \
0047               "don't know how to disassemble %s objects" % \
0048               type(x).__name__
0049 
0050 def distb(tb=None):
0051     """Disassemble a traceback (default: last traceback)."""
0052     if tb is None:
0053         try:
0054             tb = sys.last_traceback
0055         except AttributeError:
0056             raise RuntimeError, "no last traceback to disassemble"
0057         while tb.tb_next: tb = tb.tb_next
0058     disassemble(tb.tb_frame.f_code, tb.tb_lasti)
0059 
0060 def disassemble(co, lasti=-1):
0061     """Disassemble a code object."""
0062     code = co.co_code
0063     labels = findlabels(code)
0064     linestarts = dict(findlinestarts(co))
0065     n = len(code)
0066     i = 0
0067     extended_arg = 0
0068     free = None
0069     while i < n:
0070         c = code[i]
0071         op = ord(c)
0072         if i in linestarts:
0073             if i > 0:
0074                 print
0075             print "%3d" % linestarts[i],
0076         else:
0077             print '   ',
0078 
0079         if i == lasti: print '-->',
0080         else: print '   ',
0081         if i in labels: print '>>',
0082         else: print '  ',
0083         print repr(i).rjust(4),
0084         print opname[op].ljust(20),
0085         i = i+1
0086         if op >= HAVE_ARGUMENT:
0087             oparg = ord(code[i]) + ord(code[i+1])*256 + extended_arg
0088             extended_arg = 0
0089             i = i+2
0090             if op == EXTENDED_ARG:
0091                 extended_arg = oparg*65536L
0092             print repr(oparg).rjust(5),
0093             if op in hasconst:
0094                 print '(' + repr(co.co_consts[oparg]) + ')',
0095             elif op in hasname:
0096                 print '(' + co.co_names[oparg] + ')',
0097             elif op in hasjrel:
0098                 print '(to ' + repr(i + oparg) + ')',
0099             elif op in haslocal:
0100                 print '(' + co.co_varnames[oparg] + ')',
0101             elif op in hascompare:
0102                 print '(' + cmp_op[oparg] + ')',
0103             elif op in hasfree:
0104                 if free is None:
0105                     free = co.co_cellvars + co.co_freevars
0106                 print '(' + free[oparg] + ')',
0107         print
0108 
0109 def disassemble_string(code, lasti=-1, varnames=None, names=None,
0110                        constants=None):
0111     labels = findlabels(code)
0112     n = len(code)
0113     i = 0
0114     while i < n:
0115         c = code[i]
0116         op = ord(c)
0117         if i == lasti: print '-->',
0118         else: print '   ',
0119         if i in labels: print '>>',
0120         else: print '  ',
0121         print repr(i).rjust(4),
0122         print opname[op].ljust(15),
0123         i = i+1
0124         if op >= HAVE_ARGUMENT:
0125             oparg = ord(code[i]) + ord(code[i+1])*256
0126             i = i+2
0127             print repr(oparg).rjust(5),
0128             if op in hasconst:
0129                 if constants:
0130                     print '(' + repr(constants[oparg]) + ')',
0131                 else:
0132                     print '(%d)'%oparg,
0133             elif op in hasname:
0134                 if names is not None:
0135                     print '(' + names[oparg] + ')',
0136                 else:
0137                     print '(%d)'%oparg,
0138             elif op in hasjrel:
0139                 print '(to ' + repr(i + oparg) + ')',
0140             elif op in haslocal:
0141                 if varnames:
0142                     print '(' + varnames[oparg] + ')',
0143                 else:
0144                     print '(%d)' % oparg,
0145             elif op in hascompare:
0146                 print '(' + cmp_op[oparg] + ')',
0147         print
0148 
0149 disco = disassemble                     # XXX For backwards compatibility
0150 
0151 def findlabels(code):
0152     """Detect all offsets in a byte code which are jump targets.
0153 
0154     Return the list of offsets.
0155 
0156     """
0157     labels = []
0158     n = len(code)
0159     i = 0
0160     while i < n:
0161         c = code[i]
0162         op = ord(c)
0163         i = i+1
0164         if op >= HAVE_ARGUMENT:
0165             oparg = ord(code[i]) + ord(code[i+1])*256
0166             i = i+2
0167             label = -1
0168             if op in hasjrel:
0169                 label = i+oparg
0170             elif op in hasjabs:
0171                 label = oparg
0172             if label >= 0:
0173                 if label not in labels:
0174                     labels.append(label)
0175     return labels
0176 
0177 def findlinestarts(code):
0178     """Find the offsets in a byte code which are start of lines in the source.
0179 
0180     Generate pairs (offset, lineno) as described in Python/compile.c.
0181 
0182     """
0183     byte_increments = [ord(c) for c in code.co_lnotab[0::2]]
0184     line_increments = [ord(c) for c in code.co_lnotab[1::2]]
0185 
0186     lastlineno = None
0187     lineno = code.co_firstlineno
0188     addr = 0
0189     for byte_incr, line_incr in zip(byte_increments, line_increments):
0190         if byte_incr:
0191             if lineno != lastlineno:
0192                 yield (addr, lineno)
0193                 lastlineno = lineno
0194             addr += byte_incr
0195         lineno += line_incr
0196     if lineno != lastlineno:
0197         yield (addr, lineno)
0198 
0199 def _test():
0200     """Simple test program to disassemble a file."""
0201     if sys.argv[1:]:
0202         if sys.argv[2:]:
0203             sys.stderr.write("usage: python dis.py [-|file]\n")
0204             sys.exit(2)
0205         fn = sys.argv[1]
0206         if not fn or fn == "-":
0207             fn = None
0208     else:
0209         fn = None
0210     if fn is None:
0211         f = sys.stdin
0212     else:
0213         f = open(fn)
0214     source = f.read()
0215     if fn is not None:
0216         f.close()
0217     else:
0218         fn = "<stdin>"
0219     code = compile(source, fn, "exec")
0220     dis(code)
0221 
0222 if __name__ == "__main__":
0223     _test()
0224 

Generated by PyXR 0.9.4
SourceForge.net Logo