3
/*^h                 @   s   d Z ddlmZ ddlmZ ddlmZmZmZmZ ddl	m
Z
 ddlmZ er\ddlmZ ddlmZmZ G d	d
 d
eZedkrddlmZ de  kodk n  rddlZej jZddlmZ eeje\ZZx"eD ]Zee qW nede  dS )a}  
Python 2 Generic bytecode scanner/deparser

This overlaps various Python3's dis module, but it can be run from
Python versions other than the version running this code. Notably,
run from Python version 2.

Also we *modify* the instruction sequence to assist deparsing code.
For example:
 -  we add "COME_FROM" instructions to help in figuring out
    conditional branching and looping.
 -  LOAD_CONSTs are classified further into the type of thing
    they load:
      lambda's, genexpr's, {dict,set,list} comprehension's,
 -  PARAMETER counts appended  {CALL,MAKE}_FUNCTION, BUILD_{TUPLE,SET,SLICE}

Finally we save token information.
    )print_function)copy)code2numiscodeop_has_argumentinstruction_size)_get_const_info)PYTHON3)intern)ScannerTokenc               @   s|   e Zd ZdddZedd Zedd Zed	d
 Zdi dfddZ	dd Z
dd Zdd Zdd Zdd ZdddZdS )Scanner2NFc             C   s  t j| ||| t| jj| jjg| _t| jj| jjg| _	d| _
tg | _t| jj| jj| jj| jj| jj| jj| jj| jj| jj| jj| jj| jj| jj| jj| jj| jj| jj| jj| jj| jj | jj!| jj"| jj#| jj$| jj%| jj&| jj| jj'g| _(t| jj| jj| jj| jj| jj| jj)| jj*| jj+| jj,| jj| jj-| jjg| _.tg | _/t| jj0| jj1| jj2| jj-| jj3| jj4| jj5| jj6| jj7| jj8| jj9| jjg| _:d S )Nz	<genexpr>);r   __init__	frozensetopcPJIFPJITpop_jump_ifJUMP_ABSOLUTEJUMP_FORWARDjump_forwardZgenexpr_namesetload_asserts
SETUP_LOOP
BREAK_LOOPSETUP_FINALLYEND_FINALLYSETUP_EXCEPT	POP_BLOCK
STORE_FASTDELETE_FASTSTORE_DEREFSTORE_GLOBALDELETE_GLOBAL
STORE_NAMEDELETE_NAME
STORE_ATTRDELETE_ATTRSTORE_SUBSCRDELETE_SUBSCRRETURN_VALUERAISE_VARARGSPOP_TOP
PRINT_EXPR
PRINT_ITEMPRINT_NEWLINEZPRINT_ITEM_TOZPRINT_NEWLINE_TOCONTINUE_LOOPZ	EXEC_STMTstatement_opcodesZSTORE_SLICE_0ZSTORE_SLICE_1ZSTORE_SLICE_2ZSTORE_SLICE_3UNPACK_SEQUENCEdesignator_opspop_jump_if_or_pop
BUILD_LISTBUILD_TUPLEBUILD_SLICEMAKE_FUNCTIONCALL_FUNCTIONZMAKE_CLOSUREZCALL_FUNCTION_VARCALL_FUNCTION_KWZCALL_FUNCTION_VAR_KWZDUP_TOPXvarargs_ops)selfversionshow_asmis_pypy r@   Y/home/psgendb/BIRCHDEV/python/lib/python3.6/site-packages/uncompyle6/scanners/scanner2.pyr   4   sz    
	
zScanner2.__init__c             C   s   t r| d> S | td> S dS )zReturn integer value of an EXTENDED_ARG operand.
        In Python2 this always the operand value shifted 16 bits since
        the operand is always 2 bytes. In Python 3.6+ this changes to one byte.
           N)r	   long)argr@   r@   rA   extended_arg_val   s    zScanner2.extended_arg_valc             C   s2   | j |r.| dd dkr.| t|d d S | S )znRemove __ from the end of _name_ if it starts with __classname__
        return the "unmangled" name.
           N__)
startswithlen)name	classnamer@   r@   rA   unmangle_name   s    zScanner2.unmangle_namec                s    rpd j d d  t|dr> fdd|j|j D }nf } fdd|jD } fdd|jD }n(t|dr|j|j }nf }|j}|j}|||fS )znRemove __ from the end of _name_ if it starts with __classname__
        return the "unmangled" name.
        _rG   co_cellvarsc                s   g | ]}j | qS r@   )rM   ).0rK   )rL   r<   r@   rA   
<listcomp>   s   z0Scanner2.unmangle_code_names.<locals>.<listcomp>c                s   g | ]}j | qS r@   )rM   )rP   rK   )rL   r<   r@   rA   rQ      s    c                s   g | ]}j | qS r@   )rM   )rP   rK   )rL   r<   r@   rA   rQ      s    )lstriphasattrrO   co_freevarsco_namesco_varnames)r<   corL   freenamesvarnamesr@   )rL   r<   rA   unmangle_code_names   s    

zScanner2.unmangle_code_namesc       '      C   s  |s
| j }| j|}|d,kr<x|j|D ]}t|j  q(W g }i }| jrRd|d< t| j}	| j||\}
}}|| _	t
 | _x| jd|	D ]x}| jr| j| | jj| jjfk}n| j| | jjk}|o| j|d  | jjkr|| j|d  dkr| jj|d  qW t| j}| j|}|| _| jd }| j| }i }x||	d k r| j| j|kr| j| | jjkr| j| | jjkrd||< n| j| | jjkrd	||< |}| j| }q:W d}x| jd|	D ]x}||krtd}xt|| d
dD ]z}d}| j|}|jdrB| jdkrB|tdd }|d-krBd| }|jt||t |d||f d
d |d7 }qW | j| }| j!|}d}d}t"|| j}|rX| j|| }d}|| jj#kr|| j$|7 }q|| jj%kr|j&| }t'|rd|}|j(dkr|dkst)d}n:|j(dkr,d}n(|j(dkr>d}n|j(dkrPd}nd}d|j( d  }n$|t|j&k rt*||j&\}} |}n|| jj+kr|| }n|| jj,kr| jdkr| j-||| t |d | }n||| jj.kr| jdkr| j-||| t |}nJ|| jj/kr&|| }n2|| jj0krB| jj1| }n|| jj2krX|
| }|| j3kr|| jj4kr| j| j5|  | jj6krqn4| jr| r|d!krd"}nd||f }|||< n$|| jj7kr| j8|}!|!|krd#}| j9| }"| j9|! }#| j:|#d  j;d$ko,| j:|"d  j;d%k}$|$r8d&}|| j<kr| j|d  | jj=| jj>fkr|| j?kr| j| j5|  | jj7ks| j|! | jj@ks|| jAkrd&}n>|| jjkr|| jkrd'}n|| jjBkr|| jCkrd(}| j?jD|d}%||kr&|jt|||||%||| j n"|jt|| ||||%||| j qW |d.kr~x|D ]}&t|&jEd*d+ q^W t  ||fS )/a&  
        Pick out tokens from an uncompyle6 code object, and transform them,
        returning a list of uncompyle6 Token's.

        The transformations are made to assist the deparsing grammar.
        Specificially:
           -  various types of LOAD_CONST's are categorized in terms of what they load
           -  COME_FROM instructions are added to assist parsing control structures
           -  MAKE_FUNCTION and FUNCTION_CALLS append the number of positional arguments
           -  some EXTENDED_ARGS instructions are removed

        Also, when we encounter certain tokens, we add them to a set which will cause custom
        grammar rules. Specifically, variable arg tokens like MAKE_FUNCTION or BUILD_LIST
        cause specific rules for the specific number of arguments they take.
        bothbeforer   PyPy   AssertionError   ZPRINT_ITEM_CONTZPRINT_NEWLINE_CONTT)reverseZ	COME_FROMZSETUP_g@NLOOPEXCEPTzCOME_FROM_%sz%s_%d)offsethas_argz<lambda>
LOAD_CONSTZLOAD_LAMBDAz	<genexpr>ZLOAD_GENEXPRz
<dictcomp>ZLOAD_DICTCOMPz	<setcomp>ZLOAD_SETCOMPZ	LOAD_CODEz<code_object >	BUILD_MAPZBUILD_MAP_n	JUMP_BACKr   r   CONTINUEZLOAD_ASSERTZRETURN_END_IFafter )Zline_prefix)r\   r]   )rc   rd   )r\   rl   )Fr>   Zbuild_instructionsget_instructionsprintdisassembler?   rJ   coder[   rY   r   r   op_ranger   r   r   LOAD_GLOBALget_argumentaddr   find_jump_targets	next_stmtlinesnextr.   r/   sortedopname_for_offsetrI   r=   appendr   reprop_namer   EXTENDED_ARGrE   Z	CONST_OPS	co_constsr   co_namer`   r   ZNAME_OPSJREL_OPSpatch_continueJABS_OPSZ	LOCAL_OPSZCOMPARE_OPScmp_opZFREE_OPSr;   r6   prevLOAD_CLOSUREr   
get_targetoffset2inst_indexinstsopnamestmtsr   r   
linestartsFOR_ITERnot_continuer*   return_end_ifsgetformat)'r<   rW   rL   Zcode_objectsr>   bytecodeinstrtokens	customizeZcodelenrX   rY   rZ   iZhave_pop_jumpZload_asserts_saveZjump_targets	last_stmtreplaceextended_argre   Zjump_idxjump_offsetZcome_from_namer~   Zcome_from_typeopopargZpattrrf   constargvalrN   targetjZtarget_indexZis_continueZ	linestarttr@   r@   rA   ingest   s8   



























zScanner2.ingestc             C   s  | j }d}t|}t| jj| jjf| jj| jjf| jj| jjf| jj| jjfg}| j||| j	}t
| }| _t
 }x|D ]}xz| j||t|d  D ]^}	d}
x2|D ]*}|||	 krd}
P |	t||	 | j7 }	qW |
r| j|	 }	|j|	 |j|	 qW q|W |rt|}|j  n|}d	}g | _g  }| _d}	x|D ]}|| | jjkr||kr| j|}||ks| j| j| j| jkr|j| q<| j| }x"|| | jjkr| j| }qW | jdkr| j|dkr|j| q<n|| | jjkrZ|| j|  }|| jjksJ| jdk r|| jj| jj| jjfkr|j| q<nh|| | jkr| j| }x || | jkr| j| }qvW | jdkr|| | jjkr|j| q<|}||g||	  7 }|}	q<W ||g|t|  7 }d S )
Nr   ra   TFgffffff@LIST_APPENDg@g @) rq   rJ   r   r   r   r   r   r   	all_instrr1   r   r   rr   r   r   ru   listsortrw   r   rx   Zl_noremover=   r{   r,   ROT_TWOZJUMP_IF_FALSEZJUMP_IF_TRUEr*   r3   r   )r<   rq   startendZstmt_opcode_seqsZprelimr   Z
pass_stmtsseqr   matchelemZ	stmt_listr   slistsr   r   r   r@   r@   rA   build_statement_indices  s    






$






z Scanner2.build_statement_indicesc       	      C   s  | j | | jjkr| j|t| j | jj}|r| j| j| }| jdk r| j | | j	kr| j
j| | j|}| j| }| j | | jjkr| j |d  dkrdS || j| j	B kr| jj| dS | jj| | j
j| |S d}d}x| j|t| j D ]}| j | }|| jjkrz||krp| jdkrT| j | j|  | j	t| jjgB ksTt| j
j| j|  | j| S |d7 }q|| jkr|d7 }qW dS )z
        Return the next jump that was generated by an except SomeException:
        construct in a try...except...else clause or None if not found.
        g@ra   
   Nr   )rq   r   DUP_TOPZfirst_instrrJ   r   r   r   r=   r   r   ru   
COMPARE_OPr   	ignore_ifrr   r   r   r*   r`   Z	setup_ops)	r<   r   Zexcept_matchjmpZprev_offsetZcount_END_FINALLYZcount_SETUP_r   r   r@   r@   rA   next_except_jump*  s>    






zScanner2.next_except_jumpc       8      C   s  | j }| jd }|d }|d }xR| jD ]H}|d }	|d }
|	|  koN|
k n  r(|	|kr(|
|kr(|	}|
}|}q(W || jjkr| j| j|  }|t|| j7 }|j}| j||}|| j	|< || j
|< ||kr|| j|< | j| \}}| j||| jj|d}|r| jdk rl|d }| j| j| j|   }| j||| }||ksf||d  | jj| jjgkrd}n|d }| j| j|  }|r|| j| kr|| | jkr|| j|  | jjks|| j|  | jjkr|| | jjkrd}|s| j||| jj}|sdS |d	7 }d}| jdk rp|| j|  | jjkr|| j| j|   | jkr| j| j|  }n || j|  | jkr| j| }|rd
}| jj| | jdk r|| j|  | jjkr| jj| j|  nd}|}|d }n| j||kr| j||| jj|d}||d kr||| | jkr|||d  | jkr| j|d | j|kr|d | j|< |d }n ||k r|d | j|< |d }| j|| jj}| jdkr|| | jj| jjfkrd}nd
}| jdk r| j | j|  | jjkr| j| j|  }n
| j| }||kr.d}n<| j | | jjkrj| j|}| jj| ||d krj|}| jj| | jj| | jj|d ||d |d |kr| jj|d |d |d 
n|| jj kr|t|| j }| j||}| j||}||kr|| j|< | jjd|d |d d | j| j|  }}|}d}xr|t!| j k r| j | | jj"kr|dkr~P n|d	8 }n| j | | jj kr|d	7 }|t|| | j7 }qLW |}x|t!| j k r||k r| j#|}|dkr | j$| }q| j | | jjkr6| jjd||d	 d |d	 }np| j|}||krT| j|}| j | | jjkr| jdkr|| j|< n
d#| j|< | jjd||d |d }qW ||kr| j||} | jdkr | jjd|d	 | d | | j|< n|d	 | j|< n|| jkr| j||}| j||}!||!krN|d dkrN|!| j|< dS |}"|d }| j}#|}| jdk r||#|  | jjkr|#| }| j}$n| j%| jB }$||#|  |$kr||kr|#| | j|< | jjd||#| d dS |#|! }%|| jj&k
r| j'|| j$| | jj&|}&|&r||% | jk	r|%| j(k	r| j| j|%||!k	r||#|%  | jjkr| j)|gr|| j|#|% kr|#|% | j(ks| j|#|% |#|% krd	t!| j)| j'||#|% | j|krܐ
q||#|%  | jjk	r^| j)|g	r^d	t!t*| j)| j'||#|% | j|t*| j)| j'||#|% | jj&| jj+| jjf|%dB k	r^nd}'| j,|| j$| | jj&}(d})xF|(D ]>}*|| j|*k	r| j|* j-|*d k	r|)	r|*}'P nd})	qW |'	p|&d$ | j|< dS n8| jdk 
r|d d%k
r|!| j|< n|&d& | j|< dS n| jdk 
rH||d  | jjk
rH|d }+n|d }+|+| j.k
r~||% | jj/k
rrdS | j.j0|+ | j$| },|#|, |k
rn
||, | jkr|| j|,kr||#|,  | jj&kr||, | jjks
||!ks
||#|%  | jj| jjfkr|#|, | j|< dS n||, | jjkr|| | jkr| j|,}-| j||-krl|#|, | j|< dS ||- | jkr| j|-| j|kr|#|, | j|< dS || jkrdS | jdkr^||% | jjkr^|%| j(kr^|%|kr^|#|% |kr^||! | jjkrR||!d  | jjkrR||#|%  | jjkr6n| j|#|% |krLn|%}!n|%}!|#|! }%||% }.|.| jkr| j|%}/|/|%k r|#|/ | j	kr|/|krdS |t| j | | j }0| j |0 }1| j1|1dkr| j|0|1}|| j
kr| jjd|"|d || j|"< dS | j|/|}d}2d| j  ko4dkn  r| j2|"j3dr||"d	  }3| j2|3|" d d kr|3|" }4||4d	  }5| j2|4}6|6dkr|5d	kr| jjd|d |%d || j4|< n|6d!krd|d |%d}2n$| jdkr| jjd|d |%d |%| j5ks | jdk r,| jj|% |!|k r|2r|6d!kr| j|4||4 }| j2|dkr| j||| }7||7kr| jj|2 || j4|< | jjd|!|d n|.| jjkr| jdks|%| jkr| j | j|  | jj6ks| j | j| d	  d"kr| jjd||!d |!| j4|< | jdksF||%d	  | jjkr|!| j|< | jdkr| j| j|#|%   j7r| j8j|#|%  n| j8j|% n*|| j%kr| j||}| j||| j|< dS )'zs
        Detect type of block structures and their boundaries to fix optimized jumps
        in python2.3+
        r   r   r   Fg@   r_   Nra   whileforg @zwhile 1z-loop)typer   r   z-elsetryexceptg@ztry-elser   zand/orTrootfor-loopif-thenelser   z
while-loopg@ZJUMP_IFr,   r   r   r   r   )r   r   r   r   r   r   )9rq   structsr   r   r   r   r   r   Zrestrict_to_parentsetup_loop_targetssetup_loopsfixed_jumpsrx   Z
last_instrr   r=   r   r   r   r   r*   r   r,   r   r   ru   r   GET_ITERZJUMP_OPsr   loopsr|   r   rJ   r   r   rw   r4   r   rem_orr   Zremove_mid_line_ifsr   r   r   ry   r   r+   r   r~   r{   rI   thensr   r   is_jump_targetr   )8r<   re   r   r   rq   parentr   r   structZcurrent_startZcurrent_endinstZsetup_targetZloop_end_offsetZline_noZnext_line_byteZjump_back_offsetZjump_forward_offsetZreturn_val_offset1Zjump_targetZ	if_offsetZ	loop_typeZtest_op_offsetZtest_targetr   Z
end_offsetZend_elseZ
start_elseZend_finally_offsetZsetup_except_nestr   r   Z
r_end_elseZrtargetZjump_if_offsetpreZtest_setZpre_rtargetr   ZfixZjump_ifsZlast_jump_goodr   Zassert_offsetry   Znext_targetZcode_pre_rtargetZif_endZnext_offsetZnext_opZif_then_maybeZjump_if_targetZ	jump_instr   Zjump_opZ
end_targetr@   r@   rA   detect_control_flowX  s   



























    "





















zScanner2.detect_control_flowc             C   s(  | j }t|}dd|d dg| _g | _i | _t | _| j  t | _t | _	i | _
i | _i | _i }d}x| jd|D ]}|| }|| jjkrt||d |B }|| j|7 }qx| j||| t|| jr| jj|}	| j|}
|	dkrZ|| jjkr| j|dkr|d |
 }	n>| jdkrZ|| jjkrZ|| jj| jjfkrZ|
|krZ|
}	|	dk	r|	dkr| jdkr|	| jkr| j|	 }n|}|j|	g |g ||	< q||	 | jjko|| j|	  | jjks||d  | jjkp||d  | jjko||d	  | jjk}|r2|| jj kr2d
}|s|t| jkr|	| jkr`| j|	 }n|}| jdks| j | | jj!ks| j |	 | jj kr|j|	g |g ||	< nF|| jjkr|| jkr| jdkr| j| }	|j|	g |g ||	< d}qxW |dkr$t"| ddl#}|j#| j |S )a  
        Detect all offsets in a byte code which are jump targets
        where we might insert a pseudo "COME_FROM" instruction.
        "COME_FROM" instructions are used in detecting overall
        control flow. The more detailed information about the
        control flow is captured in self.structs.
        Since this stuff is tricky, consult self.structs when
        something goes amiss.

        Return the list of offsets. An instruction can be jumped
        to in from multiple instructions.
        r   r   ra   )r   r   r   Nr   r_   g@r   Fg@r\   rl   r   )r\   rl   )$rq   rJ   r   r   r   r   r   r   r   r   r   r   r   rr   r   r   r   rE   r   r   r   rt   r   r~   r=   r   JUMP_IF_FALSE_OR_POPJUMP_IF_TRUE_OR_POPr,   r   r*   r   r   r   ro   pprint)r<   debugrq   ntargetsr   re   r   rD   labelr   sourceZskip_come_fromppr@   r@   rA   rv     s    


	

zScanner2.find_jump_targetsc             C   sZ   || j j| j jfkrVt|}|dkrV|d jdkrV| j|d  | j jkrVtd|d _d S )NrF   ra   rj   r_   rk   r   r   )r   r   r   rJ   kindrq   r   r
   )r<   r   re   r   r   r@   r@   rA   r   _  s    zScanner2.patch_continuec          
   C   s  |dkr|t | jkr||ks"tyd|k W n   |g}Y nX g }xp| j||D ]`}| j| }||krT|dkr~|j| qT| j||}	|r|	|kr|j| qT|	|krT|j| qTW | j||| jj}
g }xJ|
D ]B}| j|d }x&|D ]}||kp||kr|j| qW |}g }qW |S )aR  
        Find all <instr> in the block from start to end.
        <instr> is any python bytecode instruction or a list of opcodes
        If <instr> is an opcode with a target (like a jump), a target
        destination can be specified which must match precisely.

        Return a list with indexes to them or [] if none found.
        r   Nr_   )	rJ   rq   r`   rr   r|   r   r   r   r   )r<   r   r   r   r   Zinclude_beyond_targetZinstr_offsetsr   r   r   ZpjitsfilteredZpjitZtgtr@   r@   rA   r   o  s4    
"


zScanner2.rem_or)NF)NF)__name__
__module____qualname__r   staticmethodrE   rM   classmethodr[   r   r   r   r   rv   r   r   r@   r@   r@   rA   r   3   s&   
\	  W.      r   __main__)PYTHON_VERSIONg       @g      @Nz'Need to be Python 2.x to demo; I am %s.)__doc__
__future__r   r   Zxdisr   r   r   r   Zxdis.bytecoder   
uncompyle6r	   sysr
   Zuncompyle6.scannerr   r   r   r   r   inspectcurrentframef_coderW   r   r   r   r   ro   r@   r@   r@   rA   <module>"   s<             p

