U
    ڲg                     @   s  d dl mZ d dlmZmZ d dlmZmZ zd dl mZ	 W n e
k
rX   ddl	Z	Y nX ddlZddlZddlZz(ejdk rddlZnddlZe ZW n e
k
r   dZY nX dd	 Zd
ZedejejB ZedejejB ZedejZedZedZedZedZdaedej Z!edZ"edZ#edZ$edZ%edZ&edZ'e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) Z0d*d+ Z1G d,d- d-e2Z3dS ).   )model)COMMON_TYPESresolve_common_type)FFIError	CDefError)
_pycparser    N)   c                  C   s   dd l } dd l} d S Nr   )Zpycparser.yacctabZpycparser.lextab)	pycparser r   0/tmp/pip-unpacked-wheel-lbi5ej3i/cffi/cparser.py%_workaround_for_static_import_finders   s    r   z<cdef source string>z/\*.*?\*/|//([^\n\\]|\\.)*?$z?^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)\b((?:[^\n\\]|\\.)*?)$z^[ \t]*#[ \t]*(?:line|\d+)\b.*$z=\s*\.\.\.\s*[,}]|\.\.\.\s*\}z__dotdotdot\d+__$z\[\s*\.\.\.\s*\]z\w+|\Sz-?0?x?[0-9a-f]+[lu]*$z\b(__stdcall|WINAPI)\bz[(]\s*(__stdcall|WINAPI)\bz\b__cdecl\bz9\bextern\s*"(Python|Python\s*\+\s*C|C\s*\+\s*Python)"\s*.z'[*]\s*((const|volatile|restrict)\b\s*)+z3(\b(int|long|short|signed|unsigned|char)\s*)+\.\.\.z\b(double|float)\s*\.\.\.c                   C   s   t d krt a t S N)_parser_cacher   ZCParserr   r   r   r   _get_parser2   s    r   c                 C   s  g }t | }|sq|| d |   |d d}||  | }| d|rl|d |d7 }d}|}|t| k r| | }|dkr|d7 }n.|dkr|dkrq|d8 }n|dkr|dkrq|d7 }qt| || | | |d   } q||  d|S )N()*r   r   z,;= )	_r_star_const_spacesearchappendstartgroupend
startswithlenjoin)csourcepartsmatchclosingendposlevelicr   r   r   _workaround_for_old_pycparser8   s:    

 
 



r'   c                 C   s,  g }t | }|sq| d }|| d |   d|dkrR|d n
|d | | dkr| d|}|dk rtd| d|d |dkrtd	|| |d |  | |d d  } nB| d
|}|dk rtd|| ||d   | |d d  } |d q||  d	|S )Nr   Cz(void __cffi_extern_python_plus_c_start; z!void __cffi_extern_python_start; {}r   z!'extern "Python" {': no '}' foundz7cannot use { } inside a block 'extern "Python" { ... }';z'extern "Python": no ';' foundz  void __cffi_extern_python_stop;r   )
_r_extern_pythonr   r   r   r   r   findr   NotImplementedErrorr   )r   r    r!   r#   r"   Z	semicolonr   r   r   _preprocess_extern_pythonb   s2    


r/   c                 C   sJ   d| krd S |   D ]0}d|kr| dsdd l}|d  qFqd S )N"#r   zString literal found in cdef() or type source. String literals are ignored here, but you should remove them anyway because some character sequences confuse pre-parsing.)
splitlineslstripr   warningswarn)r   liner4   r   r   r   _warn_for_string_literal   s    
r7   c                 C   s$   | j s dd l}|d| jf  d S )Nr   zrGlobal variable '%s' in cdef(): for consistency with C it should have a storage class specifier (usually 'extern'))Zstorager4   r5   name)declr4   r   r   r   /_warn_for_non_extern_non_static_global_variable   s
    r:   c                    s$   g   fdd}t || } |  fS )Nc                    s   t  } |   d| S )Nz#line@%d)r   r   r   )mr%   line_directivesr   r   replace   s    z(_remove_line_directives.<locals>.replace_r_line_directivesub)r   r>   r   r<   r   _remove_line_directives   s    rB   c                    s    fdd}t || S )Nc                    s.   |   }|dstd t|dd   S )Nz#line@zBunexpected #line directive (should have been processed and removed   )r   r   AssertionErrorint)r;   sr<   r   r   r>      s    
z*_put_back_line_directives.<locals>.replacer?   )r   r=   r>   r   r<   r   _put_back_line_directives   s    rG   c                 C   s  t | \} }dd }t|| } i }t| D ](}| \}}|dd }|||< q.td| } tj	dk rvt
| } td| } td| } td| } t| } t|  td	| } tt| }tt|D ]\}}| }	| |	 d
kr2| d|	| }
|
|	kstd| d |	 || |
d d  f } q| |	|	d  dksLtd| d |	 || |	d d  f } qtd| } td| } | dd} t| |} | |fS )Nc                 S   s   d|   dd  S )N 
)r   count)r;   r   r   r   replace_keeping_newlines   s    z-_preprocess.<locals>.replace_keeping_newlinesz\
r   z2.14z volatile volatile const(z volatile volatile const rH   z[__dotdotdotarray__]=...z%s,__dotdotdot%d__ %sr	   z%s __dotdotdot%d__ %sz __dotdotdotint__ z __dotdotdotfloat__ z __dotdotdot__ )rB   
_r_commentrA   	_r_definefinditergroupsr>   stripr   __version__r'   _r_stdcall2_r_stdcall1_r_cdeclr/   r7   _r_partial_arraylist_r_partial_enum	enumeratereversedr   r-   r   rD   _r_int_dotdotdot_r_float_dotdotdotrG   )r   r=   rK   macrosr!   Z	macronameZ
macrovaluematchesnumberpp2r   r   r   _preprocess   sF    


rc   c                 C   s   t t}|d |d |d |d |d t  }d}d}d}t| D ]}||kr|dkr|r|| || d}nj|dkrd	}d}nX|dkr|d
7 }nF|dkr|d
8 }n4|dkr|r|dkr|| || n
|| |}qV|S )Nr+   ,r   r   typedefFr   r   Tr   )setr   add_r_wordsfindalldiscard)r   Zlook_for_wordsZ
words_usedZ
is_typedefZparenZprevious_wordwordr   r   r   _common_type_names   s>    










rl   c                   @   s   e Zd Zdd Zdd Zdd Zdd Zd: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dZd d! Zd<d"d#Zd=d$d%Zd>d&d'Zd(d) Zd?d*d+Zd,d- Zd@d.d/Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd
S )AParserc                 C   s:   i | _ t | _d| _t | _i | _i | _g | _	d | _
d S r
   )_declarationsrf   _included_declarations_anonymous_counterweakrefWeakKeyDictionary_structnode2type_options_int_constants_recomplete_uses_new_featureselfr   r   r   __init__)  s    
zParser.__init__c              
   C   s6  t |\}}t|}g }t| jD ].}|dr"|dd  }|| || q"|t|7 }g }|d |D ]}|d|  qp|d |dtf  || |d d|}t	d k	rt	
  zJzt |}	W n4 tjjk
r }
 z| |
| W 5 d }
~
X Y nX W 5 t	d k	r*t	  X |	||fS )	Ntypedef    z*# 1 "<cdef automatic initialization code>"ztypedef int %s;z@typedef int __dotdotdotint__, __dotdotdotfloat__, __dotdotdot__;z# 1 "%s"r   rI   )rc   rl   sortedrn   r   r   rj   CDEF_SOURCE_STRINGr   lockacquirereleaser   parser   Zc_parser
ParseErrorconvert_pycparser_error)ry   r   r^   Zctn	typenamesr8   csourcelinestypenameZfullcsourceaster   r   r   _parse3  s6    






"

zParser._parsec                 C   sf   d }t |}tdtf |}|rbt|dd}| }d|  krRt|krbn n||d  }|S )Nz	%s:(\d+):r   
   )strrer!   r~   rE   r   r2   r   )ry   r   r   r6   msgr!   linenumr   r   r   r   _convert_pycparser_errorZ  s    zParser._convert_pycparser_errorc                 C   s@   |  ||}t|}|r*d| |f }n
d|f }t|d S )Nzcannot parse "%s"
%szparse error
%s)r   r   rR   r   )ry   r   r   r6   r   r   r   r   r   h  s    
zParser.convert_pycparser_errorFNc                 C   sz   |r&|dkrt d|r t dd}n$|rF||d @ rJt d|f nd}| j}z|||d| _| | W 5 || _X d S )NTzB'packed' should be False or True; use 'pack' to give another valuez$cannot give both 'pack' and 'packed'r   z%'pack' must be a power of two, not %rr   )overridepacked	dllexport)
ValueErrorrt   _internal_parse)ry   r   r   r   packr   Zprev_optionsr   r   r   r   r  s(    zParser.parsec              
   C   s8  |  |\}}}| | t|j}|D ]}|jdkr( qDq(dsDtd }zXd| _|D ]F}|}t|tj	j
rz| | qVt|tj	jrj|jstd|d}t|jjtj	jr|jjjd dr| |}nt|jtj	jr0t|jjtj	jr0t|jjjtj	jr0|jjjjd dr0| |}n"| j|j|jdd|jf d	\}}| jd
|j ||d qV|jjdkrdd l}	|	d qVtd|jj |qVW n tk
r }
 z$t|
jdkr|
j|f |
_ W 5 d }
~
X Y nN tk
r2 }
 z.| |
|}|r |
jd d|  f|
_ W 5 d }
~
X Y nX d S )N__dotdotdot__r   __cffi_extern_python_stopz!typedef does not declare any nameZ__dotdotdotTz*(%s *)0)r8   partial_length_oktypedef_exampler{   qualsZPragmaa  #pragma in cdef() are entirely ignored. They should be removed for now, otherwise your code might behave differently in a future version of CFFI if #pragma support gets added. Note that '#pragma pack' needs to be replaced with the 'packed' keyword argument to cdef().zBunexpected <%s>: this construct is valid C but not valid in cdef()r   z
    *** Err: %s) r   _process_macrositerextr8   rD   _inside_extern_python
isinstancer   c_astZDecl_parse_declZTypedefr   typeIdentifierTypenamesr   _get_unknown_typePtrDeclTypeDecl_get_unknown_ptr_type_get_type_and_quals_declare	__class____name__r4   r5   r   argsr   r   )ry   r   r   r^   iteratorr9   Zcurrent_declr   Zrealtyper4   r   r   r   r   r   r     sx    




  


zParser._internal_parsec                 C   s8   || j kr*| j | |krd S td|f || j |< d S )Nz%multiple declarations of constant: %s)ru   r   )ry   keyvalr   r   r   _add_constants  s    
zParser._add_constantsc                 C   s   |  d}|d}|r(|dd  }|drT|dkrT|dsTd|dd   }t|d}|rh| }| || | d| | d S )	Nul-r   00xZ0or   macro )lowerrstripr   rE   r   r   )ry   r8   Zint_strnegZpyvaluer   r   r   _add_integer_constant  s    

zParser._add_integer_constantc                 C   sd   |  D ]V\}}| }t|r0| || q|dkrJ| d| | qtd||||f qd S )NrM   r   zonly supports one of the following syntax:
  #define %s ...     (literally dot-dot-dot)
  #define %s NUMBER  (with NUMBER an integer constant, decimal/hex/octal)
got:
  #define %s %s)itemsrR   _r_int_literalr!   r   r   r   )ry   r^   r   valuer   r   r   r     s    

zParser._process_macrosc                 C   sX   |  ||}| jdrd}n$| jdkr.d}n| jdkr>d}nd}| ||j | d S )Nr   zdllexport_python Z__cffi_extern_python_startzextern_python Z!__cffi_extern_python_plus_c_startzextern_python_plus_c z	function )_get_type_pointerrt   getr   r   r8   )ry   tpr   r9   tagr   r   r   _declare_function  s    

zParser._declare_functionc                 C   s  |j }t|tjjrJ| j||jd\}}t|tjs8t	| 
||| nt|tjjrf| d| nHt|tjjr| d| n,t|tjjr| d| n|jstd||jr| j|dd\}}|jr| 
||| n0| r(t|dr(t|jd	r(t|jjr(| |j|jj n| rt|jtjjr|jjd
krt|jjd	rt|jjjr| |jd
|jjj  n|tjkr|jdr|j| _n^| jdkrtd|tj@ r|js| j d|j ||d nt!| | j d|j ||d d S )N)r8   structunionenumz'construct does not declare any variableTr   initr   r   Z__cffi_extern_python_r   z<cannot declare constants or variables with 'extern "Python"'z	constant r   z	variable )"r   r   r   r   FuncDeclr   r8   r   RawFunctionTyperD   r   Struct_get_struct_union_enum_typeUnionEnumr   Zis_raw_functionZis_integer_typehasattrr   r   r!   r   r   UnaryOpopexpr	void_typer   r   Q_CONSTZis_array_typer   r:   )ry   r9   noder   r   r   r   r   r     sj    






zParser._parse_declc                 C   s   |  |d S r
   )parse_type_and_quals)ry   cdeclr   r   r   
parse_type0  s    zParser.parse_typec                 C   s`   |  d| d d \}}|r"t|jd jjjd }t|tjj	rTt
d|jf | |jS )Nzvoid __dummy(
%s
);   r   r   zunknown identifier '%s')r   rD   r   r   r   paramsr   r   r   IDr   r8   r   )ry   r   r   r^   exprnoder   r   r   r   3  s    zParser.parse_type_and_qualsr   c                 C   sx   || j krF| j | \}}||kr,||kr,d S | jdsFtd|f d| ksVt||f| j |< |rt| j| d S )Nr   zPmultiple declarations of %s (for interactive usage, try cdef(xx, override=True))r   )rn   rt   r   r   splitrD   ro   rg   )ry   r8   objincludedr   ZprevobjZ	prevqualsr   r   r   r   ;  s    
zParser._declarec                 C   sZ   d}t |tjjtjjfrVd|jkr.|tjO }d|jkrB|tjO }d|jkrV|tj	O }|S )Nr   constvolatileZrestrict)
r   r   r   r   r   r   r   r   Z
Q_VOLATILEZ
Q_RESTRICTry   r   r   r   r   r   _extract_qualsI  s    






zParser._extract_qualsc                 C   sj   t |tjr| S t |tjr^|jdr^|jdd   r^|jd kr^|d k	r^t	|||S t
||S )N$r   )r   r   r   as_function_pointerZStructOrUnionOrEnumr8   r   isdigit	forcenameZNamedPointerTypePointerType)ry   r   r   declnamer   r   r   r   U  s    
zParser._get_type_pointerc                 C   sb  t |tjjrtt |jtjjrtt|jjdkrtd|jjd  | jkrt| jd|jjd   \}}|| 	|O }||fS t |tjj
r|jd krd }n| j|j|d}|d k	r|dkrd|f }d| }| j|j||d\}}t|||fS t |tjjr,| |j\}}	| j||	|d	}| 	|}||fS t |tjjr| 	|}|j}
t |
tjjrpt|
j}|d
dgkri }|r|d }|dkr||dd ||< |d= nqqxg }dD ](}t||dD ]}|| qАq|sdg}|dgkrd|ksd|krg }|| }d|}|dkr<tj|fS |dkrVtd|jj t| |\}}|||B fS t |
tjjr| d|
|}||fS t |
tjjr| d|
|}||fS t |
tjjr| d|
|}||fS t |tjj r| !||dfS t |tjjr(| jd||dddfS t |tjjrN| jd||dddfS td|jj d S )Nr   r{   r   r   rM   z_cffi_array_len(%s)r   )r   r   )r   signedchar)shortlongr   unsigned)r   r   r   rE   r   r   rH   voidr   z:%d: bad usage of "..."r   r   r   T)nestedz(:%d: bad or unsupported type declaration)"r   r   r   r   r   r   r   r   rn   r   Z	ArrayDeclZdim_parse_constantr   r   	ArrayTyper   r   rX   r   ranger   r   r   r   coordr6   r   r   r   r   r   r   _parse_function_type)ry   typenoder8   r   r   r   r   lengthZitemtypeZ	itemqualsr   r   prefixesZnewnamesprefixr%   identZtp0Zquals0r   r   r   r   ^  s    
 











zParser._get_type_and_qualsc              	      s6  t t|jdg }t|D ]4\}}t|dstd|p6d|d t|ddf qt|dkot|d	 jt	j
jot|d	 jjt	j
jo|d	 jjjd
gk}|r|  |std|pd  fdd|D }|s|tjgkrg } |j\}}	d }
t|jdr"|jjdd  dddgkr"d}
tt||||
S )Nr   r   zt%s arg %d: unknown type '%s' (if you meant to use the old C syntax of giving untyped arguments, it is not supported)zin expressionr   r8   ?r   r   r   z=%s: a function with only '(...)' as argument is not correct Cc                    s   g | ]} j  |j qS r   )_as_func_argr   r   ).0Zargdeclnoderx   r   r   
<listcomp>  s   z/Parser._parse_function_type.<locals>.<listcomp>r   r   r   Z	__stdcall)rX   getattrr   rZ   r   r   r   r   r   r   r   r   r   r   popr   r   r   r   r   tuple)ry   r   funcnamer   r%   argZellipsisr   resultr   abir   rx   r   r     sH    


zParser._parse_function_typec                 C   s6   t |tjrt|j|S t |tjr.| S |S d S r   )r   r   r   r   itemr   r   r   r   r   r   r     s
    zParser._as_func_argc                 C   s*  z| j | W S  tk
r    Y nX |}|j}|d krd|d k	rFd| }n|  jd7  _d| j }d }n"|}d||f }| j|d\}}	|d kr|dkrt|d d d }nP|dkrt|d d d }n6|dkr|d	krt	d
| 
||j}ntd|f |d k	r4| || n"|dkr4|jd k	r4td| |jsF|| |jrld|jkrl| d|j | || j |< |dkr|S |jd kr|S |jd k	rt	d| g }
g }g }g }|jD ]}t|jtjjrd|jjd	kr| || q|jd krd}n| |j}d| _| j|jdd\}}| jrH| || t|tjrj|jrj| || |
 |jpxd | | | | | | qt!|
|_t!||_"t!||_#t!||_$|dgt%| krt|tjr|jrtd|f | j&d|_'|j(r&d|_(| j) | |S )Nz$%sr   z$%dz%s %s)NNr   r   r   r   z!Enums cannot be declared with ...z	kind = %rz^enum %s: the '{}' declaration should appear on the first time the enum is mentioned, not laterr   zanonymous %sz"duplicate declaration of struct %sr   r   FTr   z#%s: using both bitfields and '...;'r   r   )*rs   KeyErrorr8   rp   rn   r   r   Z
StructTypeZ	UnionTyper   _build_enum_typevaluesrD   r   r.   r   Zforce_the_namedeclsfldnamesr   r   r   r   r   r   r   _make_partialbitsizer   _partial_lengthr   partialr   r  fldtypes
fldbitsizefldqualsr   rt   r   Z	completedrv   )ry   kindr   r8   r   Z
force_nameexplicit_namer   r   _r  r  r  r  r9   r  Zfqualr   r   r   r     s    	















z"Parser._get_struct_union_enum_typec                 C   s>   t |tjstd|f | s4|s4td|f d|_d S )Nz%s cannot be partialz%s is partial but has no C nameT)r   r   ZStructOrUnionr   Z
has_c_namer.   r  )ry   r   r   r   r   r   r  h  s
    zParser._make_partialc                 C   s  t |tjjr8|j}d|d   kr.dkrn n|d}z&|drTt|dW S t|dW S W nd tk
r   t	|dkr|
 dd d	krt|d
 Y S |
 dd dkrt|d Y S Y nX td|f n`|d dkr*|d dkr*t	|dkst	|dkr*|d dkr*t|d S td|f t |tjjr`|jdkr`| |jS t |tjjr|jdkr| |j S t |tjjr|j| jkr| j|j S t |tjjr|jdkr|rd| _dS td|jj t |tjjr| |j}| |j}|jdkr,|| S |jdkr@|| S |jdkrT|| S |jdkrl| ||S |jdkr|| |||  S |jdkr||> S |jdkr||? S |jdkr||@ S |jdkr||B S |jd kr||A S td!|jj d S )"Nr   r   9ZuUlLr|   r   r   r   r      0bzinvalid constant %r'r   r	      \+r   Z__dotdotdotarray__TrM   zT:%d: unsupported '[...]' here, cannot derive the actual array length in this contextr   /%z<<z>>&|^z?:%d: unsupported expression: expected a simple numeric constant)r   r   r   Constantr   r   r   rE   r   r   r   r   ordr   r   r   r   r   r8   ru   r  r   r   r6   ZBinaryOpleftright_c_div)ry   r   r   rF   r(  r)  r   r   r   r   o  s    





zParser._parse_constantc                 C   s0   || }|dk |dk A r,|| dkr,|d7 }|S )Nr   r   r   )ry   abr  r   r   r   r*    s    zParser._c_divc           	      C   s   |d k	rd}g }g }d}|j D ]X}t|jr4d}q|jd k	rJ| |j}||j || | |j| |d7 }qt|}t|}t	
|||}||_nt	
|dd}|S )NFr   Tr   r   )enumerators_r_enum_dotdotdotr!   r8   r   r   r   r   r  r   ZEnumTyper  )	ry   r  r  r  r-  Z
enumvaluesZnextenumvaluer   r   r   r   r   r    s*    



zParser._build_enum_typec                 C   sr   |j  D ]B\}\}}|dr"q
|ddd }|dkr
| j||d|d q
|j D ]\}}| || qXd S )Nzanonymous $enum_$rH   r   r   )r   r   r   Z	anonymousre   T)r   r   )rn   r   r   r   r   ru   r   )ry   otherr8   r   r   r  kvr   r   r   include  s    
zParser.includec                 C   s   |j j j}|dgkr t|jS |dgkrL| jd kr@d|j | _t|jS |dgkrx| jd krld|j | _t|jS td|j	j
 d S )Nr   Z__dotdotdotint__z'typedef int... %s'Z__dotdotdotfloat__z'typedef float... %s'*:%d: unsupported usage of "..." in typedef)r   r   r   Zunknown_typer8   rw   ZUnknownIntegerTypeZUnknownFloatTyper   r   r6   )ry   r9   r   r   r   r   r     s    





zParser._get_unknown_typec                 C   s2   |j j j jdgkrt|jS td|jj d S )Nr   r3  )r   r   r   Zunknown_ptr_typer8   r   r   r6   )ry   r9   r   r   r   r     s
    zParser._get_unknown_ptr_type)FFNF)Fr   )N)NFN)N)NF)F)r   
__module____qualname__rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r*  r  r2  r   r   r   r   r   r   rm   '  s>   
'
  
?3

	  
i
#
v
I
rm   )4r   r   Zcommontypesr   r   errorr   r   r   r   ImportErrorrq   r   sysversion_infothread_threadallocate_lockr   r   r~   compileDOTALL	MULTILINErN   rO   r@   rY   r.  rW   rh   r   
IGNORECASEr   rU   rT   rV   r,   r   r\   r]   r   r'   r/   r7   r:   rB   rG   rc   rl   objectrm   r   r   r   r   <module>   s`   














*2	B(