3
/*^L                 @   s2  d Z ddlmZ ddlmZ ddlmZ ddlZddlmZm	Z	 ddl
mZ ddlZddlmZmZmZmZmZmZ ed3Zed d! eD Zded"< erejZd#Zd$d% Zned#ZG d&d' d'eZG d(d) d)eZd*d+ Zd4d-d.Zed/kr.ddl Z ddlZe j! j"Z#eej$e	d0Z%e%j&e#i d1d2\Z'Z(dS )5zl
scanner/ingestion module. From here we call various version-specific
scanners, e.g. for Python 2.7 or 3.4.
    )print_function)array)
namedtupleN)PYTHON3IS_PYPY)Token)Bytecodecanonic_python_versioncode2numinstruction_sizeextended_arg_valnext_offset      ?皙??ffffff?      ?皙? @皙@ffffff@333333@      @@皙@      @@皙	@ffffff
@333333@      @@皙@ffffff@333333@c             c   s   | ]}t t| |fV  qd S )N)r	   str).0v r(   O/home/psgendb/BIRCHDEV/python/lib/python3.6/site-packages/uncompyle6/scanner.py	<genexpr>A   s    r*   z3.5.2i   c             C   s   | S )Nr(   )lr(   r(   r)   longM   s    r,   c               @   s   e Zd ZdZdddZdS )Codez
    Class for representing code-objects.

    This is similar to the original code object, but additionally
    the diassembled code is stored in the attribute '_tokens'.
    Nc             C   sF   x,t |D ] }|jdr
t| |t|| q
W |j||\| _| _d S )NZco_)dir
startswithsetattrgetattringestZ_tokensZ
_customize)selfcoscanner	classnameir(   r(   r)   __init__]   s    
zCode.__init__)N)__name__
__module____qualname____doc__r8   r(   r(   r(   r)   r-   U   s   r-   c               @   s   e Zd Zd3ddZdd Zdd Zd	d
 Zdd Zdd Zdd Z	d4ddZ
dd Zdd Zdd Zd5ddZd6ddZd7dd Zd8d!d"Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 ZdS )9ScannerNFc             C   s|   || _ || _|| _|tkrZ|r0dt|d  }ndt|d  }td|  td|  ntd| | jj| _| j	  d S )Nzopcode_%spypy
   z	opcode_%szfrom xdis.opcodes import %szself.opc = %sz'%s is not a Python version I know about)
versionshow_asmis_pypyPYTHON_VERSIONSintexec	TypeErroropcopnameresetTokenClass)r3   r?   r@   rA   v_strr(   r(   r)   r8   e   s    
zScanner.__init__c             C   sl   t d|j| _t|| j}| j  | jt|| _| j	|| _
i | _x"t| jD ]\}}|| j|j< qPW |S )z
        Create a list of instructions (a structured object rather than
        an array of bytes) and store that in self.insts
        B)r   co_codecoder   rF   build_prev_opremove_extended_argslistinstsbuild_lines_datalinesoffset2inst_index	enumerateoffset)r3   r4   bytecoder7   instr(   r(   r)   build_instructionsy   s    zScanner.build_instructionsc             C   s   | j dkrt| jj|}n
ddgg}t|| _g }tdddg}|d \}}d}xB|dd D ]2\}}	x$||k r|j||| |d7 }qjW |	}q`W t| j	}
x$||
k r|j|||
 |d7 }qW |S )z<
        Generate various line-related helper data.
        gffffff?r      	LineTuplel_nonextN)
r?   rO   rF   findlinestartsdict
linestartsr   appendlenrL   )r3   Zcode_objr_   rR   rZ   _Zprev_line_norU   Zstart_offsetZline_nocodelenr(   r(   r)   rQ      s$    





zScanner.build_lines_datac             C   sd   | j }t|}dg | _| _xB| jd|D ]2}|| }x$tt|| jD ]}| jj| qHW q*W dS )zv
        Compose 'list-map' which allows to jump to previous
        op, given offset of current op as index.
        r   N)	rL   ra   prevprev_opop_rangeranger   rF   r`   )r3   rL   rc   rU   oprb   r(   r(   r)   rM      s    zScanner.build_prev_opc             C   s2   | j |j}|dkrdS |dkr$dS || j|k S )z
        Return True if the code at offset is some sort of jump forward.
        That is, it is ether "JUMP_FORWARD" or an absolute jump that
        goes forward.
        JUMP_FORWARDTJUMP_ABSOLUTEF)get_instrG   
get_target)r3   rU   rG   r(   r(   r)   is_jump_forward   s    zScanner.is_jump_forwardc             C   s   | j | j| d  jS )NrY   )rP   rS   rU   )r3   rU   r(   r(   r)   prev_offset   s    zScanner.prev_offsetc             C   sD   || j kr4|t| jj| j8 }| j| | jjks4t| j| j |  S )N)rS   r   rF   EXTENDED_ARGrL   AssertionErrorrP   )r3   rU   r(   r(   r)   rk      s    
zScanner.get_instr   c             C   s>   | j |}|j| jj| jjB kr(|j}nt|j| j|j}|S )z|
        Get next instruction offset for op located at given <offset>.
        NOTE: extended_arg is no longer used
        )rk   opcoderF   ZJREL_OPSZJABS_OPSargvalr   rU   )r3   rU   extended_argrW   targetr(   r(   r)   rl      s
    
zScanner.get_targetc             C   s$   | j |d  | j |d  d  }|S )NrY         )rL   )r3   posargr(   r(   r)   get_argument   s     zScanner.get_argumentc             C   s   t j|| j|S )N)xdisr   rF   )r3   rh   rU   r(   r(   r)   r      s    zScanner.next_offsetc             C   sp   xj| j dt| jD ]T}| j| }|| jkrR| j||}td|| j| |f  qtd|| j| f  qW d S )Nr   z%i	%s	%iz%i	%s	)rf   ra   rL   ZJUMP_OPSrl   printrG   )r3   r7   rh   destr(   r(   r)   print_bytecode   s    

zScanner.print_bytecodeTc             C   s   | j }|dkr|t|kstt|ts.|g}d}t|}xf| j||D ]V}	||	 }
|
|krH|dkrh|	S | j|	}||kr~|	S |sHt|| }||k rH|}|	}qHW |S )a  
        Find the first <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 if exact
        is True, or if exact is False, the instruction which has a target
        closest to <target> will be returned.

        Return index to it or None if not found.
        r   N)rL   ra   rp   
isinstancerO   rf   rl   abs)r3   startendinstrrt   exactrL   result_offsetcurrent_distancerU   rh   r|   new_distancer(   r(   r)   first_instr   s(    

zScanner.first_instrc             C   s   | j }|dko|t|ksdS t|ts.|g}d}| jd j| jd j }d}	x| j||D ]}
||
 }|| jjkrt	||
d |	B }t
| j|}	q\||kr|dkr|
}n>| j|
|	}||krd}|
}n |st|| }||kr|}|
}d}	q\W |S )a  
        Find the last <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 if exact
        is True, or if exact is False, the instruction which has a target
        closest to <target> will be returned.

        Return index to it or None if not found.
        r   NrY   )rL   ra   r~   rO   rP   rU   rf   rF   ro   r
   r   rl   r   )r3   r   r   r   rt   r   rL   r   r   rs   rU   rh   rx   r|   r   r(   r(   r)   
last_instr  s:    
zScanner.last_instrc       
   	   C   s   yd|k W n   |g}Y nX | j | }g }x|| j|d D ]j}|j|kr|dkrb|j|j n:| j|j}	|r|	|kr|j|j n|	|kr|j|j |j|kr>P q>W |S )aB  
        Find all `instr` in the block from start to end.
        `instr` is a Python opcode 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.
        N)rS   rP   rq   r`   rU   rl   )
r3   r   r   r   rt   include_beyond_targetfirstresultrW   tr(   r(   r)   inst_matchesP  s&    	


zScanner.inst_matchesc             C   s   | j }|dkr|t|kstyd|k W n   |g}Y nX g }d}x| j||D ]}	||	 }
|
| jjkrt||	d |B }t| j|}qT|
|kr|dkr|j|	 n6| j	|	|}|r||kr|j|	 n||kr|j|	 d}qTW |S )aD  
        Find all `instr` in the block from start to end.
        `instr` is any Python opcode 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   NrY   )
rL   ra   rp   rf   rF   ro   r
   r   r`   rl   )r3   r   r   r   rt   r   rL   r   rs   rU   rh   rx   r   r(   r(   r)   	all_instrz  s2    

zScanner.all_instrc             C   s   | j j| j|  S )N)rF   rG   rL   )r3   rU   r(   r(   r)   opname_for_offset  s    zScanner.opname_for_offsetc             C   s   | j j| S )N)rF   rG   )r3   rh   r(   r(   r)   op_name  s    zScanner.op_namec             c   s.   x(||k r(|V  |t | j| | j7 }qW dS )zS
        Iterate through positions of opcodes, skipping
        arguments.
        N)r   rL   rF   )r3   r   r   r(   r(   r)   rf     s    
zScanner.op_rangec             C   s   g }d}t |}xt|D ]\}}|jdkrb|d |k rb||d  jdkrbd}|j}|j}|j}	q|r|j|||	d}
|
}||k r| j|| j }||d  j}| j| }x,| j| |kr||k r|| j|< |d7 }qW d}|j| qW |S )zGo through instructions removing extended ARG.
        get_instruction_bytes previously adjusted the operand values
        to account for theseFro   rY   MAKE_FUNCTIONT)starts_lineis_jump_targetrU   )	ra   rT   rG   r   r   rU   _replacere   r`   )r3   ZinstructionsZnew_instructionsZlast_was_extargnr7   rW   r   r   rU   Znew_instZnew_prevjZold_prevr(   r(   r)   rN     s8    


zScanner.remove_extended_argsc             C   sf   g }x\|D ]T}| j | j| j |d  jkrT| j| j| j | j  | jj| jjfkrTq
|j| q
W |S )z^
        Go through passed offsets, filtering ifs
        located somewhere mid-line.
           )	rR   r[   rL   rd   r\   rF   ZPJITZPJIFr`   )r3   Zifsfilteredr7   r(   r(   r)   remove_mid_line_ifs  s    
zScanner.remove_mid_line_ifsc             C   s
   | j tS )N)setTokenClassr   )r3   r(   r(   r)   rH     s    zScanner.resetTokenClassc             C   s,   |d |  k o|d k n  s(|d }|S )z/Restrict target to parent structure boundaries.r   r   r(   )r3   rt   parentr(   r(   r)   restrict_to_parent  s     zScanner.restrict_to_parentc             C   s   || _ | j S )N)r   )r3   Z
tokenClassr(   r(   r)   r     s    zScanner.setTokenClass)NF)r   )NT)NT)NF)NF)r9   r:   r;   r8   rX   rQ   rM   rm   rn   rk   rl   ry   r   r}   r   r   r   r   r   r   rf   rN   r   rH   r   r   r(   r(   r(   r)   r=   d   s.   
%
	
"
6
*
.	)r=   c             C   s   | d@ | d? d@ | d? d@ fS )N         i  r(   )Zargcr(   r(   r)   parse_fn_counts  s    r   Fc             C   s  t | trF| tkrtd|  t|  }|tkr>td| |f t| } | tkrdt| d  }y.dd l}|r~|jd| }n|jd| }W nB t	k
r   |rt
d| t t  nt
d	| t t  Y nX |rtd
| t t }ntd| t t }ntd|  |S )Nz!Unknown Python version in xdis %sz*Unsupported Python version %s (canonic %s)z%sr>   r   zuncompyle6.scanners.pypy%szuncompyle6.scanners.scanner%sz)import uncompyle6.scanners.pypy%s as scanz,import uncompyle6.scanners.scanner%s as scanz%scan.ScannerPyPy%s(show_asm=show_asm)z!scan.Scanner%s(show_asm=show_asm)zUnsupported Python version %s)r~   r%   r	   RuntimeErrorCANONIC2VERSIONrB   rC   	importlibimport_moduleImportErrorrD   localsglobalseval)r?   rA   r@   Zcanonic_versionrI   r   scanr5   r(   r(   r)   get_scanner	  sD    


r   __main__Tafter)r@   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   )FN))r<   
__future__r   r   collectionsr   sys
uncompyle6r   r   Zuncompyle6.scanners.tokr   rz   r   r	   r
   r   r   r   	frozensetrB   r^   r   internZL65536r,   objectr-   r=   r   r   r9   inspectcurrentframef_coder4   ZPYTHON_VERSIONr5   r2   tokensZ	customizer(   r(   r(   r)   <module>   sf                          
   $
4

