diff --git a/uncompyle6/scanner.py b/uncompyle6/scanner.py index 36a95f67..a1119e62 100755 --- a/uncompyle6/scanner.py +++ b/uncompyle6/scanner.py @@ -45,12 +45,17 @@ class Code(object): class Scanner(object): - def __init__(self, version): + def __init__(self, version, show_asm=False): self.version = version + self.show_asm = show_asm + # FIXME: DRY if version == 2.7: from xdis.opcodes import opcode_27 self.opc = opcode_27 + elif version == 2.3: + from xdis.opcodes import opcode_23 + self.opc = opcode_23 elif version == 2.6: from xdis.opcodes import opcode_26 self.opc = opcode_26 @@ -281,7 +286,7 @@ class Scanner(object): target = parent['end'] return target -def get_scanner(version): +def get_scanner(version, show_asm=False): # Pick up appropriate scanner # from trepan.api import debug; # debug(start_opts={'startup-profile': True}) @@ -289,25 +294,28 @@ def get_scanner(version): # FIXME: see if we can do better if version == 2.7: import uncompyle6.scanners.scanner27 as scan - scanner = scan.Scanner27() + scanner = scan.Scanner27(show_asm=show_asm) + elif version == 2.3: + import uncompyle6.scanners.scanner23 as scan + scanner = scan.Scanner23(show_asm) elif version == 2.6: import uncompyle6.scanners.scanner26 as scan - scanner = scan.Scanner26() + scanner = scan.Scanner26(show_asm) elif version == 2.5: import uncompyle6.scanners.scanner25 as scan - scanner = scan.Scanner25() + scanner = scan.Scanner25(show_asm) elif version == 3.2: import uncompyle6.scanners.scanner32 as scan - scanner = scan.Scanner32() + scanner = scan.Scanner32(show_asm) elif version == 3.3: import uncompyle6.scanners.scanner33 as scan - scanner = scan.Scanner33() + scanner = scan.Scanner33(show_asm) elif version == 3.4: import uncompyle6.scanners.scanner34 as scan - scanner = scan.Scanner34() + scanner = scan.Scanner34(show_asm) elif version == 3.5: import uncompyle6.scanners.scanner35 as scan - scanner = scan.Scanner35() + scanner = scan.Scanner35(show_asm) else: raise RuntimeError("Unsupported Python version %s" % version) return scanner @@ -315,9 +323,5 @@ def get_scanner(version): if __name__ == "__main__": import inspect, uncompyle6 co = inspect.currentframe().f_code - scanner = get_scanner(uncompyle6.PYTHON_VERSION) + scanner = get_scanner(uncompyle6.PYTHON_VERSION, True) tokens, customize = scanner.disassemble(co, {}) - print('-' * 30) - for t in tokens: - print(t) - pass diff --git a/uncompyle6/scanners/scanner2.py b/uncompyle6/scanners/scanner2.py index 79195dff..6f8b7361 100755 --- a/uncompyle6/scanners/scanner2.py +++ b/uncompyle6/scanners/scanner2.py @@ -32,8 +32,8 @@ from xdis.bytecode import findlinestarts import uncompyle6.scanner as scan class Scanner2(scan.Scanner): - def __init__(self, version): - scan.Scanner.__init__(self, version) + def __init__(self, version, show_asm=False): + scan.Scanner.__init__(self, version, show_asm) self.pop_jump_if = frozenset([self.opc.PJIF, self.opc.PJIT]) self.jump_forward = frozenset([self.opc.JA, self.opc.JF]) @@ -204,6 +204,13 @@ class Scanner2(scan.Scanner): tokens.append(Token(op_name, oparg, pattr, offset, linestart)) else: tokens.append(Token(replace[offset], oparg, pattr, offset, linestart)) + pass + pass + + if self.show_asm: + for t in tokens: + print(t) + print() return tokens, customize def op_size(self, op): diff --git a/uncompyle6/scanners/scanner25.py b/uncompyle6/scanners/scanner25.py index e6ece85c..f135ab9f 100755 --- a/uncompyle6/scanners/scanner25.py +++ b/uncompyle6/scanners/scanner25.py @@ -23,8 +23,8 @@ JUMP_OPs = opcode_25.JUMP_OPs # The history is that 2.7 support is the cleanest, # then from that we got 2.6 and so on. class Scanner25(scan.Scanner26): - def __init__(self): - scan2.Scanner2.__init__(self, 2.5) + def __init__(self, show_asm): + scan2.Scanner2.__init__(self, 2.5, show_asm) self.stmt_opcodes = frozenset([ self.opc.SETUP_LOOP, self.opc.BREAK_LOOP, self.opc.SETUP_FINALLY, self.opc.END_FINALLY, diff --git a/uncompyle6/scanners/scanner26.py b/uncompyle6/scanners/scanner26.py index 1c5a903d..1995ca6f 100755 --- a/uncompyle6/scanners/scanner26.py +++ b/uncompyle6/scanners/scanner26.py @@ -18,8 +18,8 @@ from xdis.opcodes import opcode_26 JUMP_OPs = opcode_26.JUMP_OPs class Scanner26(scan.Scanner2): - def __init__(self): - super(Scanner26, self).__init__(2.6) + def __init__(self, show_asm=False): + super(Scanner26, self).__init__(2.6, show_asm) self.stmt_opcodes = frozenset([ self.opc.SETUP_LOOP, self.opc.BREAK_LOOP, self.opc.SETUP_FINALLY, self.opc.END_FINALLY, @@ -251,9 +251,10 @@ class Scanner26(scan.Scanner2): pass pass - # Debug - # for t in tokens: - # print t + if self.show_asm: + for t in tokens: + print(t) + print() return tokens, customize def getOpcodeToDel(self, i): @@ -586,8 +587,8 @@ class Scanner26(scan.Scanner2): if (jump_back and jump_back != self.prev[end] and code[jump_back + 3] in self.jump_forward): if (code[self.prev[end]] == self.opc.RETURN_VALUE - or code[self.prev[end]] == self.opc.POP_BLOCK - and code[self.prev[self.prev[end]]] == self.opc.RETURN_VALUE): + or (code[self.prev[end]] == self.opc.POP_BLOCK + and code[self.prev[self.prev[end]]] == self.opc.RETURN_VALUE)): jump_back = None if not jump_back: # loop suite ends in return. wtf right? jump_back = self.last_instr(start, end, self.opc.JA, start, False) @@ -604,7 +605,7 @@ class Scanner26(scan.Scanner2): else: if self.get_target(jump_back) >= next_line_byte: jump_back = self.last_instr(start, end, self.opc.JA, start, False) - if end > jump_back + 4 and code[end] in (self.opc.JF, self.opc.JA): + if end > jump_back + 4 and code[end] in self.jump_forward: if code[jump_back + 4] in (self.opc.JA, self.opc.JF): if self.get_target(jump_back+4) == self.get_target(end): self.fixed_jumps[pos] = jump_back+4 @@ -807,9 +808,7 @@ if __name__ == "__main__": if PYTHON_VERSION == 2.6: import inspect co = inspect.currentframe().f_code - tokens, customize = Scanner26().disassemble(co) - for t in tokens: - print(t.format()) + tokens, customize = Scanner26(show_asm=True).disassemble(co) else: print("Need to be Python 2.6 to demo; I am %s." % PYTHON_VERSION) diff --git a/uncompyle6/scanners/scanner27.py b/uncompyle6/scanners/scanner27.py index d50e0d5d..415dd40f 100755 --- a/uncompyle6/scanners/scanner27.py +++ b/uncompyle6/scanners/scanner27.py @@ -17,8 +17,8 @@ from xdis.opcodes import opcode_27 JUMP_OPs = opcode_27.JUMP_OPs class Scanner27(Scanner2): - def __init__(self): - super(Scanner27, self).__init__(2.7) + def __init__(self, show_asm=False): + super(Scanner27, self).__init__(2.7, show_asm) # opcodes that start statements self.stmt_opcodes = frozenset([ diff --git a/uncompyle6/scanners/scanner3.py b/uncompyle6/scanners/scanner3.py index 3475c126..7acdc7e6 100644 --- a/uncompyle6/scanners/scanner3.py +++ b/uncompyle6/scanners/scanner3.py @@ -40,8 +40,8 @@ import uncompyle6.scanner as scan class Scanner3(scan.Scanner): - def __init__(self, version): - super(Scanner3, self).__init__(version) + def __init__(self, version, show_asm=False): + super(Scanner3, self).__init__(version, show_asm) def disassemble(self, co, classname=None, code_objects={}): """ diff --git a/uncompyle6/scanners/scanner32.py b/uncompyle6/scanners/scanner32.py index 123e5ad4..97ff2644 100644 --- a/uncompyle6/scanners/scanner32.py +++ b/uncompyle6/scanners/scanner32.py @@ -8,16 +8,15 @@ scanner routine for Python 3. from __future__ import print_function -import xdis - # bytecode verification, verify(), uses JUMP_OPs from here -# JUMP_OPs = xdis.opcodes.opcode_32.JUMP_OPs +from xdis.opcodes import opcode_32 as opc +JUMP_OPs = map(lambda op: opc.opname[op], opc.hasjrel + opc.hasjabs) from uncompyle6.scanners.scanner3 import Scanner3 class Scanner32(Scanner3): - def __init__(self): - super(Scanner3, self).__init__(3.2) + def __init__(self, show_asm=False): + super(Scanner3, self).__init__(3.2, show_asm) return pass diff --git a/uncompyle6/scanners/scanner33.py b/uncompyle6/scanners/scanner33.py index f90db30c..a59614a6 100644 --- a/uncompyle6/scanners/scanner33.py +++ b/uncompyle6/scanners/scanner33.py @@ -8,16 +8,15 @@ scanner routine for Python 3. from __future__ import print_function -from xdis.opcodes import opcode_33 as opc - # bytecode verification, verify(), uses JUMP_OPs from here +from xdis.opcodes import opcode_33 as opc JUMP_OPs = map(lambda op: opc.opname[op], opc.hasjrel + opc.hasjabs) from uncompyle6.scanners.scanner3 import Scanner3 class Scanner33(Scanner3): - def __init__(self): - super(Scanner3, self).__init__(3.3) + def __init__(self, show_asm=False): + super(Scanner3, self).__init__(3.3, show_asm) return pass diff --git a/uncompyle6/scanners/scanner34.py b/uncompyle6/scanners/scanner34.py index aa1f65b6..55365e78 100644 --- a/uncompyle6/scanners/scanner34.py +++ b/uncompyle6/scanners/scanner34.py @@ -17,8 +17,8 @@ JUMP_OPs = map(lambda op: opc.opname[op], opc.hasjrel + opc.hasjabs) from uncompyle6.scanners.scanner3 import Scanner3 class Scanner34(Scanner3): - def __init__(self): - super(Scanner3, self).__init__(3.4) + def __init__(self, show_asm=False): + super(Scanner3, self).__init__(3.4, show_asm) return pass diff --git a/uncompyle6/scanners/scanner35.py b/uncompyle6/scanners/scanner35.py index 6efc1281..ee655c85 100644 --- a/uncompyle6/scanners/scanner35.py +++ b/uncompyle6/scanners/scanner35.py @@ -8,17 +8,16 @@ scanner routine for Python 3. from __future__ import print_function -from xdis.opcodes import opcode_35 as opc - from uncompyle6.scanners.scanner3 import Scanner3 # bytecode verification, verify(), uses JUMP_OPs from here +from xdis.opcodes import opcode_35 as opc JUMP_OPs = map(lambda op: opc.opname[op], opc.hasjrel + opc.hasjabs) class Scanner35(Scanner3): - def __init__(self): - super(Scanner35, self).__init__(3.5) + def __init__(self, show_asm=False): + super(Scanner35, self).__init__(3.5, show_asm) return pass diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 80e07c7c..234a13ac 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -345,6 +345,16 @@ TABLE_DIRECT = { 'kv2': ( '%c: %c', 1, 2 ), 'mapexpr': ( '{%[1]C}', (0, maxint, ', ') ), + ####################### + # Python 2.3 Additions + ####################### + + # Import style for 2.0-2.3 + 'importstmt20': ( '%|import %c\n', 1), + 'importstar20': ( '%|from %[1]{pattr} import *\n', ), + 'importfrom20': ( '%|from %[1]{pattr} import %c\n', 2 ), + 'importlist20': ( '%C', (0, sys.maxint, ', ') ), + ####################### # Python 2.5 Additions ####################### @@ -526,7 +536,11 @@ class SourceWalker(GenericASTTraversal, object): self.classes = [] self.pending_newlines = 0 self.hide_internal = True + self.version = version + if 2.0 <= version <= 2.3: + TABLE_DIRECT['tryfinallystmt'] = ( + '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n', 1, 4 ) return f = property(lambda s: s.params['f'], @@ -1658,7 +1672,6 @@ class SourceWalker(GenericASTTraversal, object): else: defparams = node[:args_node.attr] kw_args, annotate_args = (0, 0) - pos_args = args_node.attr pass if self.version > 3.0 and isLambda and iscode(node[-3].attr):