Start handling Python 2.2 bytecode and...

Fix some bugs in Python 2.3-2.5 bytecode handling
This commit is contained in:
rocky 2016-08-13 07:08:48 -04:00
parent 6b98432082
commit d8598f61e4
14 changed files with 79 additions and 13 deletions

View File

@ -11,7 +11,7 @@ Introduction
------------
*uncompyle6* translates Python bytecode back into equivalent Python
source code. It accepts bytecodes from Python version 2.3 to 3.6 or
source code. It accepts bytecodes from Python version 2.2 to 3.6 or
so, including PyPy bytecode.
Why this?
@ -45,7 +45,7 @@ Requirements
This project requires Python 2.6 or later, PyPy 3-2.4, or PyPy-5.0.1.
The bytecode files it can read has been tested on Python bytecodes from
versions 2.3-2.7, and 3.2-3.6 and the above-mentioned PyPy versions.
versions 2.2-2.7, and 3.2-3.6 and the above-mentioned PyPy versions.
Installation
------------

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -269,9 +269,6 @@ class PythonParser(GenericASTBuilder):
"""
_for ::= GET_ITER FOR_ITER
# Possibly before Python 2.3
# _for ::= LOAD_CONST FOR_LOOP
for_block ::= l_stmts_opt _come_from JUMP_BACK
for_block ::= return_stmts _come_from
@ -546,7 +543,13 @@ def get_python_parser(
# FIXME: there has to be a better way...
if version < 3.0:
if version == 2.3:
if version == 2.2:
import uncompyle6.parsers.parse22 as parse22
if compile_mode == 'exec':
p = parse22.Python22Parser(debug_parser)
else:
p = parse22.Python22ParserSingle(debug_parser)
elif version == 2.3:
import uncompyle6.parsers.parse23 as parse23
if compile_mode == 'exec':
p = parse23.Python23Parser(debug_parser)

View File

@ -0,0 +1,30 @@
# Copyright (c) 2016 Rocky Bernstein
# Copyright (c) 2000-2002 by hartmut Goebel <hartmut@goebel.noris.de>
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from uncompyle6.parser import PythonParserSingle
from uncompyle6.parsers.parse23 import Python23Parser
class Python22Parser(Python23Parser):
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
super(Python23Parser, self).__init__(debug_parser)
self.customized = {}
def p_misc22(self, args):
'''
stmt ::= SET_LINENO
_for ::= LOAD_CONST FOR_LOOP
'''
class Python22ParserSingle(Python23Parser, PythonParserSingle):
pass
if __name__ == '__main__':
# Check grammar
p = Python22Parser()
p.checkGrammar()
p.dumpGrammar()
# local variables:
# tab-width: 4

View File

@ -22,7 +22,7 @@ from uncompyle6 import PYTHON3, IS_PYPY
from uncompyle6.scanners.tok import Token
# The byte code versions we support
PYTHON_VERSIONS = (2.3, 2.4, 2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6)
PYTHON_VERSIONS = (2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6)
# FIXME: DRY
if PYTHON3:

View File

@ -0,0 +1,27 @@
# Copyright (c) 2016 by Rocky Bernstein
"""
Python 2.2 bytecode scanner/deparser
This overlaps Python's 2.2's dis module, but it can be run from
Python 3 and other versions of Python. Also, we save token
information for later use in deparsing.
"""
import uncompyle6.scanners.scanner23 as scan
# bytecode verification, verify(), uses JUMP_OPs from here
from xdis.opcodes import opcode_22
JUMP_OPs = opcode_22.JUMP_OPs
# We base this off of 2.3 instead of the other way around
# because we cleaned things up this way.
# The history is that 2.7 support is the cleanest,
# then from that we got 2.6 and so on.
class Scanner22(scan.Scanner23):
def __init__(self, show_asm=False):
scan.Scanner23.__init__(self, show_asm)
self.opc = opcode_22
self.opname = opcode_22.opname
self.version = 2.2
self.genexpr_name = '<generator expression>';
return

View File

@ -1,8 +1,8 @@
# Copyright (c) 2016 by Rocky Bernstein
"""
Python 2.4 bytecode scanner/deparser
Python 2.3 bytecode scanner/deparser
This overlaps Python's 2.4's dis module, but it can be run from
This overlaps Python's 2.3's dis module, but it can be run from
Python 3 and other versions of Python. Also, we save token
information for later use in deparsing.
"""
@ -20,6 +20,8 @@ JUMP_OPs = opcode_23.JUMP_OPs
class Scanner23(scan.Scanner24):
def __init__(self, show_asm):
scan.Scanner24.__init__(self, show_asm)
self.opc = opcode_23
self.opname = opcode_23.opname
# These are the only differences in initialization between
# 2.3-2.6
self.version = 2.3

View File

@ -22,6 +22,8 @@ class Scanner24(scan.Scanner25):
scan.Scanner25.__init__(self, show_asm)
# These are the only differences in initialization between
# 2.4, 2.5 and 2.6
self.opc = opcode_24
self.opname = opcode_24.opname
self.version = 2.4
self.genexpr_name = '<generator expression>';
return

View File

@ -21,6 +21,8 @@ class Scanner25(scan.Scanner26):
def __init__(self, show_asm):
# There are no differences in initialization between
# 2.5 and 2.6
self.opc = opcode_25
self.opname = opcode_25.opname
scan.Scanner26.__init__(self, show_asm)
self.version = 2.5
return

View File

@ -329,7 +329,9 @@ TABLE_DIRECT = {
'kv': ( '%c: %c', 3, 1 ),
'kv2': ( '%c: %c', 1, 2 ),
'mapexpr': ( '{%[1]C}', (0, maxint, ', ') ),
'importstmt': ( '%|import %c\n', 2),
'importfrom': ( '%|from %[2]{pattr} import %c\n', 3 ),
'importstar': ( '%|from %[2]{pattr} import *\n', ),
}
@ -560,14 +562,12 @@ class SourceWalker(GenericASTTraversal, object):
'importfrom20': ( '%|from %[1]{pattr} import %c\n', 2 ),
'importlist20': ( '%C', (0, maxint, ', ') ),
})
elif version >= 2.5:
########################
# Import style for 2.5+
########################
TABLE_DIRECT.update({
'importstmt': ( '%|import %c\n', 2),
'importstar': ( '%|from %[2]{pattr} import *\n', ),
'importfrom': ( '%|from %[2]{pattr} import %c\n', 3 ),
'importmultiple': ( '%|import %c%c\n', 2, 3 ),
'import_cont' : ( ', %c', 2 ),
})