B
    b                 @   s   d Z ddlZddlZddlZddlmZmZ G dd dejj	Z
eddd	ZG d
d dZdd ZG dd dejj	ZG dd dZdd ZdS )z"Dependency scanner for C/C++ code.    N   )
ClassicCPPFindPathDirsc                   s@   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Z  Z	S )SConsCPPScannerzSCons-specific subclass of the cpp.py module's processing.

    We subclass this so that: 1) we can deal with files represented
    by Nodes, not strings; 2) we can keep track of the files that are
    missing.
    c                s   t  j|| g | _d S )N)super__init__missing)selfargskwargs)	__class__ .lib/python3.7/site-packages/SCons/Scanner/C.pyr   '   s    zSConsCPPScanner.__init__c             C   s   t j|g| _d S )N)SConsUtil
UniqueListresult)r	   fnamer   r   r   initialize_result+   s    z!SConsCPPScanner.initialize_resultc             C   s   | j dd  S )Nr   )r   )r	   r   r   r   r   finalize_result.   s    zSConsCPPScanner.finalize_resultc             C   s:   |\}}}t jj|| j| }|s6| j|| jf |S )N)r   NodeFS	find_file
searchpathr   appendcurrent_file)r	   tkeywordquoter   r   r   r   r   find_include_file1   s
    
z!SConsCPPScanner.find_include_filec          
   C   s^   y$t t| 
}| S Q R X W n4 tk
rX } z| j|| jf dS d }~X Y nX d S )N )openstrrfilereadEnvironmentErrorr   r   r   )r	   filefper   r   r   	read_file8   s    zSConsCPPScanner.read_file)
__name__
__module____qualname____doc__r   r   r   r   r)   __classcell__r   r   )r   r   r       s   r   )returnc          	   C   s   |  di }|dkri S tj|ri }xX|D ]P}tj|rvy|d ||d < W q~ tk
rr   d||d < Y q~X q.d||< q.W |S tj|s|diS |S )z'Returns CPPDEFINES converted to a dict.Z
CPPDEFINESNr   r   )getr   r   Zis_Sequence
IndexErrorZis_Dict)envZ
cppdefinesr   cr   r   r   dictify_CPPDEFINES@   s     
r4   c               @   s2   e Zd ZdZdd ZdddZdd Zd	d
 ZdS )SConsCPPScannerWrappera5  The SCons wrapper around a cpp.py scanner.

    This is the actual glue between the calling conventions of generic
    SCons scanners, and the (subclass of) cpp.py class that knows how
    to look for #include lines with reasonably real C-preprocessor-like
    evaluation of #if/#ifdef/#else/#elif lines.
    c             C   s   || _ t|| _d S )N)namer   path)r	   r6   variabler   r   r   r   ^   s    zSConsCPPScannerWrapper.__init__r   c             C   sP   t | |t|d}||}x,|jD ]"\}}tjtjjd||f  q&W |S )N)currentcpppathdictzJNo dependency generated for file: %s (included from: %s) -- file not found)r   get_dirr4   r   r   WarningswarnDependencyWarning)r	   noder2   r7   cppr   includedincluderr   r   r   __call__b   s    zSConsCPPScannerWrapper.__call__c             C   s   |S )Nr   )r	   nodesr   r   r   recurse_nodeso   s    z$SConsCPPScannerWrapper.recurse_nodesc             C   s   | S )Nr   )r	   r@   r   r   r   selectq   s    zSConsCPPScannerWrapper.selectN)r   )r*   r+   r,   r-   r   rD   rF   rG   r   r   r   r   r5   U   s
   
r5   c              C   s   t dddd} | S )z^Return a prototype Scanner instance for scanning source files
    that use the C pre-processorCScannerz$CPPSUFFIXESCPPPATHz8^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|"))r   )Zcsr   r   r   rH   t   s    
rH   c                   s8   e Zd ZdZ fddZdd Zdd Zdd	 Z  ZS )
SConsCPPConditionalScannerzSCons-specific subclass of the cpp.py module's processing.

    We subclass this so that: 1) we can deal with files represented
    by Nodes, not strings; 2) we can keep track of the files that are
    missing.
    c                s   t  j|| g | _g | _d S )N)r   r   r   _known_paths)r	   r
   r   )r   r   r   r      s    z#SConsCPPConditionalScanner.__init__c             C   s   t j|g| _d S )N)r   r   r   r   )r	   r   r   r   r   r      s    z,SConsCPPConditionalScanner.initialize_resultc       	      C   s   |\}}}t | j| j|  }|dkr4| jjf| }tjj||}|r|	 }xB| j| D ] }|
|	 r\| j| P q\W n| j|| jf |S )N")tuplerK   r   r   dirr   r   r   r   Zget_abspath
startswithr   r   )	r	   r   r   r   r   pathsr   Zresult_pathpr   r   r   r      s    
z,SConsCPPConditionalScanner.find_include_filec          	   C   sP   y$t t| 
}| S Q R X W n& tk
rJ   | j|| jf dS X d S )Nr    )r!   r"   r#   r$   r%   r   r   r   )r	   r&   r'   r   r   r   r)      s    z$SConsCPPConditionalScanner.read_file)	r*   r+   r,   r-   r   r   r   r)   r.   r   r   )r   r   rJ      s
   rJ   c               @   s2   e Zd ZdZdd ZdddZdd	 Zd
d ZdS )!SConsCPPConditionalScannerWrappera:  
    The SCons wrapper around a cpp.py scanner.

    This is the actual glue between the calling conventions of generic
    SCons scanners, and the (subclass of) cpp.py class that knows how
    to look for #include lines with reasonably real C-preprocessor-like
    evaluation of #if/#ifdef/#else/#elif lines.
    c             C   s   || _ t|| _d S )N)r6   r   r7   )r	   r6   r8   r   r   r   r      s    z*SConsCPPConditionalScannerWrapper.__init__r   c       
      C   sV   t | |t||d}||}x0|jD ]&\}}d}	tjtjj|	||f  q(W |S )N)r9   r:   r;   depthzJNo dependency generated for file: %s (included from: %s) -- file not found)rJ   r<   r4   r   r   r=   r>   r?   )
r	   r@   r2   r7   rT   rA   r   rB   rC   Zfmtr   r   r   rD      s    z*SConsCPPConditionalScannerWrapper.__call__c             C   s   |S )Nr   )r	   rE   r   r   r   rF      s    z/SConsCPPConditionalScannerWrapper.recurse_nodesc             C   s   | S )Nr   )r	   r@   r   r   r   rG      s    z(SConsCPPConditionalScannerWrapper.selectN)r   rS   )r*   r+   r,   r-   r   rD   rF   rG   r   r   r   r   rR      s
   
rR   c               C   s
   t ddS )z
    Return an advanced conditional Scanner instance for scanning source files

    Interprets C/C++ Preprocessor conditional syntax
    (#ifdef, #if, defined, #else, #elif, etc.).
    CConditionalScannerrI   )rR   r   r   r   r   rU      s    rU   )r-   ZSCons.Node.FSr   Z	SCons.cppZ
SCons.Utilr    r   r   rA   ZPreProcessorr   r;   r4   r5   rH   rJ   rR   rU   r   r   r   r   <module>   s    )$