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)
|
||||
self.linestarts = list(dis.findlinestarts(co))
|
||||
self.prev = [0]
|
||||
pop_delet = 0
|
||||
i=0
|
||||
# change jump struct
|
||||
self.restructRelativeJump()
|
||||
|
||||
# class and names
|
||||
if classname:
|
||||
classname = '_' + classname.lstrip('_') + '__'
|
||||
@@ -78,15 +78,13 @@ class Scanner:
|
||||
self.names = names
|
||||
# add instruction to remonde in "toDel" list
|
||||
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]
|
||||
ret = self.getOpcodeToDel(i)
|
||||
if ret != None:
|
||||
toDel += ret
|
||||
if op >= dis.HAVE_ARGUMENT:
|
||||
i += 2
|
||||
i += 1
|
||||
|
||||
if toDel: # degeu a revoir / repenser (tout faire d'un coup? chaud)
|
||||
toDel = sorted(list(set(toDel)))
|
||||
delta = 0
|
||||
@@ -103,6 +101,7 @@ class Scanner:
|
||||
self.code.pop(x-delta)
|
||||
self.restructCode(x-delta)
|
||||
delta += 1
|
||||
|
||||
# mapping adresses of prev instru
|
||||
n = len(self.code)
|
||||
for i in self.op_range(0, n):
|
||||
@@ -155,16 +154,16 @@ class Scanner:
|
||||
|
||||
extended_arg = 0
|
||||
for offset in self.op_range(0, n):
|
||||
op = self.code[offset]
|
||||
opname = dis.opname[op]
|
||||
oparg = None; pattr = None
|
||||
|
||||
if offset in cf:
|
||||
k = 0
|
||||
for j in cf[offset]:
|
||||
rv.append(Token('COME_FROM', None, repr(j),
|
||||
offset="%s_%d" % (offset, k) ))
|
||||
k += 1
|
||||
|
||||
op = self.code[offset]
|
||||
opname = dis.opname[op]
|
||||
oparg = None; pattr = None
|
||||
if op >= HAVE_ARGUMENT:
|
||||
oparg = self.get_argument(offset) + extended_arg
|
||||
extended_arg = 0
|
||||
@@ -204,7 +203,10 @@ class Scanner:
|
||||
pattr = dis.cmp_op[oparg]
|
||||
elif op in dis.hasfree:
|
||||
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,
|
||||
UNPACK_SEQUENCE,
|
||||
MAKE_FUNCTION, CALL_FUNCTION, MAKE_CLOSURE,
|
||||
@@ -321,6 +323,46 @@ class Scanner:
|
||||
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:
|
||||
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
|
||||
|
||||
def restructRelativeJump(self):
|
||||
@@ -359,6 +401,9 @@ class Scanner:
|
||||
result.append((item[0], item[1]))
|
||||
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)):
|
||||
op = self.code[x]
|
||||
if op >= HAVE_ARGUMENT:
|
||||
|
@@ -57,9 +57,9 @@ class Scanner:
|
||||
# linestarts contains bloc code adresse (addr,block)
|
||||
self.linestarts = list(dis.findlinestarts(co))
|
||||
self.prev = [0]
|
||||
pop_delet = 0
|
||||
i=0
|
||||
# change jump struct
|
||||
self.restructRelativeJump()
|
||||
|
||||
# class and names
|
||||
if classname:
|
||||
classname = '_' + classname.lstrip('_') + '__'
|
||||
@@ -78,15 +78,13 @@ class Scanner:
|
||||
self.names = names
|
||||
# add instruction to remonde in "toDel" list
|
||||
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]
|
||||
ret = self.getOpcodeToDel(i)
|
||||
if ret != None:
|
||||
toDel += ret
|
||||
if op >= dis.HAVE_ARGUMENT:
|
||||
i += 2
|
||||
i += 1
|
||||
|
||||
if toDel: # degeu a revoir / repenser (tout faire d'un coup? chaud)
|
||||
toDel = sorted(list(set(toDel)))
|
||||
delta = 0
|
||||
@@ -103,6 +101,7 @@ class Scanner:
|
||||
self.code.pop(x-delta)
|
||||
self.restructCode(x-delta)
|
||||
delta += 1
|
||||
|
||||
# mapping adresses of prev instru
|
||||
n = len(self.code)
|
||||
for i in self.op_range(0, n):
|
||||
@@ -155,16 +154,16 @@ class Scanner:
|
||||
|
||||
extended_arg = 0
|
||||
for offset in self.op_range(0, n):
|
||||
op = self.code[offset]
|
||||
opname = dis.opname[op]
|
||||
oparg = None; pattr = None
|
||||
|
||||
if offset in cf:
|
||||
k = 0
|
||||
for j in cf[offset]:
|
||||
rv.append(Token('COME_FROM', None, repr(j),
|
||||
offset="%s_%d" % (offset, k) ))
|
||||
k += 1
|
||||
|
||||
op = self.code[offset]
|
||||
opname = dis.opname[op]
|
||||
oparg = None; pattr = None
|
||||
if op >= HAVE_ARGUMENT:
|
||||
oparg = self.get_argument(offset) + extended_arg
|
||||
extended_arg = 0
|
||||
@@ -204,7 +203,10 @@ class Scanner:
|
||||
pattr = dis.cmp_op[oparg]
|
||||
elif op in dis.hasfree:
|
||||
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,
|
||||
UNPACK_SEQUENCE,
|
||||
MAKE_FUNCTION, CALL_FUNCTION, MAKE_CLOSURE,
|
||||
@@ -325,6 +327,36 @@ class Scanner:
|
||||
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:
|
||||
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
|
||||
|
||||
def restructRelativeJump(self):
|
||||
@@ -363,6 +395,9 @@ class Scanner:
|
||||
result.append((item[0], item[1]))
|
||||
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)):
|
||||
op = self.code[x]
|
||||
if op >= HAVE_ARGUMENT:
|
||||
|
@@ -206,7 +206,7 @@ def main(in_base, out_base, files, codes, outfile=None,
|
||||
raise
|
||||
except:
|
||||
failed_files += 1
|
||||
sys.stderr.write("### Can't uncompyle %s\n" % infile)
|
||||
sys.stderr.write("\n# Can't uncompyle %s\n" % infile)
|
||||
if outfile:
|
||||
outstream.close()
|
||||
os.rename(outfile, outfile + '_failed')
|
||||
@@ -219,7 +219,7 @@ def main(in_base, out_base, files, codes, outfile=None,
|
||||
if do_verify:
|
||||
try:
|
||||
verify.compare_code_with_srcfile(infile, outfile)
|
||||
print '# okay decompyling', infile, __memUsage()
|
||||
print '\n# okay decompyling', infile, __memUsage()
|
||||
okay_files += 1
|
||||
except verify.VerifyCmpError, e:
|
||||
verify_failed_files += 1
|
||||
@@ -228,5 +228,5 @@ def main(in_base, out_base, files, codes, outfile=None,
|
||||
print >>sys.stderr, e
|
||||
else:
|
||||
okay_files += 1
|
||||
print '# okay decompyling', infile, __memUsage()
|
||||
print '\n# okay decompyling', infile, __memUsage()
|
||||
return (tot_files, okay_files, failed_files, verify_failed_files)
|
||||
|
Reference in New Issue
Block a user