You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
fix for the with statement
This commit is contained in:
@@ -57,9 +57,9 @@ class Scanner:
|
|||||||
# linestarts contains bloc code adresse (addr,block)
|
# linestarts contains bloc code adresse (addr,block)
|
||||||
self.linestarts = list(dis.findlinestarts(co))
|
self.linestarts = list(dis.findlinestarts(co))
|
||||||
self.prev = [0]
|
self.prev = [0]
|
||||||
pop_delet = 0
|
# change jump struct
|
||||||
i=0
|
|
||||||
self.restructRelativeJump()
|
self.restructRelativeJump()
|
||||||
|
|
||||||
# class and names
|
# class and names
|
||||||
if classname:
|
if classname:
|
||||||
classname = '_' + classname.lstrip('_') + '__'
|
classname = '_' + classname.lstrip('_') + '__'
|
||||||
@@ -78,15 +78,13 @@ class Scanner:
|
|||||||
self.names = names
|
self.names = names
|
||||||
# add instruction to remonde in "toDel" list
|
# add instruction to remonde in "toDel" list
|
||||||
toDel = []
|
toDel = []
|
||||||
while i < n-pop_delet:
|
# add instruction to change in "toChange" list
|
||||||
|
self.toChange = []
|
||||||
|
for i in self.op_range(0, n):
|
||||||
op = self.code[i]
|
op = self.code[i]
|
||||||
ret = self.getOpcodeToDel(i)
|
ret = self.getOpcodeToDel(i)
|
||||||
if ret != None:
|
if ret != None:
|
||||||
toDel += ret
|
toDel += ret
|
||||||
if op >= dis.HAVE_ARGUMENT:
|
|
||||||
i += 2
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
if toDel: # degeu a revoir / repenser (tout faire d'un coup? chaud)
|
if toDel: # degeu a revoir / repenser (tout faire d'un coup? chaud)
|
||||||
toDel = sorted(list(set(toDel)))
|
toDel = sorted(list(set(toDel)))
|
||||||
delta = 0
|
delta = 0
|
||||||
@@ -103,8 +101,9 @@ class Scanner:
|
|||||||
self.code.pop(x-delta)
|
self.code.pop(x-delta)
|
||||||
self.restructCode(x-delta)
|
self.restructCode(x-delta)
|
||||||
delta += 1
|
delta += 1
|
||||||
|
|
||||||
# mapping adresses of prev instru
|
# mapping adresses of prev instru
|
||||||
n = len(self.code)
|
n = len(self.code)
|
||||||
for i in self.op_range(0, n):
|
for i in self.op_range(0, n):
|
||||||
op = self.code[i]
|
op = self.code[i]
|
||||||
self.prev.append(i)
|
self.prev.append(i)
|
||||||
@@ -152,19 +151,19 @@ class Scanner:
|
|||||||
if self.code[last_import] == IMPORT_NAME == self.code[i]:
|
if self.code[last_import] == IMPORT_NAME == self.code[i]:
|
||||||
replace[i] = 'IMPORT_NAME_CONT'
|
replace[i] = 'IMPORT_NAME_CONT'
|
||||||
last_import = i
|
last_import = i
|
||||||
|
|
||||||
extended_arg = 0
|
extended_arg = 0
|
||||||
for offset in self.op_range(0, n):
|
for offset in self.op_range(0, n):
|
||||||
|
op = self.code[offset]
|
||||||
|
opname = dis.opname[op]
|
||||||
|
oparg = None; pattr = None
|
||||||
|
|
||||||
if offset in cf:
|
if offset in cf:
|
||||||
k = 0
|
k = 0
|
||||||
for j in cf[offset]:
|
for j in cf[offset]:
|
||||||
rv.append(Token('COME_FROM', None, repr(j),
|
rv.append(Token('COME_FROM', None, repr(j),
|
||||||
offset="%s_%d" % (offset, k) ))
|
offset="%s_%d" % (offset, k) ))
|
||||||
k += 1
|
k += 1
|
||||||
|
|
||||||
op = self.code[offset]
|
|
||||||
opname = dis.opname[op]
|
|
||||||
oparg = None; pattr = None
|
|
||||||
if op >= HAVE_ARGUMENT:
|
if op >= HAVE_ARGUMENT:
|
||||||
oparg = self.get_argument(offset) + extended_arg
|
oparg = self.get_argument(offset) + extended_arg
|
||||||
extended_arg = 0
|
extended_arg = 0
|
||||||
@@ -204,7 +203,10 @@ class Scanner:
|
|||||||
pattr = dis.cmp_op[oparg]
|
pattr = dis.cmp_op[oparg]
|
||||||
elif op in dis.hasfree:
|
elif op in dis.hasfree:
|
||||||
pattr = free[oparg]
|
pattr = free[oparg]
|
||||||
|
if offset in self.toChange:
|
||||||
|
if self.code[offset] == JA and self.code[oparg] == WITH_CLEANUP:
|
||||||
|
opname = 'SETUP_WITH'
|
||||||
|
cf[oparg] = cf.get(oparg, []) + [offset]
|
||||||
if op in (BUILD_LIST, BUILD_TUPLE, BUILD_SLICE,
|
if op in (BUILD_LIST, BUILD_TUPLE, BUILD_SLICE,
|
||||||
UNPACK_SEQUENCE,
|
UNPACK_SEQUENCE,
|
||||||
MAKE_FUNCTION, CALL_FUNCTION, MAKE_CLOSURE,
|
MAKE_FUNCTION, CALL_FUNCTION, MAKE_CLOSURE,
|
||||||
@@ -244,7 +246,7 @@ class Scanner:
|
|||||||
rv.append(Token(opname, oparg, pattr, offset, linestart = offset in linestartoffsets))
|
rv.append(Token(opname, oparg, pattr, offset, linestart = offset in linestartoffsets))
|
||||||
else:
|
else:
|
||||||
rv.append(Token(replace[offset], oparg, pattr, offset, linestart = offset in linestartoffsets))
|
rv.append(Token(replace[offset], oparg, pattr, offset, linestart = offset in linestartoffsets))
|
||||||
|
|
||||||
if self.showasm:
|
if self.showasm:
|
||||||
out = self.out # shortcut
|
out = self.out # shortcut
|
||||||
for t in rv:
|
for t in rv:
|
||||||
@@ -321,6 +323,46 @@ class Scanner:
|
|||||||
end = self.first_instr(i, end, YIELD_VALUE)
|
end = self.first_instr(i, end, YIELD_VALUE)
|
||||||
if end and self.code[end+1] == POP_TOP and self.code[end+2] == JA and self.code[end+5] == POP_BLOCK:
|
if end and self.code[end+1] == POP_TOP and self.code[end+2] == JA and self.code[end+5] == POP_BLOCK:
|
||||||
return [i,end+5]
|
return [i,end+5]
|
||||||
|
# with stmt
|
||||||
|
if opcode == WITH_CLEANUP:
|
||||||
|
chckDel = i-self.op_size(DELETE_NAME)
|
||||||
|
assert self.code[chckDel] in (DELETE_NAME, DELETE_FAST)
|
||||||
|
toDel = [chckDel]
|
||||||
|
nameDel = self.get_argument(chckDel)
|
||||||
|
chckDel -= self.op_size(LOAD_NAME)
|
||||||
|
assert self.code[chckDel] in (LOAD_NAME, LOAD_FAST)
|
||||||
|
toDel += [chckDel]
|
||||||
|
|
||||||
|
allStore = self.all_instr(0, i, (STORE_NAME,STORE_FAST))
|
||||||
|
chckStore = -1
|
||||||
|
for store in allStore:
|
||||||
|
if nameDel == self.get_argument(store):
|
||||||
|
if self.code[store+3] == LOAD_ATTR and self.code[store-3] == LOAD_ATTR \
|
||||||
|
and self.code[store-4] == DUP_TOP:
|
||||||
|
chckStore = store
|
||||||
|
assert chckStore > 0
|
||||||
|
toDel += [chckStore-4,chckStore-3,chckStore+3]
|
||||||
|
|
||||||
|
chckStp = -1
|
||||||
|
allSetup = self.all_instr(chckStore+3, i, (SETUP_FINALLY))
|
||||||
|
for stp in allSetup:
|
||||||
|
if chckDel == self.get_target(stp):
|
||||||
|
chckStp = stp
|
||||||
|
assert chckStp > 0
|
||||||
|
toDel += [chckStp]
|
||||||
|
chckDel = chckStore+3+self.op_size(self.code[chckStore+3])
|
||||||
|
while chckDel < chckStp-3:
|
||||||
|
toDel += [chckDel]
|
||||||
|
chckDel += self.op_size(self.code[chckDel])
|
||||||
|
if self.code[chckStp-3] in (STORE_NAME,STORE_FAST) and self.code[chckStp+3] in (LOAD_NAME,LOAD_FAST) \
|
||||||
|
and self.code[chckStp+6] in (DELETE_NAME,DELETE_FAST):
|
||||||
|
toDel += [chckStp-3,chckStp+3,chckStp+6]
|
||||||
|
# SETUP_WITH opcode dosen't exist in 2.5 but is necessary for the grammar
|
||||||
|
self.code[chckStore] = JUMP_ABSOLUTE # ugly hack
|
||||||
|
self.code[chckStore+1] = i & 0xFF
|
||||||
|
self.code[chckStore+2] = (i >> 8) & 0xFF
|
||||||
|
self.toChange.append(chckStore)
|
||||||
|
return toDel
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def restructRelativeJump(self):
|
def restructRelativeJump(self):
|
||||||
@@ -358,7 +400,10 @@ class Scanner:
|
|||||||
else:
|
else:
|
||||||
result.append((item[0], item[1]))
|
result.append((item[0], item[1]))
|
||||||
self.linestarts = result
|
self.linestarts = result
|
||||||
|
|
||||||
|
for change in self.toChange:
|
||||||
|
if change > i:
|
||||||
|
self.toChange[self.toChange.index(change)] -= 1
|
||||||
for x in self.op_range(0, len(self.code)):
|
for x in self.op_range(0, len(self.code)):
|
||||||
op = self.code[x]
|
op = self.code[x]
|
||||||
if op >= HAVE_ARGUMENT:
|
if op >= HAVE_ARGUMENT:
|
||||||
|
@@ -57,9 +57,9 @@ class Scanner:
|
|||||||
# linestarts contains bloc code adresse (addr,block)
|
# linestarts contains bloc code adresse (addr,block)
|
||||||
self.linestarts = list(dis.findlinestarts(co))
|
self.linestarts = list(dis.findlinestarts(co))
|
||||||
self.prev = [0]
|
self.prev = [0]
|
||||||
pop_delet = 0
|
# change jump struct
|
||||||
i=0
|
|
||||||
self.restructRelativeJump()
|
self.restructRelativeJump()
|
||||||
|
|
||||||
# class and names
|
# class and names
|
||||||
if classname:
|
if classname:
|
||||||
classname = '_' + classname.lstrip('_') + '__'
|
classname = '_' + classname.lstrip('_') + '__'
|
||||||
@@ -78,15 +78,13 @@ class Scanner:
|
|||||||
self.names = names
|
self.names = names
|
||||||
# add instruction to remonde in "toDel" list
|
# add instruction to remonde in "toDel" list
|
||||||
toDel = []
|
toDel = []
|
||||||
while i < n-pop_delet:
|
# add instruction to change in "toChange" list
|
||||||
|
self.toChange = []
|
||||||
|
for i in self.op_range(0, n):
|
||||||
op = self.code[i]
|
op = self.code[i]
|
||||||
ret = self.getOpcodeToDel(i)
|
ret = self.getOpcodeToDel(i)
|
||||||
if ret != None:
|
if ret != None:
|
||||||
toDel += ret
|
toDel += ret
|
||||||
if op >= dis.HAVE_ARGUMENT:
|
|
||||||
i += 2
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
if toDel: # degeu a revoir / repenser (tout faire d'un coup? chaud)
|
if toDel: # degeu a revoir / repenser (tout faire d'un coup? chaud)
|
||||||
toDel = sorted(list(set(toDel)))
|
toDel = sorted(list(set(toDel)))
|
||||||
delta = 0
|
delta = 0
|
||||||
@@ -103,8 +101,9 @@ class Scanner:
|
|||||||
self.code.pop(x-delta)
|
self.code.pop(x-delta)
|
||||||
self.restructCode(x-delta)
|
self.restructCode(x-delta)
|
||||||
delta += 1
|
delta += 1
|
||||||
|
|
||||||
# mapping adresses of prev instru
|
# mapping adresses of prev instru
|
||||||
n = len(self.code)
|
n = len(self.code)
|
||||||
for i in self.op_range(0, n):
|
for i in self.op_range(0, n):
|
||||||
op = self.code[i]
|
op = self.code[i]
|
||||||
self.prev.append(i)
|
self.prev.append(i)
|
||||||
@@ -152,19 +151,19 @@ class Scanner:
|
|||||||
if self.code[last_import] == IMPORT_NAME == self.code[i]:
|
if self.code[last_import] == IMPORT_NAME == self.code[i]:
|
||||||
replace[i] = 'IMPORT_NAME_CONT'
|
replace[i] = 'IMPORT_NAME_CONT'
|
||||||
last_import = i
|
last_import = i
|
||||||
|
|
||||||
extended_arg = 0
|
extended_arg = 0
|
||||||
for offset in self.op_range(0, n):
|
for offset in self.op_range(0, n):
|
||||||
|
op = self.code[offset]
|
||||||
|
opname = dis.opname[op]
|
||||||
|
oparg = None; pattr = None
|
||||||
|
|
||||||
if offset in cf:
|
if offset in cf:
|
||||||
k = 0
|
k = 0
|
||||||
for j in cf[offset]:
|
for j in cf[offset]:
|
||||||
rv.append(Token('COME_FROM', None, repr(j),
|
rv.append(Token('COME_FROM', None, repr(j),
|
||||||
offset="%s_%d" % (offset, k) ))
|
offset="%s_%d" % (offset, k) ))
|
||||||
k += 1
|
k += 1
|
||||||
|
|
||||||
op = self.code[offset]
|
|
||||||
opname = dis.opname[op]
|
|
||||||
oparg = None; pattr = None
|
|
||||||
if op >= HAVE_ARGUMENT:
|
if op >= HAVE_ARGUMENT:
|
||||||
oparg = self.get_argument(offset) + extended_arg
|
oparg = self.get_argument(offset) + extended_arg
|
||||||
extended_arg = 0
|
extended_arg = 0
|
||||||
@@ -204,7 +203,10 @@ class Scanner:
|
|||||||
pattr = dis.cmp_op[oparg]
|
pattr = dis.cmp_op[oparg]
|
||||||
elif op in dis.hasfree:
|
elif op in dis.hasfree:
|
||||||
pattr = free[oparg]
|
pattr = free[oparg]
|
||||||
|
if offset in self.toChange:
|
||||||
|
if self.code[offset] == JA and self.code[oparg] == WITH_CLEANUP:
|
||||||
|
opname = 'SETUP_WITH'
|
||||||
|
cf[oparg] = cf.get(oparg, []) + [offset]
|
||||||
if op in (BUILD_LIST, BUILD_TUPLE, BUILD_SLICE,
|
if op in (BUILD_LIST, BUILD_TUPLE, BUILD_SLICE,
|
||||||
UNPACK_SEQUENCE,
|
UNPACK_SEQUENCE,
|
||||||
MAKE_FUNCTION, CALL_FUNCTION, MAKE_CLOSURE,
|
MAKE_FUNCTION, CALL_FUNCTION, MAKE_CLOSURE,
|
||||||
@@ -244,7 +246,7 @@ class Scanner:
|
|||||||
rv.append(Token(opname, oparg, pattr, offset, linestart = offset in linestartoffsets))
|
rv.append(Token(opname, oparg, pattr, offset, linestart = offset in linestartoffsets))
|
||||||
else:
|
else:
|
||||||
rv.append(Token(replace[offset], oparg, pattr, offset, linestart = offset in linestartoffsets))
|
rv.append(Token(replace[offset], oparg, pattr, offset, linestart = offset in linestartoffsets))
|
||||||
|
|
||||||
if self.showasm:
|
if self.showasm:
|
||||||
out = self.out # shortcut
|
out = self.out # shortcut
|
||||||
for t in rv:
|
for t in rv:
|
||||||
@@ -258,10 +260,10 @@ class Scanner:
|
|||||||
"""
|
"""
|
||||||
opcode = self.code[i]
|
opcode = self.code[i]
|
||||||
opsize = self.op_size(opcode)
|
opsize = self.op_size(opcode)
|
||||||
|
|
||||||
if i+opsize >= len(self.code):
|
if i+opsize >= len(self.code):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if opcode == EXTENDED_ARG:
|
if opcode == EXTENDED_ARG:
|
||||||
raise 'TODO'
|
raise 'TODO'
|
||||||
# del POP_TOP
|
# del POP_TOP
|
||||||
@@ -325,6 +327,36 @@ class Scanner:
|
|||||||
end = self.first_instr(i, end, YIELD_VALUE)
|
end = self.first_instr(i, end, YIELD_VALUE)
|
||||||
if end and self.code[end+1] == POP_TOP and self.code[end+2] == JA and self.code[end+5] == POP_BLOCK:
|
if end and self.code[end+1] == POP_TOP and self.code[end+2] == JA and self.code[end+5] == POP_BLOCK:
|
||||||
return [i,end+5]
|
return [i,end+5]
|
||||||
|
# with stmt
|
||||||
|
if opcode == WITH_CLEANUP:
|
||||||
|
allRot = self.all_instr(0, i, (ROT_TWO))
|
||||||
|
chckRot = -1
|
||||||
|
for rot in allRot:
|
||||||
|
if self.code[rot+1] == LOAD_ATTR and self.code[rot-3] == LOAD_ATTR \
|
||||||
|
and self.code[rot-4] == DUP_TOP:
|
||||||
|
chckRot = rot
|
||||||
|
assert chckRot > 0
|
||||||
|
toDel = [chckRot-4,chckRot-3,chckRot]
|
||||||
|
chckStp = -1
|
||||||
|
allSetup = self.all_instr(chckRot+1, i, (SETUP_FINALLY))
|
||||||
|
for stp in allSetup:
|
||||||
|
if i == self.get_target(stp):
|
||||||
|
chckStp = stp
|
||||||
|
assert chckStp > 0
|
||||||
|
toDel += [chckStp]
|
||||||
|
chckDel = chckRot+1+self.op_size(self.code[chckRot+1])
|
||||||
|
while chckDel < chckStp-3:
|
||||||
|
toDel += [chckDel]
|
||||||
|
chckDel += self.op_size(self.code[chckDel])
|
||||||
|
if self.code[chckStp-3] in (STORE_NAME,STORE_FAST) and self.code[chckStp+3] in (LOAD_NAME,LOAD_FAST) \
|
||||||
|
and self.code[chckStp+6] in (DELETE_NAME,DELETE_FAST):
|
||||||
|
toDel += [chckStp-3,chckStp+3,chckStp+6]
|
||||||
|
# SETUP_WITH opcode dosen't exist in 2.6 but is necessary for the grammar
|
||||||
|
self.code[chckRot+1] = JUMP_ABSOLUTE # ugly hack
|
||||||
|
self.code[chckRot+2] = i & 0xFF
|
||||||
|
self.code[chckRot+3] = (i >> 8) & 0xFF
|
||||||
|
self.toChange.append(chckRot+1)
|
||||||
|
return toDel
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def restructRelativeJump(self):
|
def restructRelativeJump(self):
|
||||||
@@ -362,7 +394,10 @@ class Scanner:
|
|||||||
else:
|
else:
|
||||||
result.append((item[0], item[1]))
|
result.append((item[0], item[1]))
|
||||||
self.linestarts = result
|
self.linestarts = result
|
||||||
|
|
||||||
|
for change in self.toChange:
|
||||||
|
if change > i:
|
||||||
|
self.toChange[self.toChange.index(change)] -= 1
|
||||||
for x in self.op_range(0, len(self.code)):
|
for x in self.op_range(0, len(self.code)):
|
||||||
op = self.code[x]
|
op = self.code[x]
|
||||||
if op >= HAVE_ARGUMENT:
|
if op >= HAVE_ARGUMENT:
|
||||||
|
@@ -206,7 +206,7 @@ def main(in_base, out_base, files, codes, outfile=None,
|
|||||||
raise
|
raise
|
||||||
except:
|
except:
|
||||||
failed_files += 1
|
failed_files += 1
|
||||||
sys.stderr.write("### Can't uncompyle %s\n" % infile)
|
sys.stderr.write("\n# Can't uncompyle %s\n" % infile)
|
||||||
if outfile:
|
if outfile:
|
||||||
outstream.close()
|
outstream.close()
|
||||||
os.rename(outfile, outfile + '_failed')
|
os.rename(outfile, outfile + '_failed')
|
||||||
@@ -219,7 +219,7 @@ def main(in_base, out_base, files, codes, outfile=None,
|
|||||||
if do_verify:
|
if do_verify:
|
||||||
try:
|
try:
|
||||||
verify.compare_code_with_srcfile(infile, outfile)
|
verify.compare_code_with_srcfile(infile, outfile)
|
||||||
print '# okay decompyling', infile, __memUsage()
|
print '\n# okay decompyling', infile, __memUsage()
|
||||||
okay_files += 1
|
okay_files += 1
|
||||||
except verify.VerifyCmpError, e:
|
except verify.VerifyCmpError, e:
|
||||||
verify_failed_files += 1
|
verify_failed_files += 1
|
||||||
@@ -228,5 +228,5 @@ def main(in_base, out_base, files, codes, outfile=None,
|
|||||||
print >>sys.stderr, e
|
print >>sys.stderr, e
|
||||||
else:
|
else:
|
||||||
okay_files += 1
|
okay_files += 1
|
||||||
print '# okay decompyling', infile, __memUsage()
|
print '\n# okay decompyling', infile, __memUsage()
|
||||||
return (tot_files, okay_files, failed_files, verify_failed_files)
|
return (tot_files, okay_files, failed_files, verify_failed_files)
|
||||||
|
Reference in New Issue
Block a user