3
/*^                 @   s  d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	m
Z
 ddlZddljjZddlmZ ddlZddlmZ erzejZe jej G d	d
 d
eZedkr
d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 3 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)iscodeinstruction_size)_get_const_info)Tokenparse_fn_countsN)Scanner)PYTHON3c                   s`   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	dddZ
  ZS )Scanner3NFc                s  t t| j||| | jdk rN| jj| jj| jjg}t|t| jjg | _	n| jjg}t|| _	| jdkrz|j
| jj t|| _| jdkrt| jj| jjg| _d| _n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$g}| jdk rX|| jj%| jj&g7 }t|| j	B | _'t| jj| jj| jj| jj| jj| jj| jj(| jj$| jj)g	| _*| jdkr,t| jj+| jj,g| _-t| jj+| jj,| jj.| jj/g| _0| jj/| jj1f| jj/| jj$f| jj.| jj1f| jj.| jj$fg| _2n:tg | _-tg | _0| jj1f| jj$f| jj1f| jj$fg| _2t3| jj4| jj5| jj6| jj7| jj8| jj(| jj"g}|s| jdkr|j9| jj: | jdkr|t3| jj;| jj<| jj=| jj>gO }| jd	kr|j9| jj? t@d
jA | _Bt|| _Cd S )Ngffffff@g	@g      @END_FINALLY	POP_BLOCKPOP_TOPg@g      @g@z9
                 default keyword-only annotation closure)r   r   r   )r   r   )Dsuperr
   __init__versionopc
SETUP_LOOPSETUP_EXCEPTSETUP_FINALLY	frozensetZsetup_ops_no_loopappend
SETUP_WITH	setup_opsJUMP_IF_FALSEJUMP_IF_TRUEpop_jump_tfnot_continue_followZPJIFZPJITr   
STORE_FASTDELETE_FASTSTORE_DEREFSTORE_GLOBALDELETE_GLOBAL
STORE_NAMEDELETE_NAME
STORE_ATTRDELETE_ATTRSTORE_SUBSCRr   DELETE_SUBSCRr   RETURN_VALUERAISE_VARARGS
PRINT_EXPRJUMP_ABSOLUTE
BREAK_LOOPCONTINUE_LOOP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_FALSE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.   rI   )	__class__ Y/home/psgendb/BIRCHDEV/python/lib/python3.6/site-packages/uncompyle6/scanners/scanner3.pyr   ;   s    	










zScanner3.__init__c       .      C   s\  |s
| j }| j|}|dLkr<x|j|D ]}t|j  q(W g }i }| jrRd|d< t | _t| j	}	xt
| j	D ]\}
}| jdkr|jdko|
d |	k }|r| j	|
d  }|jdMko|
d |	k }|}n|jdNko|
d |	k }|}|rp| j	|
d  }|jdkrp|jdkrp|jrp| j| j|j  }| j	| }|jjdrp| jj|j qpW | j|}d}xt
| j	D ]\}
}|j}|j}|jdkr|
d |	k r| j	|
d  j| jjkrqb|j|kr|d}xt||j ddD ]}d}| j|}|dkr
tj|| j|}| j|}|jdr0|tdd }d| }n|j| jkrBd}|jt||t|d|j|f d| jd |d7 }qW n@|j| jkr| j|j }|jtddt|d|j d| jd |j }|j}|| jj!kr|}t"|r`|j#dkr|dkst$d}nL|j#dkrd }n:|j#d!kr(d"}n(|j#d#kr:d$}n|j#d%krLd&}nd'}d(|j# d) }n`t%|t&stj'd*krt%|t(rd+}n6t%|j)t*r|j)t|j+k rt,|j)|j+\}}|}n,|dOkr| jd.kr$|} d/|  }g }!x*| j-D ] }"| d@ }#|!j|# | dL } qW |!dd0 }!n`t.|j\}$}%}&d1|$|%|&f }|%dkrXd2||%f }|&dkrnd3||&f }d4||$f }|$|%|&f}!|jt||!||j|j/||j0| jd5 qbn>|| j1kr|}$| jr|$ r|d6krd7}nd4||$f }n| jr6|dPkr6|d8krd||< n| jd.kr|d:krd;}n|d<krz|d:@ }'|d=? d:@ }(d>|'|(f }|'|(f}d?||'|(f }nv|| jj2kr|}| j3|j})|)|jkr| j	|
d  j}*| j	| j|)  jd@ko| j	|
d  jdAk}+| jdkr*| j	|
d  jdAkr*|+ r*| j| j|)  },| j	|, jdBk}+|+sR|j| j4krX|j/rX|*| j5krXdC}nJdD}|dQ j6dDkr|dR j7|kr|dS j6dFkr|dT= nt8dC|dU _6|r|dCkrd}qbn4|| jj9kr|j| j:krdG}n|j| jkrdH}|dFk}|jt||||j|j/||j0| jd5 qbW |dVkrTx|D ]}-t|-j;dJdK q4W t  ||fS )Wa&  
        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   PyPyg      @r      r   r   r5   r6   LOAD_GLOBALAssertionErrorr)   FEXTENDED_ARGT)reverseZ	COME_FROMZSETUP_NzCOME_FROM_%sZCOME_FROM_EXCEPT_CLAUSEz%s_%s)offsethas_argr   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 >g@ZLOAD_STRMAKE_FUNCTIONMAKE_CLOSUREg@zMAKE_FUNCTION_%d   z,%d positional, %d keyword only, %d annotatedz%s_N%dz%s_A_%dz%s_%d)opnameattrpattrrX   Z	linestartoprY   r   r?   ZBUILD_MAP_nJUMP_IF_NOT_DEBUGCALL_FUNCTION   CALL_FUNCTION_KWr0      z%d before vararg, %d afterz%s_%d+%dFOR_ITERr8   r   ZCONTINUEZ	JUMP_BACK   r,   ZRETURN_END_IFZLOAD_ASSERTafter )Zline_prefix)rP   rQ   )r   r   )r5   r6   )r]   r^   )rd   re   rm   rm   rm   )rP   rk   )<rK   Zbuild_instructionsget_instructionsprintdisassemblerL   r:   Zload_assertsleninsts	enumerater   r`   argvaloffset2inst_indexprev_op
startswithr@   rX   find_jump_targetsopcoder   r]   sortedZopname_for_offsetxdisnext_offsetexcept_targetsr   r   repr
else_startargreprZ	CONST_OPSr   co_namerU   
isinstancestrPYTHON_VERSIONunicodeargint	co_constsr   rH   r   starts_linerY   rI   r+   
get_targetstmtsr   kindra   internr(   return_end_ifsformat).rJ   co	classnameZcode_objectsrK   bytecodeinstrtokens	customizeniinstZassert_can_followZ	prev_instZjump_if_instZ	next_instZ	raise_idxZ
raise_instZjump_targetsZlast_op_was_breakru   rc   Zjump_idxZjump_offsetZcome_from_namer`   jZcome_from_typeZ
end_offsetrb   const_flagsra   flagbitZpos_argsZname_pair_argsZannotate_argsZbefore_argsZ
after_argstargetZnext_opnameZis_continueZtarget_prevtrN   rN   rO   ingest   s   

	






(



$ 







" 

zScanner3.ingestc             C   s  | j }t|}dd|d dg| _g | _i | _i | _t | _| j  i | _	t | _
t | _i | _i | _i }xTt| jD ]D\}}|j}|j}| j||| |jr| jj|}	|j}
| jdkr| j | | jjkrtj|| j|}tj|| j|}ntj|| j|}|	dkr\|| jjkr4|| jjkr4||
 }	n(|| jjkr\|| jkr\|
|kr\|
}	|	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   rS   )typestartendg@NrP   rk   rm   )rP   rk   )!coderr   structsloopsfixed_jumpsr~   r:   	ignore_ifbuild_statement_indicesr   not_continuer   Zsetup_loop_targetssetup_loopsrt   rs   rX   rz   detect_control_flowrY   getr   r   r   rV   r|   r}   hasjrelri   hasjabsr4   r   pprint)rJ   debugr   r   targetsr   r   rX   rc   labelZopargr   r}   pprN   rN   rO   ry   "  sT    





zScanner3.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   rS   TFrm   )r   rr   inst_matchesr.   r:   r   r9   op_ranger   r   rw   r@   listsort	next_stmtr+   r   linesZl_noremoveLIST_APPENDr   ROT_TWOr1   ri   )rJ   r   r   r   ZcodelenZprelimr   Z
pass_stmtssequencer   matchelemZstmt_offset_listslistZlast_stmt_offsetZstmt_offsetr   r   rN   rN   rO   r   k  sl    














z Scanner3.build_statement_indicesc       1      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 }| j	||}| j}||kr
|d dkr
|| j|< dS | j|| }|j| j!krz||krz|j"|krz| jdk sT|j |krz|j"| j|< | jjd||j"d dS || }|| jj#kr| j$|| j%| | jj#|}|r| j|}|r~|| j&kr~| j	| j|||kr~|||  | jjkrn| j'|grn|| j|| krn|| | j&ksD| j|| || krndt(| j'| j$||| | j|krnq|||  | jjkr| j'|grdt(t)| j'| j$||| | j|t)| j'| j$||| | jj#| jj*| jjf|dB krn| jdkrd} | j+|| j%| | jj#}!d}"xF|!D ]>}#|| j|#krZ| j|# j,|#d
 kr^|"r^|#} P nd}"q"W | pp|d | j|< dS n4| jdk r|d | j|< n||kr|| j|< dS n| j%| }$||$ |krn| j|$rN|| j|$krN|||$  | jj#kr||$ | jj-ks:||ks:|||  | jj| jjfkr||$ | j|< dS nF||$ | jjkr| j|r| j|| j|$kr||$ | j|< dS || jkrdS || | jjk}%|%r"|| j&kr"||kr"|| |kr"|| | jjko||d
  | jjko|||  | jjk r"|}| jdk r@| jj| jj.f}&n
| jjf}&| j|sh|%	r<| jdk	r<| j|}'|'|k r| jdk r|||'  | jjkr|'|krdS | j	|'|}	| jjd||d | jj| ||	k r|| | jj/| jjfkr|||  | jj0| jj/fkr| jjd||	d |	| j1|< q| j2|d	rr|}'| jjd||d | jj| q|| |&kr| jjd||d || }(| j3	r||( | jj4k	r| jj5||(d   dk	rdS | jdk
r| jdk 
r|| | jj6k
rdS |})||) | jjk
r.|)t7| j |) | j7 })||) | jjk
rV|)t7| j |) | j7 })|)|k
rx8||) D ],}*||* }+| jdk 
rj|+| jj6k
rjdS 
qjW | jdk
r|| j|< || | jjk
r|dk
o| j|d  j dks| j8j| n|| j|< | jj| n| jdk},| jdkrb| j9| }#|#d t(| jk rb| j|#d  j:rb| j|#d  j;dk},|,r~||kr|| j|< n||kr|| j|< nH| jdk r|| jj6kr| j|}| j	||}	|	| j|< n
|| jj0krRt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|< nZ|| j>kr| j|}||kr| j||| jj-|}.|.r||.d
  | jj?kr|.| j|< n| j	||| j|< n| jdkr|| jjkrXtj|| j|}-|-t(|k r||- | jjkr|| j8kr| j8j@| n|| jj-kr| j|}| j| }/||/ | jjkr|/| j8kr|/}0x4|0|kr||0 tAj-tAjgkrdS | j|0 }0qW | j8j@|/ 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-elser   zand/org      @rS   Tg	@g@zif-thenelsezexception-matchg333333@rj   r   rm   rm   )Br   rs   rz   r   r   r   r   Z	inst_sizer   Zrestrict_to_parentr   r   r   Z
last_instrr+   r|   r}   prevrw   is_jump_forwardr(   r   Zget_instr   r   r@   ri   GET_ITERZJUMP_OPsr   r   r   ru   r7   rX   r6   rem_orr   r   Zremove_mid_line_ifsrr   r:   r5   r   nextr8   r,   r   
POP_EXCEPTr   is_jump_backrL   
COMPARE_OPcmp_opr   r   r   rv   is_jump_targetr`   r~   r   r4   r   r   op3)1rJ   rX   r   Z
inst_indexr   r   rc   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_offsetZrtargetrw   Z	pretargetZpre_rtargetr   r   ZfixZjump_ifsZlast_jump_goodr   r   Zrtarget_is_jaZrtarget_breakZif_endZ	jump_prevZnext_opZtry_opZcome_from_opZnormal_jumpr}   Zunop_targetZrtarget_prevr   rN   rN   rO   r     sn   









































&











zScanner3.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   )rJ   rX   extended_argrN   rN   rO   r     s    zScanner3.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   rS   N)r   r   DUP_TOPZfirst_instrrr   r6   rw   r   r   r@   r   r   r   r   r+   r8   r(   rU   Zsetup_opts_no_loop)rJ   r   Zexcept_matchZjmpZcount_END_FINALLYZcount_SETUP_r   rc   rN   rN   rO   next_except_jump  s.    



zScanner3.next_except_jumpc             C   s   |dkr|t | jkr||ks"t| j|||||}| jdkrH| jj}n| jj}| j|||}g }	xJ|D ]B}
| j|
d }x&|D ]}||
ks||kr|	j	| qW |	}g }	qhW |S )z
        Find offsets of all requested <instr> between <start> and <end>,
        optionally <target>ing specified offset, and return list found
        <instr> offsets which are not within any POP_JUMP_IF_TRUE jumps.
        r   g      @r   )
rr   r   rU   r   r   r   r   r5   r   r   )rJ   r   r   r   r   Zinclude_beyond_targetZinstr_offsetsZjump_true_opZpjit_offsetsfilteredZpjit_offsetZpjit_tgtZinstr_offsetrN   rN   rO   r     s     "



zScanner3.rem_or)NF)NF)__name__
__module____qualname__r   r   ry   r   r   r   r   r   __classcell__rN   rN   )rM   rO   r
   :   s      SIZ    
#r
   __main__)r   g	@z2Need to be Python 3.2 or greater to demo; I am %s.)#__doc__
__future__r   r|   r   r   Zxdis.bytecoder   Zuncompyle6.scannerr   r   Zxdis.opcodes.opcode_33ZopcodesZ	opcode_33r   r   sys
uncompyle6r	   r   globalsupdateopmapr
   r   r   inspectcurrentframef_coder   r   r   r   r   rp   rN   rN   rN   rO   <module>"   sB            `


