B
    bi                 @   s  d Z ddlZddlZddlmZmZ ddlZddlm	Z	m
Z
 ejjejjejjgZeefadd Zdd ZG d	d
 d
ZG dd dZdd ZG dd dejZdd ZG dd dZG dd dejZG dd dZG dd dejjZe Z dd Z!dddd hZ"G d!d" d"Z#G d#d$ d$ejZ$dZ%d%Z&d&Z'e(d'Z)e(d(Z*e)de*gZ+d)d* Z,d+d, Z-e,de-gZ.d-Z/e(d.e/ Z0e(d/e/ Z1e(d0Z2e&ddi i dfd1d2Z3e&ddi i dfd3d4Z4d5d6 Z5dS )7zSCons string substitution.    N)	signature	Parameter)	is_Stringis_Sequencec              G   s   dd | D a d S )Nc             S   s   g | ]}|r|qS  r   ).0Z_fr   r   *lib/python3.7/site-packages/SCons/Subst.py
<listcomp>-   s    z*SetAllowableExceptions.<locals>.<listcomp>)AllowableExceptions)Zexceptsr   r   r   SetAllowableExceptions+   s    r   c             C   s>   | j j}d|| |f }|r.tj|d |ntj|d S )Nz%s `%s' trying to evaluate `%s'r   )	__class____name__SConsErrorsZ
BuildError	UserError)Z	exceptiontargetsnamemsgr   r   r   raise_exception0   s
    r   c               @   sP   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd ZdS )LiteralzA wrapper for a string.  If you use this object wrapped
    around a string, then it will be interpreted as literal.
    When passed to the command interpreter, all special
    characters will be escaped.c             C   s
   || _ d S )N)lstr)selfr   r   r   r   __init__>   s    zLiteral.__init__c             C   s   | j S )N)r   )r   r   r   r   __str__A   s    zLiteral.__str__c             C   s
   || j S )N)r   )r   escape_funcr   r   r   escapeD   s    zLiteral.escapec             C   s   | j S )N)r   )r   r   r   r   for_signatureG   s    zLiteral.for_signaturec             C   s   dS )N   r   )r   r   r   r   
is_literalJ   s    zLiteral.is_literalc             C   s   t |tsdS | j|jkS )NF)
isinstancer   r   )r   otherr   r   r   __eq__M   s    
zLiteral.__eq__c             C   s   |  | S )N)r"   )r   r!   r   r   r   __neq__R   s    zLiteral.__neq__c             C   s
   t | jS )N)hashr   )r   r   r   r   __hash__U   s    zLiteral.__hash__N)r   
__module____qualname____doc__r   r   r   r   r   r"   r#   r%   r   r   r   r   r   9   s   r   c               @   s:   e Zd ZdZdddZdd Zdd Zd	d
 Zdd ZdS )SpecialAttrWrappera  This is a wrapper for what we call a 'Node special attribute.'
    This is any of the attributes of a Node that we can reference from
    Environment variable substitution, such as $TARGET.abspath or
    $SOURCES[1].filebase.  We implement the same methods as Literal
    so we can handle special characters, plus a for_signature method,
    such that we can return some canonical string during signature
    calculation to avoid unnecessary rebuilds.Nc             C   s   || _ |r|| _n|| _dS )zThe for_signature parameter, if supplied, will be the
        canonical string we return from for_signature().  Else
        we will simply return lstr.N)r   forsig)r   r   r   r   r   r   r   a   s    zSpecialAttrWrapper.__init__c             C   s   | j S )N)r   )r   r   r   r   r   k   s    zSpecialAttrWrapper.__str__c             C   s
   || j S )N)r   )r   r   r   r   r   r   n   s    zSpecialAttrWrapper.escapec             C   s   | j S )N)r*   )r   r   r   r   r   q   s    z SpecialAttrWrapper.for_signaturec             C   s   dS )Nr   r   )r   r   r   r   r   t   s    zSpecialAttrWrapper.is_literal)N)	r   r&   r'   r(   r   r   r   r   r   r   r   r   r   r)   X   s   

r)   c             C   s$   d| ksd| krd|  S t | S dS )z\Generic function for putting double quotes around any string that
    has white space in it. 	z"%s"N)str)argr   r   r   quote_spacesw   s    r/   c                   s6   e Zd ZdZd	 fdd	Zdd ZefddZ  ZS )
CmdStringHoldera6  This is a special class used to hold strings generated by
    scons_subst() and scons_subst_list().  It defines a special method
    escape().  When passed a function with an escape algorithm for a
    particular platform, it will return the contained string with the
    proper escape sequences inserted.
    Nc                s   t  | || _d S )N)superr   literal)r   cmdr2   )r   r   r   r      s    zCmdStringHolder.__init__c             C   s   | j S )N)r2   )r   r   r   r   r      s    zCmdStringHolder.is_literalc             C   s:   |   r|| jS d| jks&d| jkr0|| jS | jS dS )aO  Escape the string with the supplied function.  The
        function is expected to take an arbitrary string, then
        return it with all special characters escaped and ready
        for passing to the command interpreter.

        After calling this function, the next call to str() will
        return the escaped string.
        r+   r,   N)r   data)r   r   Z
quote_funcr   r   r   r      s
    


zCmdStringHolder.escape)N)	r   r&   r'   r(   r   r   r/   r   __classcell__r   r   )r   r   r0      s   r0   c             C   s   |fdd}t t|| S )z|Escape a list of arguments by running the specified escape_func
    on every object in the list that has an escape() method.c             S   s,   y
| j }W n tk
r   | S X ||S d S )N)r   AttributeError)objr   er   r   r   r      s
    
zescape_list.<locals>.escape)listmap)mylistr   r   r   r   r   escape_list   s    r<   c               @   s,   e Zd ZdZdd Zdd Zdd ZeZdS )		NLWrappera9  A wrapper class that delays turning a list of sources or targets
    into a NodeList until it's needed.  The specified function supplied
    when the object is initialized is responsible for turning raw nodes
    into proxies that implement the special attributes like .abspath,
    .source, etc.  This way, we avoid creating those proxies just
    "in case" someone is going to use $TARGET or the like, and only
    go through the trouble if we really have to.

    In practice, this might be a wash performance-wise, but it's a little
    cleaner conceptually...
    c             C   s   || _ || _d S )N)r9   func)r   r9   r>   r   r   r   r      s    zNLWrapper.__init__c             C   s   | j S )N)nodelist)r   r   r   r   _return_nodelist   s    zNLWrapper._return_nodelistc             C   sJ   | j }|d krg }nt|s"|g}tjt t| j|| _| j| _	| jS )N)
r9   r   r   UtilZNodeListr:   r>   r?   r@   _create_nodelist)r   r;   r   r   r   _gen_nodelist   s    zNLWrapper._gen_nodelistN)r   r&   r'   r(   r   r@   rC   rB   r   r   r   r   r=      s
   r=   c               @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )Targets_or_Sourcesa  A class that implements $TARGETS or $SOURCES expansions by in turn
    wrapping a NLWrapper.  This class handles the different methods used
    to access the list, calling the NLWrapper to create proxies on demand.

    Note that we subclass collections.UserList purely so that the
    is_Sequence() function will identify an object of this class as
    a list during variable expansion.  We're not really using any
    collections.UserList methods in practice.
    c             C   s
   || _ d S )N)nl)r   rE   r   r   r   r      s    zTargets_or_Sources.__init__c             C   s   | j  }t||S )N)rE   rB   getattr)r   attrrE   r   r   r   __getattr__   s    
zTargets_or_Sources.__getattr__c             C   s   | j  }|| S )N)rE   rB   )r   irE   r   r   r   __getitem__   s    
zTargets_or_Sources.__getitem__c             C   s   | j  }t|S )N)rE   rB   r-   )r   rE   r   r   r   r      s    
zTargets_or_Sources.__str__c             C   s   | j  }t|S )N)rE   rB   repr)r   rE   r   r   r   __repr__   s    
zTargets_or_Sources.__repr__N)	r   r&   r'   r(   r   rH   rJ   r   rL   r   r   r   r   rD      s   	rD   c               @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )Target_or_SourcezA class that implements $TARGET or $SOURCE expansions by in turn
    wrapping a NLWrapper.  This class handles the different methods used
    to access an individual proxy Node, calling the NLWrapper to create
    a proxy on demand.
    c             C   s
   || _ d S )N)rE   )r   rE   r   r   r   r      s    zTarget_or_Source.__init__c             C   sB   | j  }y|d }W n  tk
r6   td| Y nX t||S )Nr   zNodeList has no attribute: %s)rE   rB   
IndexErrorr6   rF   )r   rG   rE   Znl0r   r   r   rH      s    
zTarget_or_Source.__getattr__c             C   s   | j  }|rt|d S dS )Nr    )rE   rB   r-   )r   rE   r   r   r   r      s    
zTarget_or_Source.__str__c             C   s   | j  }|rt|d S dS )Nr   rO   )rE   rB   rK   )r   rE   r   r   r   rL      s    
zTarget_or_Source.__repr__N)r   r&   r'   r(   r   rH   r   rL   r   r   r   r   rM      s
   	rM   c               @   s   e Zd Zdd Zdd ZdS )NullNodeListc             O   s   dS )NrO   r   )r   argskwargsr   r   r   __call__       zNullNodeList.__call__c             C   s   dS )NrO   r   )r   r   r   r   r     rT   zNullNodeList.__str__N)r   r&   r'   rS   r   r   r   r   r   rP      s   rP   c             C   s   i }| rDdd }t | |}t||d< t||d< d|d< d|d< nt|d< t|d< |rdd	 }t ||}t||d
< t||d< d|d< d|d< nt|d
< t|d< |S )a  Create a dictionary for substitution of special
    construction variables.

    This translates the following special arguments:

    target - the target (object or array of objects),
             used to generate the TARGET and TARGETS
             construction variables

    source - the source (object or array of objects),
             used to generate the SOURCES and SOURCE
             construction variables
    c             S   s*   y|   }W n tk
r$   | }Y nX |S )N)get_subst_proxyr6   )thingZsubst_proxyr   r   r   get_tgt_subst_proxy  s
    
z'subst_dict.<locals>.get_tgt_subst_proxyTARGETSTARGETz$TARGETSZCHANGED_TARGETSZUNCHANGED_TARGETSc             S   sH   y
| j }W n tk
r   Y nX | } y|  S  tk
rB   | S X d S )N)rfiler6   rU   )ZnoderZ   r   r   r   get_src_subst_proxy+  s    
z'subst_dict.<locals>.get_src_subst_proxySOURCESZSOURCEz$SOURCESZCHANGED_SOURCESZUNCHANGED_SOURCES)r=   rD   rM   NullNodesList)r   sourcedictrW   Ztnlr[   Zsnlr   r   r   
subst_dict  s(    



r`   r   r^   envr   c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )	StringSubberzA class to construct the results of a scons_subst() call.

    This binds a specific construction environment, mode, target and
    source with two methods (substitute() and expand()) that handle
    the expansion.
    c             C   s   || _ || _|| _|| _d S )N)ra   modeconvgvars)r   ra   rc   rd   re   r   r   r   r   R  s    zStringSubber.__init__c          
   C   sV  t |ry|dd \}}W n ttfk
r6   |S X |dkrD|S |dkrPdS |dkr\|S |dd }|d dks|d	|kr|d dkr|dd
 }|}d}||kr|| }n|| jkr| j| }nlyt|| j|}W nX tk
r    Y nD tk
r. } z$|jtkrdS t	||d | W dd}~X Y nX |dkrZt
tkrZt	t
||d | n|dkrhdS | }|d	d }	d||	< | ||S nt|r| j| j|fdd}
tt|
|S t|r@t|tjjsdd t|j D tkr||d |d | j| jtkd}n| jtkr*|S | |}| ||S |dkrNdS |S dS )a  Expand a single "token" as necessary, returning an
        appropriate string containing the expansion.

        This handles expanding different types of things (strings,
        lists, callables) appropriately.  It calls the wrapper
        substitute() method to re-expand things as necessary, so that
        the results of expansions of side-by-side strings still get
        re-evaluated separately, not smushed together.
        N   $z$$z()r   r   {.rO   rX   c             S   s   ||| |S )Nr   )lrd   
substitutelvarsr   r   r   r>     s    z!StringSubber.expand.<locals>.funcc             S   s(   h | ] \}}|t ks |jtjkr|qS r   )_callable_args_setdefaultr   empty)r   kvr   r   r   	<setcomp>  s    z&StringSubber.expand.<locals>.<setcomp>r\   )r   r^   ra   r   )r   rN   
ValueErrorre   evalKeyboardInterrupt	Exceptionr   r
   r   	NameErrorcopysplitrl   r   rd   r9   r:   callabler    r   rA   Nullr   
parametersitemsrn   ra   rc   	SUBST_SIG	SUBST_RAW)r   r   rm   s0s1keyold_sr8   lvvarr>   r   r   r   expandX  sl    



"


&

zStringSubber.expandc                s   t |rt|tst|}y fdd}t||}W nn tk
r   t|}g }x$|D ]}|	
|  q\W t|dkr|d }ndtt|}Y nX |S | S dS )zSubstitute expansions in an argument or list of arguments.

        This serves as a wrapper for splitting up a string into
        separate tokens.
        c                s    | d S )Nr   )rd   r   group)match)rm   r   r   r   	sub_match  s    z*StringSubber.substitute.<locals>.sub_matchr   r   rO   N)r   r    r0   r-   _dollar_expssub	TypeError_separate_argsfindallappendrd   r   lenjoinr:   )r   rQ   rm   r   resultar   )rm   r   r   rl     s    


zStringSubber.substituteN)r   r&   r'   r(   r   r   rl   r   r   r   r   rb   I  s   erb   c                   sx   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Z  ZS )
ListSubbera  A class to construct the results of a scons_subst_list() call.

    Like StringSubber, this class binds a specific construction
    environment, mode, target and source with two methods
    (substitute() and expand()) that handle the expansion.

    In addition, however, this class is used to track the state of
    the result(s) we're gathering so we can do the appropriate thing
    whenever we have to append another word to the result--start a new
    line, start a new word, append to the current word, etc.  We do
    this by setting the "append" attribute to the right method so
    that our wrapper methods only need ever call ListSubber.append(),
    and the rest of the object takes care of doing the right thing
    internally.
    c                sZ   t  g  | _| _| _| _ jtkr> fdd _n
dd  _d  _ 	  d S )Nc                s
     | S )N)r   )x)r   r   r   <lambda>  rT   z%ListSubber.__init__.<locals>.<lambda>c             S   s   d S )Nr   )r   r   r   r   r     rT   )
r1   r   ra   rc   rd   re   r   	add_stripin_strip	next_line)r   ra   rc   rd   re   )r   )r   r   r     s    

zListSubber.__init__c             C   s,   t |rt|trdS t|}t|dkS )ab  Determines if the string s requires further expansion.

        Due to the implementation of ListSubber expand will call
        itself 2 additional times for an already expanded string. This
        method is used to determine if a string is already fully
        expanded and if so exit the loop early to prevent these
        recursive calls.
        FN)r   r    r0   r-   r   r   )r   r   r   r   r   expanded  s    	zListSubber.expandedc          
   C   s  t |ry|dd \}}W n" ttfk
r@   | | dS X |dkrX| | dS |dkrn| d q|dkr| d q|dkr| d q|dd }|d	 d
ks|dd	kr|d	 d
kr|dd }|}d}||kr|| }n|| jkr
| j| }nnyt|| j|}W nZ t	k
r4    Y nD t
k
rv } z$|jtkrVdS t||d | W dd}~X Y nX |dkrttkrtt |d | n|dkrdS | |r| | dS | }	|dd	 }
d|	|
< | ||	d	 |   nt|r0x|D ]}| ||d |   qW nt|rt|tjjshdd t|j D tkr||d |d | j| j t!kd}n$| j t"kr| | dS | #|}| ||| n|dkr|   n
| | dS )a  Expand a single "token" as necessary, appending the
        expansion to the current result.

        This handles expanding different types of things (strings,
        lists, callables) appropriately.  It calls the wrapper
        substitute() method to re-expand things as necessary, so that
        the results of expansions of side-by-side strings still get
        re-evaluated separately, not smushed together.
        Nrf   rg   (z$()z$)r   r   rh   ri   rj   rX   rO   c             S   s(   h | ] \}}|t ks |jtjkr|qS r   )rn   ro   r   rp   )r   rq   rr   r   r   r   rs   Z  s    z$ListSubber.expand.<locals>.<setcomp>r\   )r   r^   ra   r   )$r   rN   rt   r   
open_stripclose_stripfindre   ru   rv   rw   r   r
   r   rx   r   ry   rz   rl   	this_wordr   	next_wordr{   r    r   rA   r|   r   r}   r~   rn   ra   rc   	SUBST_CMDr   rd   )r   r   rm   within_listr   r   r   r   r8   r   r   r   r   r   r   r   	  s    



"





&



zListSubber.expandc             C   s   t |rzt|tszt|}t|}xb|D ]J}|d dkrfd|krL|   qt|r\| | qt|   q*| 	||| q*W n| 	||| dS )zSubstitute expansions in an argument or list of arguments.

        This serves as a wrapper for splitting up a string into
        separate tokens.
        r   z 	

N)
r   r    r0   r-   r   r   r   r   r   r   )r   rQ   rm   r   r   r   r   r   rl   o  s    



zListSubber.substitutec             C   s   t j| g  |   dS )zArrange for the next word to start a new line.  This
        is like starting a new word, except that we have to append
        another line to the result.N)collectionsUserListr   r   )r   r   r   r   r     s    zListSubber.next_linec             C   s   | j | _dS )z^Arrange for the next word to append to the end of the
        current last word in the result.N)add_to_current_wordr   )r   r   r   r   r     s    zListSubber.this_wordc             C   s   | j | _dS )z.Arrange for the next word to start a new word.N)add_new_wordr   )r   r   r   r   r     s    zListSubber.next_wordc             C   s   | j r| jtkry| d d }W n tk
r>   | | Y npX yt|d }W n tk
rh   d}Y nX |dkr~| | n0|| }| |}t|rt|d}|| d d< dS )a6  Append the string x to the end of the current last word
        in the result.  If that is not possible, then just add
        it as a new word.  Make sure the entire concatenated string
        inherits the object attributes of x (in particular, the
        escape function) by wrapping it as CmdStringHolder.rj    z<>|N)	r   rc   r   rN   r   r-   rd   r   r0   )r   r   Zcurrent_wordZ	last_charyr   r   r   r     s     


zListSubber.add_to_current_wordc             C   sP   | j r| jtkrD| |}| |}t|r6t||}| d | | j| _d S )Nrj   )	r   rc   r   r2   rd   r   r0   r   r   )r   r   r2   r   r   r   r     s    


zListSubber.add_new_wordc             C   s*   y
|j }W n tk
r   d S X | S d S )N)r   r6   )r   r   rk   r   r   r   r2     s
    
zListSubber.literalc             C   s   |  | d| _dS )z!Handle the "open strip" $( token.r   N)r   r   )r   r   r   r   r   r     s    
zListSubber.open_stripc             C   s   |  | d| _dS )z"Handle the "close strip" $) token.N)r   r   )r   r   r   r   r   r     s    
zListSubber.close_strip)r   r&   r'   r(   r   r   r   rl   r   r   r   r   r   r2   r   r   r5   r   r   )r   r   r     s   f0	r   r   rf   z\$[()]z(?<!\$)(\$[()])c             C   s   dd | D S )Nc             S   s   g | ]}|d kr|qS ))z$(z$)r   )r   rk   r   r   r   r	     s    z_rm_list.<locals>.<listcomp>r   )r9   r   r   r   _rm_list  s    r   c             C   sf   g }d}xL| D ]D}|dkr$|d7 }q|dkr@|d8 }|dk rRP q|dkr| | qW |dkrbd S |S )Nr   z$(r   z$))r   )r9   r   Zdepthrk   r   r   r   _remove_list  s    

r   z'\$[\$\(\)]|\$[_a-zA-Z][\.\w]*|\${[^}]*}z(%s)z(%s|\s+|[^\s$]+|\$)z[\t ]+(?![^{]*})c             C   sh  t | trd| kst | tr | S |dkr0t| }d|krXt||}|rX| }|| t|d< t||||}	|		| |}
y
|d= W n t
k
r   Y nX |
}t|
r&t| }|r|tkrt| ||
}
|
dkrtjd| d|
}
n|d|
}
|tkrtd|
 }
|
dd}
n>t|
rdt| }|rd||
}
|
dkrdtjdt| |
S )	aT  Expand a string or list containing construction variable
    substitutions.

    This is the work-horse function for substitutions in file names
    and the like.  The companion scons_subst_list() function (below)
    handles separating command lines into lists of arguments, so see
    that function if that's what you're looking for.
    rg   NrY   __builtins__zUnbalanced $(/$) in: r+   rO   z$$)r    r-   r0   _strconvr`   ry   updater   rb   rl   KeyErrorr   _regex_remover   _list_removerz   r   r   r   r   r   r   
_space_sepstripreplacer   )strSubstra   rc   r   r^   re   rm   rd   dZssr   Zresremover   r   r   scons_subst'  sH    	






r   c       
      C   s   |dkrt | }d|kr8t||}|r8| }|| t|d< t||||}	|	| |d y
|d= W n tk
rz   Y nX |	jS )a&  Substitute construction variables in a string (or list or other
    object) and separate the arguments into a command list.

    The companion scons_subst() function (above) handles basic
    substitutions within strings, so see that function instead
    if that's what you're looking for.
    NrY   r   r   )	r   r`   ry   r   r   r   rl   r   r4   )
r   ra   rc   r   r^   re   rm   rd   r   Zlsr   r   r   scons_subst_listu  s    


r   c             C   s   t | tr| ddk r| S d| d| d g}||d}||fdd}t| rg }x^| D ]V}t|r||kr|}t|r|| q|| q|t	|| q\|| q\W |S t| rt	|| S | S dS )	a  Perform single (non-recursive) substitution of a single
    construction variable keyword.

    This is used when setting a variable when copying or overriding values
    in an Environment.  We want to capture (expand) the old value before
    we override it, so people can do things like:

        env2 = env.Clone(CCFLAGS = '$CCFLAGS -g')

    We do this with some straightforward, brute-force code here...
    rg   r   z${}rO   c             S   s:   |  d}||kr|}t|r.dtt|S t|S d S )Nr   r+   )r   r   r   r:   r-   )r   val	matchlistr   r   r   r   r     s    
z#scons_subst_once.<locals>.sub_matchN)
r    r-   r   getr   r   extendr   r   r   )r   ra   r   r   r   r   r   r.   r   r   r   scons_subst_once  s(    	
r   )6r(   r   reinspectr   r   ZSCons.Errorsr   Z
SCons.Utilr   r   rA   Zto_String_for_substZto_String_for_signaturer   rN   rx   r
   r   r   r   r)   r/   
UserStringr0   r<   r=   r   rD   rM   ZNullSeqrP   r]   r`   rn   rb   r   r   r   r   compileZ_rmZ	_rm_splitr   r   r   r   Z_dollar_exps_strr   r   r   r   r   r   r   r   r   r   <module>   sX   
	 B   




N,