diff --git a/uncompyle6/parsers/parse26.py b/uncompyle6/parsers/parse26.py index 34248a06..45ca5be1 100644 --- a/uncompyle6/parsers/parse26.py +++ b/uncompyle6/parsers/parse26.py @@ -58,6 +58,8 @@ class Python26Parser(Python2Parser): come_froms ::= come_froms COME_FROM come_froms ::= COME_FROM + come_froms_pop ::= come_froms POP_TOP + """ # In contrast to Python 2.7, Python 2.6 has a lot of @@ -134,6 +136,7 @@ class Python26Parser(Python2Parser): whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_pop POP_BLOCK _come_from whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_cf_pop POP_BLOCK COME_FROM + whilestmt ::= SETUP_LOOP testexpr return_stmts come_froms POP_TOP POP_BLOCK COME_FROM while1stmt ::= SETUP_LOOP return_stmts POP_BLOCK COME_FROM @@ -190,6 +193,8 @@ class Python26Parser(Python2Parser): def p_misc(self, args): ''' conditional ::= expr jmp_false expr jf_cf_pop expr come_from_opt + and ::= expr JUMP_IF_FALSE POP_TOP expr JUMP_IF_FALSE POP_TOP + ''' class Python26ParserSingle(Python2Parser, PythonParserSingle): diff --git a/uncompyle6/scanners/scanner2.py b/uncompyle6/scanners/scanner2.py index fa0a49c6..868dc4bc 100755 --- a/uncompyle6/scanners/scanner2.py +++ b/uncompyle6/scanners/scanner2.py @@ -432,12 +432,27 @@ class Scanner2(scan.Scanner): jump_back = self.last_instr(start, end, self.opc.RETURN_VALUE) + 1 if not jump_back: return - # scanner26 jump_back += 1 - if code[self.prev[next_line_byte]] not in self.pop_jump_if: - loop_type = 'for' - else: + + if_offset = None + if self.version < 2.7: + # Look for JUMP_IF... POP_TOP + if (code[self.prev[next_line_byte]] == self.opc.POP_TOP + and (code[self.prev[self.prev[next_line_byte]]] + in self.pop_jump_if)): + if_offset = self.prev[self.prev[next_line_byte]] + elif code[self.prev[next_line_byte]] in self.pop_jump_if: + # Look for POP_JUMP_IF ... + if_offset = self.prev[next_line_byte] + if if_offset: loop_type = 'while' - self.ignore_if.add(self.prev[next_line_byte]) + self.ignore_if.add(if_offset) + if self.version < 2.7 and ( + code[self.prev[jump_back]] == self.opc.RETURN_VALUE): + self.ignore_if.add(self.prev[jump_back]) + pass + pass + else: + loop_type = 'for' target = next_line_byte end = jump_back + 3 else: @@ -636,11 +651,13 @@ class Scanner2(scan.Scanner): rtarget = pre[rtarget] # Does the "if" jump just beyond a jump op, then this is probably an if statement - if code[pre[rtarget]] in self.jump_forward: - if_end = self.get_target(pre[rtarget]) + pre_rtarget = pre[rtarget] + code_pre_rtarget = code[pre_rtarget] + if code_pre_rtarget in self.jump_forward: + if_end = self.get_target(pre_rtarget) # Is this a loop and not an "if" statment? - if (if_end < pre[rtarget]) and (code[pre[if_end]] == self.opc.SETUP_LOOP): + if (if_end < pre_rtarget) and (code[pre[if_end]] == self.opc.SETUP_LOOP): if(if_end > start): return @@ -648,18 +665,19 @@ class Scanner2(scan.Scanner): self.structs.append({'type': 'if-then', 'start': start, - 'end': pre[rtarget]}) - self.not_continue.add(pre[rtarget]) + 'end': pre_rtarget}) + self.not_continue.add(pre_rtarget) if rtarget < end: self.structs.append({'type': 'if-else', 'start': rtarget, 'end': end}) - elif code[pre[rtarget]] == self.opc.RETURN_VALUE: - self.structs.append({'type': 'if-then', - 'start': start, - 'end': rtarget}) - self.return_end_ifs.add(pre[rtarget]) + elif code_pre_rtarget == self.opc.RETURN_VALUE: + if self.version == 2.7 or pre_rtarget not in self.ignore_if: + self.structs.append({'type': 'if-then', + 'start': start, + 'end': rtarget}) + self.return_end_ifs.add(pre_rtarget) elif op in self.pop_jump_if_or_pop: target = self.get_target(pos, op)