3
^                 @   s   d Z ddlmZmZmZ ddlmZ ddlmZ ddlZddl	j
jZddlmZ ddlZe jej G dd deZed	krdd
lmZ edk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 37 bytecode scanner/deparser base.

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.
    )iscodeinstruction_sizeInstruction)_get_const_info)TokenN)Scannerc                   sV   e Zd Zd f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	  Z
S )Scanner37BaseNFc                sv  t t| j||| | jdk rN| jj| jj| jjg}t|t| jjg | _	n$| jjg}t|| _	d| j_
d| j_|j| jj t|| _t| jj| jjg| _d| _| 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	B | _%t| jj| jj| jj| jj| jj| jj| jj&| jj$| jj'g	| _(t| jj)| jj*g| _+t| jj)| jj*| jj,| jj-g| _.| jj-| jj/f| jj-| jj$f| jj,| jj/f| jj,| jj$fg| _0t1| jj2| jj3| jj4| jj5| jj6| jj&| jj"g}|j7| jj8 |t1| jj9| jj:| jj;| jj<gO }|j7| jj= t>dj? | _@t|| _Ad S )Ngffffff@P   w   END_FINALLY	POP_BLOCKz4
            default keyword-only annotation closure)r   r   )Bsuperr   __init__versionopc
SETUP_LOOPSETUP_EXCEPTSETUP_FINALLY	frozensetZsetup_ops_no_loop
BREAK_LOOPCONTINUE_LOOPappend
SETUP_WITH	setup_opsZPJIFZPJITpop_jump_tfnot_continue_followr   
STORE_FASTDELETE_FASTSTORE_DEREFSTORE_GLOBALDELETE_GLOBAL
STORE_NAMEDELETE_NAME
STORE_ATTRDELETE_ATTRSTORE_SUBSCRPOP_TOPDELETE_SUBSCRr   RETURN_VALUERAISE_VARARGS
PRINT_EXPRJUMP_ABSOLUTEstatement_opcodesUNPACK_SEQUENCE	UNPACK_EXdesignator_opsJUMP_IF_FALSE_OR_POPJUMP_IF_TRUE_OR_POPjump_if_popPOP_JUMP_IF_TRUEPOP_JUMP_IF_FALSEZpop_jump_if_popJUMP_FORWARDstatement_opcode_sequencesset
BUILD_LISTBUILD_TUPLE	BUILD_SETBUILD_SLICE	BUILD_MAPaddZCALL_METHODBUILD_SET_UNPACKBUILD_MAP_UNPACKBUILD_LIST_UNPACKBUILD_TUPLE_UNPACKBUILD_CONST_KEY_MAPtuplesplitMAKE_FUNCTION_FLAGSvarargs_ops)selfr   show_asmis_pypyr   r,   rF   )	__class__ ^/home/psgendb/BIRCHDEV/python/lib/python3.6/site-packages/uncompyle6/scanners/scanner37base.pyr   1   s    






zScanner37Base.__init__c       +         s   fdd}|s j } j|}|dEkrJx|j|D ]}t|j  q6W i } jr\d|d< t  _g i  _t	 j
}	xt j
D ]\}
}|jdko|
d |	k }|r j
|
d  }|jd	ko|jd
ko|jr j j|j  } j
| }|jjdr jj|j qW xt j
D ]z\}
}|jdkr j
 j|j  }|jr|jjdrt|j|j|j|j|j|j|j|j|j|j|j|j j
|
< qW  j|}d}d}xt j
D ]\}
}|j}|j}|jdkr |
d |	k r  j
|
d  j jjkr q|j|krd}xt ||j ddD ]}d} j!|}|dkrZt"j#| j|} j!|}|jdr|t	dd }d| }n|j j$krd}||t%||t&|d|j|f d jdd}|d7 }q$W nD|j j'kr j'|j }||t%ddt&|d|j d j|jd}|j}|j}| jj(kr|}t)|r|j*dkrZ|dksTt+d}nL|j*dkrld}n:|j*d kr~d!}n(|j*d"krd#}n|j*d$krd%}nd&}d'|j* d( }nHt,|t-rd)}n6t,|jt.r|jt	|j/k rt0|j|j/\}}|}n\|d*kr d+|jkr^d,}n>|dFkr|} d/|  }g }!x* j1D ] }"| d@ }#|!j2|# | dL } qBW |!dd0 }!||t%||!||j|j||j j|jd1	}qn| j3kr|}$ jr|$ r|d2krd3}nd4||$f }nz jr|d5krd||< n\|d6krF|d7@ }%|d8? d7@ }&d9|%|&f }|%|&f}d:||%|&f }n| jj4krL|} j5|j}'|'|jkr^ j
|
d  j}( j
 j|'  jd;ko j
|
d  jdk}) j6d<k r|)s|j j7kr|jr|( j8krd=}nLd>}dG j9d>kr2dH j:|kr2dI j9d@kr"dJ= nt;j<d=dK _9|r^|d=kr^d}qn|j jkr^dA}|d@k}||t%||||j|j||j j|jd1	}qW |dLkrxD ]}*t|*j=dCdD qW t  |fS )Ma&  
        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.
        c                s2   j | |  j|j< | d7 } | tks.t| S )N   )r   offset2tok_indexoffsetlenAssertionError)jtoken)rG   tokensrK   rL   tokens_append   s
    
z+Scanner37Base.ingest.<locals>.tokens_appendbothbeforer   PyPyr3   rM   LOAD_GLOBALrQ   r)   r5   JUMPFEXTENDED_ARGT)reverseZ	COME_FROMZSETUP_NzCOME_FROM_%sZCOME_FROM_EXCEPT_CLAUSEz%s_%s)rO   has_argr   has_extended_argELSEz%sz<lambda>
LOAD_CONSTZLOAD_LAMBDAz	<genexpr>ZLOAD_GENEXPRz
<dictcomp>ZLOAD_DICTCOMPz	<setcomp>ZLOAD_SETCOMPz
<listcomp>ZLOAD_LISTCOMPZ	LOAD_CODEz<code_object >ZLOAD_STRIMPORT_NAME.ZIMPORT_NAME_ATTRMAKE_FUNCTIONMAKE_CLOSUREzMAKE_FUNCTION_%d   )	opnameattrpattrrO   Z	linestartopr]   r   r^   r<   ZBUILD_MAP_nz%s_%dZJUMP_IF_NOT_DEBUGr.         z%d before vararg, %d afterz%s_%d+%dFOR_ITERgffffff@ZCONTINUEZ	JUMP_BACK   r   ZLOAD_ASSERTafter )Zline_prefix)rV   rW   )rd   re   rq   rq   rq   )rV   ro   )>rH   Zbuild_instructionsget_instructionsprintdisassemblerI   r7   Zload_assertsrN   rP   insts	enumeraterg   argvalZoffset2inst_indexprev_op
startswithr=   rO   r^   r   opcodeZoptype	inst_sizeargargreprr]   starts_lineis_jump_targetfind_jump_targetsr   rd   sortedZopname_for_offsetxdisnext_offsetexcept_targetsr   repr
else_startZ	CONST_OPSr   co_namerQ   
isinstancestrint	co_constsr   rE   r   rF   r+   
get_targetr   stmtsr   kindrh   sysinternformat)+rG   co	classnameZcode_objectsrH   rU   bytecodeinstr	customizeniinstZassert_can_followZ	next_instZ	raise_idxZ
raise_instZ	jump_instZjump_targetsZlast_op_was_breakrR   rx   rj   Zjump_idxZjump_offsetZcome_from_namerg   kZcome_from_typeZ
end_offsetri   const_flagsrh   flagbitZpos_argsZbefore_argsZ
after_argstargetZnext_opnameZis_continuetrK   )rG   rT   rL   ingest   s   

	



(




 



 

zScanner37Base.ingestc             C   s  | j }t|}dd|d dg| _g | _i | _i | _t | _| j  i | _	t | _
t | _i | _i | _i }xJt| jD ]:\}}|j}|j}| j||| |jr~| jj|}	|j}
| j | | jjkrtj|| j|}tj|| j|}ntj|| j|}|	dkrR|| jjkr*|| jjkr*||
 }	n(|| jjkrR|| jkrR|
|krR|
}	|	dk	r|	dkr|j|	g |g ||	< qx|| jjkrx|| jkrx| j| }	|j|	g |g ||	< qxW |d	krddl}|j| j |S )
a  
        Detect all offsets in a byte code which are jump targets
        where we might insert a COME_FROM instruction.

        Return the list of offsets.

        Return the list of offsets. An instruction can be jumped
        to in from multiple instructions.
        rootr   rM   )typestartendNrV   ro   rq   )rV   ro   ) coderP   structsloopsfixed_jumpsr   r7   	ignore_ifbuild_statement_indicesr   not_continuereturn_end_ifsZsetup_loop_targetssetup_loopsrw   rv   rO   r{   detect_control_flowr]   getr}   r   r[   r   r   hasjrelrm   hasjabsr2   r   pprint)rG   debugr   r   targetsr   r   rO   rj   labelZopargrR   r   pprK   rK   rL   r     sT    





zScanner37Base.find_jump_targetsc             C   s|  | j }d}t| }}| j||| j}t| }| _t }x| jD ]}x~| j||t|d  D ]b}	d}
x2|D ]*}|||	 krd}
P |	t||	 | j	7 }	qnW |
dkr`| j
|	 }	|j|	 |j|	 q`W qBW |rt|}|j  n|}g  | _}d}d}	xh|D ]^}|| | j	jkr||kr| j|}||ksN| j| j| j| jkr\|j|  q| j
| }x"|| | j	jkr| j
| }qhW || | j	jkrB|j|  qn|| | j	jkr|| j
|  | j	jkr|j|  qn\|| | jkrB| j
| }x || | jkr | j
| }qW || | j	jkrB|j|  q||g||	  7 }|}|}	 qW ||g|t|  7 }d S )Nr   rM   TFrq   )r   rP   Zinst_matchesr,   r7   r   r6   op_ranger   r   ry   r=   listsortZ	next_stmtr+   r   linesZl_noremoveLIST_APPENDr&   ROT_TWOr/   rm   )rG   r   r   r   ZcodelenZprelimr   Z
pass_stmtssequencer   matchelemZstmt_offset_listslistZlast_stmt_offsetZstmt_offsetr   rR   rK   rK   rL   r   W  sl    














z%Scanner37Base.build_statement_indicesc              C   s  | j }| j| }|j}| jd }|d }|d }	xR| jD ]H}
|
d }|
d }||  ko^|k n  r8||kr8||	kr8|}|}	|
}q8W | jdk o|| jjkr||j7 }| j|}| j	||}	|| j
|< ||	kr|	| j|< | j| \}}| j||	| jj|d}|rtj|| | j|}nd}| j| j|	  }|r|| j|	 kr| j|r|| j|	  | jjks|| j|	  | jjkr|| | jjkrd}|s*| j||	| jj}|sdS | j|}| j|j|}d}|| j|  | jkr| j| }|r
d}| jj| nd}|}tj|| | j|}	n.| j||krP| j||	| jj|d}| j|}| j|j|}|	|kr| j|	r| j|r| j|| j|	kr|| j|< |}	n||k r|| j|< |}	| j|}|| | jj| jjfkrd}nZd}| j| }||krd	}n<| j | | jjkrL| jj| | j|}||d
 krL|}| jj| | jj| | jj|d ||d tj|| | j|}||	kr| jj|d ||	d n\|| jkr|j }|| j|< n<| jdk r|| jj!kr| j|}| j	||}	|	| j|< n|| jj"krtj|| j|}| j|}||kr|| }| jj|kr| jj#|tj|| j| kr|| j|< || j$|< n|| jj%kr| j|}| j	||}	|	| j|< nN|| j&kr4| j|}||kr| j||| jj'|}|r ||d
  | jj(kr || j|< n| j	||| j|< n|| jjkrtj|| j|}|t)|k r|| | jjkr|| j*kr| j*j+| n|| jj'kr| j|}| j| }|| | jjkr|| j*kr|}x4||kr|| t,j't,jgkrdS | j| }qW | j*j+| dS )zs
        Detect type of block structures and their boundaries to fix optimized jumps
        in python2.3+
        r   r   r   gffffff@FNwhileforzwhile 1   z-loop)r   r   r   z-else)-r   rv   r{   r   r   r   r   r|   r   Zrestrict_to_parentr   r   r   Z
last_instrr+   r   r   prevry   Zis_jump_forwardr(   r   Zget_instr   r   r=   rm   GET_ITERZJUMP_OPsr   r   r   rx   r   
POP_EXCEPTr   r   r   r2   r5   r   rP   r   r   op3) rG   rO   r   Z
inst_indexr   r   rj   parentr   r   structZcurrent_startZcurrent_endr   Zline_noZnext_line_byteZ	jump_backZjump_forward_offsetZreturn_val_offset1Zjb_instZ	if_offsetZ	loop_typeZjb_next_offsettestZtest_targetZafter_jump_offsetr   Znext_opZunop_targetZrtargetZrtarget_prevr   rK   rK   rL   r     s   

























z!Scanner37Base.detect_control_flowc             C   s&   | j | | jjkrdS || j||kS )z
        Return True if the code at offset is some sort of jump back.
        That is, it is ether "JUMP_FORWARD" or an absolute jump that
        goes forward.
        F)r   r   r+   r   )rG   rO   extended_argrK   rK   rL   is_jump_backx  s    zScanner37Base.is_jump_backc             C   s  | j | | jjkrZ| j|t| j | jj}|rZ| j| j| }| jj	| | j
j	| |S d}d}x| j|t| j D ]}| j | }|| jjkr||kr| j | j|  t| jj| jj| jjgkst| j
j	| j|  | j| S |d7 }qv|| jkrv|d7 }qvW 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.
        r   rM   N)r   r   DUP_TOPZfirst_instrrP   r4   ry   r   r   r=   r   r   r   r   r+   r5   r(   rQ   Zsetup_opts_no_loop)rG   r   Zexcept_matchZjmpZcount_END_FINALLYZcount_SETUP_r   rj   rK   rK   rL   next_except_jump  s.    



zScanner37Base.next_except_jump)NF)__name__
__module____qualname__r   r   r   r   r   r   r   __classcell__rK   rK   )rJ   rL   r   0   s      YJZ H
r   __main__)PYTHON_VERSIONg@zHNeed to be Python 3.7 or greater to demo; I am version {PYTHON_VERSION}.)__doc__r   r   r   r   Zxdis.bytecoder   Zuncompyle6.scannerr   Zxdis.opcodes.opcode_37ZopcodesZ	opcode_37r   r   r   globalsupdateopmapr   r   
uncompyle6r   inspectcurrentframef_coder   r   rT   r   r   rt   rK   rK   rK   rL   <module>   s8         |

