1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2017, VU University Amsterdam
    7    All rights reserved.
    8
    9    Redistribution and use in source and binary forms, with or without
   10    modification, are permitted provided that the following conditions
   11    are met:
   12
   13    1. Redistributions of source code must retain the above copyright
   14       notice, this list of conditions and the following disclaimer.
   15
   16    2. Redistributions in binary form must reproduce the above copyright
   17       notice, this list of conditions and the following disclaimer in
   18       the documentation and/or other materials provided with the
   19       distribution.
   20
   21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32    POSSIBILITY OF SUCH DAMAGE.
   33*/
   34
   35:- module(c99_grammar,
   36          [ c99_parse//1,               % -AST
   37            c99_parse_cont//1
   38          ]).   39:- use_module(library(debug)).   40:- use_module(ctokens).   41:- use_module(library(pprint)).         % debugging
   42
   43c99_parse(AST) -->
   44    { init_state },
   45    c99_parse_cont(AST).
   46
   47c99_parse_cont(AST) -->
   48    c99_tokens(Tokens),
   49    { phrase(translation_unit(AST), Tokens) }.
   50
   51
   52		 /*******************************
   53		 *       A.2.1 Expression	*
   54		 *******************************/
   55
   56primary_expression(E) --> opt_extension, [id(E)].
   57primary_expression(E) --> constant(E).
   58primary_expression(E) --> string_literal(E).
   59primary_expression(E) --> ['('], expression(E), [')'].
   60primary_expression(E) --> opt_extension, ['('],
   61			  compound_statement(E), [')']. % GCC extension
   62
   63opt_extension --> ['__extension__'], !.
   64opt_extension --> [].
   65
   66constant(i(I)) --> [i(I)].
   67constant(l(I)) --> [l(I)].
   68constant(ll(I)) --> [ll(I)].
   69constant(u(I)) --> [u(I)].
   70constant(ul(I)) --> [ul(I)].
   71constant(ull(I)) --> [ull(I)].
   72constant(float(F)) --> [float(F)].
   73constant(double(D)) --> [double(D)].
   74constant(enum_value(Name)) --> [enum_value(Name)].
   75constant(char(Codes)) --> [char(Codes)].
   76constant(wchar(Codes)) --> [wchar(Codes)].
   77
   78string_literal(str(S)) --> [str(S)].
   79string_literal(wstr(S)) --> [wstr(S)].
   80
   81postfix_expression(Expr) -->
   82    primary_expression(P),
   83    expression_postfixes(P, Expr).
   84
   85expression_postfixes(P, Expr) -->
   86    expression_postfix(P, Expr0), !,
   87    expression_postfixes(Expr0, Expr).
   88expression_postfixes(Expr, Expr) --> [].
   89
   90expression_postfix(E0, array(E0,I)) -->
   91    ['['], expression(I), [']'].
   92expression_postfix(E0, call(E0, List)) -->
   93    ['('], argument_expression_list_opt(List), [')'].
   94expression_postfix(E0, member(E0, Id)) -->
   95    [ '.', id(Id) ].
   96expression_postfix(E0, member_ptr(E0, Id)) -->
   97    [ '->', id(Id) ].
   98expression_postfix(E0, post_incr(E0)) -->
   99    [++].
  100expression_postfix(E0, post_decr(E0)) -->
  101    [--].
  102expression_postfix(E0, cast(E0, Type, Init)) -->
  103    ['('], type_name(Type), [')', '{'],
  104    initializer_list(Init), opt_comma, ['}'].
  105
  106argument_expression_list([H|T]) -->
  107    assignment_expression(H),
  108    (   [',']
  109    ->  argument_expression_list(T)
  110    ;   {T=[]}
  111    ).
  112
  113argument_expression_list_opt(List) -->
  114    argument_expression_list(List), !.
  115argument_expression_list_opt([]) --> [].
  116
  117unary_expression(E) -->
  118    postfix_expression(E).
  119unary_expression(++(UE)) -->
  120    [++], unary_expression(UE).
  121unary_expression(--(UE)) -->
  122    [--], unary_expression(UE).
  123unary_expression(o(Op, Expr)) -->
  124    unary_operator(Op),
  125    cast_expression(Expr).
  126unary_expression(sizeof(Expr)) -->
  127    [sizeof], unary_expression(Expr).
  128unary_expression(sizeof(type(Type))) -->
  129    [sizeof, '('], type_name(Type), [')'].
  130
  131unary_operator(&) --> [&].
  132unary_operator(*) --> [*].
  133unary_operator(+) --> [+].
  134unary_operator(-) --> [-].
  135unary_operator(~) --> [~].
  136unary_operator(!) --> [!].
  137
  138cast_expression(cast(Type, Expr)) -->
  139    ['('], type_name(Type), [')'], cast_expression(Expr).
  140cast_expression(Expr) -->
  141    unary_expression(Expr).
  142
  143multiplicative_expression(Expr) -->
  144    cast_expression(A),
  145    (   multiplicative_op(Op)
  146    ->  multiplicative_expression(B),
  147        { re_nest(Op, A, B, Expr) }
  148    ;   { Expr = A }
  149    ).
  150
  151multiplicative_op(*) --> [*].
  152multiplicative_op(/) --> [/].
  153multiplicative_op('%') --> ['%'].
  154
  155re_nest(Op, A, o(Op2, B, C), Expr) :-
  156    re_nest(Op2, o(Op,A,B), C, Expr).
  157re_nest(Op, A, B, o(Op, A, B)).
  158
  159additive_expression(Expr) -->
  160    multiplicative_expression(A),
  161    (   additive_op(Op)
  162    ->  additive_expression(B),
  163        { re_nest(Op, A, B, Expr) }
  164    ;   { Expr = A }
  165    ).
  166
  167additive_op(+) --> [+].
  168additive_op(-) --> [-].
  169
  170shift_expression(Expr) -->
  171    additive_expression(A),
  172    (   shift_op(Op)
  173    ->  shift_expression(B),
  174        { re_nest(Op, A, B, Expr) }
  175    ;   { Expr = A }
  176    ).
  177
  178shift_op(<<) --> [<<].
  179shift_op(>>) --> [>>].
  180
  181relational_expression(Expr) -->
  182    shift_expression(A),
  183    (   relational_op(Op)
  184    ->  relational_expression(B),
  185        { re_nest(Op, A, B, Expr) }
  186    ;   { Expr = A }
  187    ).
  188
  189relational_op(<) --> [<].
  190relational_op(>) --> [>].
  191relational_op(>=) --> [>=].
  192relational_op(<=) --> [<=].
  193
  194equality_expression(Expr) -->
  195    relational_expression(A),
  196    (   equality_op(Op)
  197    ->  equality_expression(B),
  198        { re_nest(Op, A, B, Expr) }
  199    ;   { Expr = A }
  200    ).
  201
  202equality_op(==) --> [==].
  203equality_op('!=') --> ['!='].
  204
  205and_expression(Expr) -->
  206    equality_expression(A),
  207    (   [&]
  208    ->  and_expression(B),
  209        { re_nest(&, A, B, Expr) }
  210    ;   { Expr = A }
  211    ).
  212
  213exclusive_or_expression(Expr) -->
  214    and_expression(A),
  215    (   [^]
  216    ->  exclusive_or_expression(B),
  217        { re_nest(^, A, B, Expr) }
  218    ;   { Expr = A }
  219    ).
  220
  221
  222inclusive_or_expression(Expr) -->
  223    exclusive_or_expression(A),
  224    (   ['|']
  225    ->  inclusive_or_expression(B),
  226        { re_nest('|', A, B, Expr) }
  227    ;   { Expr = A }
  228    ).
  229
  230logical_and_expression(Expr) -->
  231    inclusive_or_expression(A),
  232    (   [&&]
  233    ->  logical_and_expression(B),
  234        { re_nest(&&, A, B, Expr) }
  235    ;   { Expr = A }
  236    ).
  237
  238logical_or_expression(Expr) -->
  239    logical_and_expression(A),
  240    (   ['||']
  241    ->  logical_or_expression(B),
  242        { re_nest('||', A, B, Expr) }
  243    ;   { Expr = A }
  244    ).
  245
  246conditional_expression(Expr) -->
  247    logical_or_expression(A),
  248    (   [?]
  249    ->  expression(If),
  250        [:],
  251        conditional_expression(Then),
  252        { Expr = cond(A, If, Then) }
  253    ;   { Expr = A }
  254    ).
  255
  256assignment_expression(assign(Op, UE, AE)) -->
  257    unary_expression(UE),
  258    assignment_operator(Op),
  259    assignment_expression(AE).
  260assignment_expression(Expr) -->
  261    conditional_expression(Expr).
  262
  263assignment_expression_opt(Expr) -->
  264    assignment_expression(Expr).
  265assignment_expression_opt(-) --> [].
  266
  267assignment_operator(=)    --> [=].
  268assignment_operator(*=)   --> [*=].
  269assignment_operator(/=)   --> [/=].
  270assignment_operator('%=') --> ['%='].
  271assignment_operator(+=)   --> [+=].
  272assignment_operator(-=)   --> [-=].
  273assignment_operator(<<=)  --> [<<=].
  274assignment_operator(>>=)  --> [>>=].
  275assignment_operator(&=)   --> [&=].
  276assignment_operator(^=)   --> [^=].
  277assignment_operator('|=') --> ['|='].
  278
  279expression(Expr) -->
  280    assignment_expression(A),
  281    (   [',']
  282    ->  expression(B),
  283        { re_nest(=, A, B, Expr) }
  284    ;   { Expr = A }
  285    ).
  286
  287constant_expression(E) -->
  288    conditional_expression(E).
  289
  290
  291		 /*******************************
  292		 *      A2.2. Declarations	*
  293		 *******************************/
  294
  295declaration(Decl) -->
  296    declaration_specifiers(DS),
  297    specifiers_declaration(DS, Decl).
  298
  299specifiers_declaration(DS, decl(DS, I, GCC)) -->
  300    init_declarator_list(I),
  301    gcc_attributes_opt(GCC),
  302    [;].
  303
  304declaration_specifiers([H|T]) -->
  305    declaration_specifier(H), !,
  306    declaration_specifiers(T).
  307declaration_specifiers([]) --> [].
  308
  309declaration_specifier(DS) --> storage_class_specifier(DS).
  310declaration_specifier(DS) --> type_specifier(DS).
  311declaration_specifier(DS) --> type_qualifier(DS).
  312declaration_specifier(DS) --> function_specifier(DS).
  313declaration_specifier(DS) --> gcc_attributes(DS).
  314
  315init_declarator_list([H|T]) -->
  316    init_declarator(H),
  317    !,
  318    (   [',']
  319    ->  init_declarator_list(T)
  320    ;   { T = [] }
  321    ).
  322init_declarator_list([]) --> [].
  323
  324init_declarator(ID) -->
  325    declarator(D),
  326    (   [=]
  327    ->  initializer(I),
  328        {ID = (D=I)}
  329    ;   {ID = D}
  330    ).
  331
  332storage_class_specifier(storage(typedef))  --> [typedef].
  333storage_class_specifier(storage(extern))   --> [extern].
  334storage_class_specifier(storage(static))   --> [static].
  335storage_class_specifier(storage(auto))     --> [auto].
  336storage_class_specifier(storage(register)) --> [register].
  337
  338type_specifier(type(void))       --> [void].
  339type_specifier(type(char))       --> [char].
  340type_specifier(type(short))      --> [short].
  341type_specifier(type(int))        --> [int].
  342type_specifier(type(long))       --> [long].
  343type_specifier(type(size_t))     --> [size_t].  % Clang, MacOS
  344type_specifier(type(float))      --> [float].
  345type_specifier(type(double))     --> [double].
  346type_specifier(type(signed))     --> [signed].
  347type_specifier(type(signed))     --> ['__signed__'].
  348type_specifier(type(unsigned))   --> [unsigned].
  349type_specifier(type('_Bool'))    --> ['_Bool'].
  350type_specifier(type('_Complex')) --> ['_Complex'].
  351type_specifier(type('__uint128_t')) --> ['__uint128_t'].
  352type_specifier(type('__int128_t')) --> ['__int128_t'].
  353type_specifier(type('_Float16')) --> ['_Float16'].
  354type_specifier(type('_Float32')) --> ['_Float32'].
  355type_specifier(type('_Float32x')) --> ['_Float32x'].
  356type_specifier(type('_Float64')) --> ['_Float64'].
  357type_specifier(type('_Float64x')) --> ['_Float64x'].
  358type_specifier(type('_Float80')) --> ['_Float80'].
  359type_specifier(type('_Float128')) --> ['_Float128'].
  360type_specifier(type('__builtin_va_list')) --> ['__builtin_va_list'].
  361type_specifier(type('__gnuc_va_list')) --> ['__gnuc_va_list'].
  362type_specifier(type(Type))       --> [struct],   struct_specifier(Type).
  363type_specifier(type(Type))       --> [union],    union_specifier(Type).
  364type_specifier(type(Type))       --> [enum],     enum_specifier(Type).
  365type_specifier(type(Type))       --> [id(Name)], {typedef_name(Name, Type)}.
  366
  367struct_specifier(struct(Id, Fields)) -->
  368    opt_id(struct, Id),
  369    ['{'], struct_declaration_list(Fields), ['}'].
  370struct_specifier(struct(Id)) -->
  371    [ id(Id) ].
  372
  373union_specifier(union(Id, Fields)) -->
  374    opt_id(union, Id),
  375    ['{'], struct_declaration_list(Fields), ['}'].
  376union_specifier(union(Id)) -->
  377    [ id(Id) ].
  378
  379opt_id(_, Id)    --> [id(Id)], !.
  380opt_id(Sort, Id) -->
  381    { anon_id(Sort, Id) }.
  382
  383struct_declaration_list([H|T]) -->
  384    struct_declaration(H), !,
  385    struct_declaration_list(T).
  386struct_declaration_list([]) --> [].
  387
  388struct_declaration(f(QL, DL, GCC)) -->
  389    specifier_qualifier_list(QL),
  390    struct_declarator_list_opt(DL),             % GCC: optional
  391    gcc_attributes_opt(GCC),
  392    [;].
  393
  394specifier_qualifier_list([H|T]) -->
  395    specifier_qualifier(H), !,
  396    specifier_qualifier_list(T).
  397specifier_qualifier_list([]) --> [].
  398
  399specifier_qualifier(SQ) --> type_specifier(SQ).
  400specifier_qualifier(SQ) --> type_qualifier(SQ).
  401
  402struct_declarator_list_opt(List) -->
  403    struct_declarator_list(List), !.
  404struct_declarator_list_opt([]) --> [].
  405
  406struct_declarator_list([H|T]) -->
  407    struct_declarator(H),
  408    (   [',']
  409    ->  struct_declarator_list(T)
  410    ;   {T=[]}
  411    ).
  412
  413struct_declarator(SD) -->
  414    declarator(D),
  415    (   [:]
  416    ->  constant_expression(E),
  417        {SD = bitfield(D, E)}
  418    ;   {SD = d(D)}
  419    ).
  420struct_declarator(SD) -->
  421    [:], constant_expression(E),
  422    {SD = bitfield(-, E)}.
  423
  424enum_specifier(enum(ID, EL)) -->
  425    opt_id(enum, ID),
  426    ['{'], enumerator_list(EL), opt_comma, ['}'].
  427enum_specifier(enum(ID)) -->
  428    [id(ID)].
  429
  430enumerator_list([H|T]) -->
  431    enumerator(H), !,
  432    (   [','], \+ ['}']
  433    ->  enumerator_list(T)
  434    ;   {T=[]}
  435    ).
  436
  437enumerator(enum_value(H, V)) -->
  438    enumeration_constant(H),
  439    gcc_attributes_opt(_),
  440    (   [=]
  441    ->  constant_expression(V)
  442    ;   {V = (-)}
  443    ).
  444
  445enumeration_constant(Id) -->
  446    [id(Id)].
  447
  448opt_comma --> [','], !.
  449opt_comma --> [].
  450
  451type_qualifier(const)    --> [const].
  452type_qualifier(restrict) --> [restrict].
  453type_qualifier(volatile) --> [volatile].
  454type_qualifier('__restrict__') --> ['__restrict__']. % GCC
  455type_qualifier('__extension__') --> ['__extension__']. % GCC
  456type_qualifier('_Nonnull') --> ['_Nonnull']. % Clang, MacOS
  457type_qualifier('_Nullable') --> ['_Nullable']. % Clang, MacOS
  458
  459function_specifier(inline) --> [inline].
  460
  461declarator(declarator(P, DD)) --> pointer(P), !, direct_declarator(DD).
  462declarator(declarator(-, DD)) --> direct_declarator(DD).
  463
  464direct_declarator(Decl) -->
  465    gcc_attributes(_),   % GCC: we ignore <type> * __attribute((...))) ...
  466    !,
  467    direct_declarator(Decl).
  468direct_declarator(dd(Id, DDS)) -->
  469    [id(Id)], !,
  470    direct_declarator_suffix_opt(DDS).
  471direct_declarator(dd(D, DDS))  -->
  472    ['('], declarator(D), [')'],
  473    direct_declarator_suffix_opt(DDS).
  474
  475direct_declarator_suffix_opt(DDS) -->
  476    direct_declarator_suffix(DDS), !.
  477direct_declarator_suffix_opt(-) --> [].
  478
  479direct_declarator_suffix(DDS) -->
  480    ['['], array_direct_declarator_suffix(DDS), [']'].
  481direct_declarator_suffix(DDS) -->
  482    ['('], param_direct_declarator_suffix(DDS), [')'].
  483
  484array_direct_declarator_suffix(dds(TQL, Ass)) -->
  485    type_qualifier_list_opt(TQL), assignment_expression_opt(Ass).
  486array_direct_declarator_suffix(dds(TQL, Ass)) -->
  487    [static],
  488    type_qualifier_list_opt(TQL), assignment_expression(Ass).
  489array_direct_declarator_suffix(dds(TQL, Ass)) -->
  490    type_qualifier_list(TQL), [static], assignment_expression(Ass).
  491array_direct_declarator_suffix(dds(TQL, *)) -->
  492    type_qualifier_list_opt(TQL), ptr.
  493
  494param_direct_declarator_suffix(dds(PTL)) -->
  495    parameter_type_list(PTL), !.
  496param_direct_declarator_suffix(dds(IDList)) -->
  497    identifier_list_opt(IDList), !.
  498
  499
  500pointer([ptr(TQL)|T]) -->
  501    ptr, type_qualifier_list_opt(TQL),
  502    pointers(T).
  503
  504pointers([ptr(TQL)|T]) -->
  505    ptr, type_qualifier_list_opt(TQL), !,
  506    pointers(T).
  507pointers([]) --> [].
  508
  509ptr --> [*].
  510ptr --> [^].             % clang
  511
  512type_qualifier_list([H|T]) -->
  513    type_qualifier(H), !,
  514    type_qualifier_list_opt(T).
  515
  516type_qualifier_list_opt([H|T]) -->
  517    type_qualifier(H), !,
  518    type_qualifier_list_opt(T).
  519type_qualifier_list_opt([]) --> [].
  520
  521parameter_type_list(List) -->
  522    parameter_list(List, T),
  523    (   [',', '...']
  524    ->  {T=[param([], '...')]}
  525    ;   {T=[]}
  526    ).
  527
  528parameter_type_list_opt(List) -->
  529    parameter_type_list(List).
  530parameter_type_list_opt([]) --> [].
  531
  532parameter_list([H|T0], T) -->
  533    parameter_declaration(H),
  534    (   [','], \+ ['...']
  535    ->  parameter_list(T0, T)
  536    ;   {T=T0}
  537    ).
  538
  539parameter_declaration(param(S,D)) -->
  540    declaration_specifiers(S),
  541    (   declarator(D)
  542    ->  gcc_attributes_opt(_)
  543    ;   abstract_declarator_opt(D)
  544    ).
  545
  546identifier_list([H|T]) -->
  547    [id(H)],
  548    (   [',']
  549    ->  identifier_list(T)
  550    ;   {T=[]}
  551    ).
  552
  553identifier_list_opt(IDL) -->
  554    identifier_list(IDL), !.
  555identifier_list_opt([]) --> [].
  556
  557type_name(type_name(QL, D)) -->
  558    specifier_qualifier_list(QL), abstract_declarator_opt(D).
  559
  560abstract_declarator(ad(AD,DAD)) -->
  561    pointer_or_block(AD), !,
  562    (   direct_abstract_declarator(DAD)
  563    ->  []
  564    ;   {DAD = (-)}
  565    ).
  566abstract_declarator(ad(-,DAD)) -->
  567    direct_abstract_declarator(DAD).
  568
  569pointer_or_block(AD) -->
  570    pointer(AD), !.
  571pointer_or_block(AD) -->
  572    block(AD).
 block -Block// is semidet
Deal with Objective C block references that appear in the MacOSX headers. We assume they follow the same rules as (*) in function pointers.
  580block([block(TQL)|T]) -->
  581    [^], type_qualifier_list_opt(TQL),
  582    blocks(T).
  583
  584blocks([block(TQL)|T]) -->
  585    [^], type_qualifier_list_opt(TQL), !,
  586    blocks(T).
  587blocks([]) --> [].
  588
  589abstract_declarator_opt(AD) -->
  590    abstract_declarator(AD), !.
  591abstract_declarator_opt(ad(-,-)) --> [].
  592
  593direct_abstract_declarator(dad(AD,S)) -->
  594    (   ['('], abstract_declarator(AD), [')']
  595    ->  []
  596    ;   {AD = (-)}
  597    ),
  598    direct_abstract_declarator_suffix(S).
  599
  600direct_abstract_declarator_suffix(dads(TQL, Ass)) -->
  601    ['['],
  602    type_qualifier_list_opt(TQL), assignment_expression_opt(Ass),
  603    [']'], !.
  604direct_abstract_declarator_suffix(dads(TQL, Ass)) -->
  605    ['[', static],
  606    type_qualifier_list_opt(TQL), assignment_expression(Ass),
  607    [']'], !.
  608direct_abstract_declarator_suffix(dads(TQL, Ass)) -->
  609    ['['],
  610    type_qualifier_list(TQL), [static], assignment_expression(Ass),
  611    [']'], !.
  612direct_abstract_declarator_suffix(dads(*)) -->
  613    ['[',*,']'], !.
  614direct_abstract_declarator_suffix(dads(PTL)) -->
  615    ['('], parameter_type_list_opt(PTL), [')'], !.
  616direct_abstract_declarator_suffix(-) -->
  617    [].
  618
  619typedef_name(Name, Type) :-
  620    defined_type(Name),
  621    Type = user_type(Name).
  622
  623initializer(init(E)) -->
  624    assignment_expression(E).
  625initializer(init(IL)) -->
  626    ['{'], initializer_list(IL), opt_comma, ['}'], !.
  627
  628initializer_list([H|T]) -->
  629    initializer1(H), !,
  630    (   [',']
  631    ->  initializer_list(T)
  632    ;   []
  633    ).
  634initializer_list([]) --> [].
  635
  636initializer1(init(D,I)) -->
  637    designation(D), !,
  638    initializer(I).
  639initializer1(init(-,I)) -->
  640    initializer(I).
  641
  642designation(D) -->
  643    designator_list(D), [=], !.
  644
  645designator_list([H|T]) -->
  646    designator(H),
  647    designator_list_opt(T).
  648
  649designator_list_opt([H|T]) -->
  650    designator(H), !,
  651    designator_list_opt(T).
  652designator_list_opt([]) --> [].
  653
  654designator([E]) -->
  655    constant_expression(E).
  656designator(.(Id)) -->
  657    [id(Id)].
 gcc_attributes(-Term)
Process GCC __attribute((List)) syntax @see https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
  664gcc_attributes_opt([H|T]) -->
  665    gcc_attributes(H), !,
  666    gcc_attributes_opt(T).
  667gcc_attributes_opt([]) --> [].
  668
  669gcc_attributes(gcc_attributes(List)) -->
  670    ['__attribute__', '(', '('], gcc_attribute_list(List), [')', ')'].
  671gcc_attributes(ASM) -->
  672    asm(ASM).
  673
  674gcc_attribute_list(List) -->
  675    [','], !,
  676    gcc_attribute_list(List).
  677gcc_attribute_list([H|T]) -->
  678    gcc_attribute(H),
  679    (   [',']
  680    ->  gcc_attribute_list(T)
  681    ;   {T=[]}
  682    ).
  683
  684gcc_attribute(H) -->
  685    gcc_attribute_name(Name),
  686    (   ['(']
  687    ->  gcc_attribute_param_list(Params), [')'],
  688        { H =.. [Name|Params] }
  689    ;   { H = Name }
  690    ).
  691
  692gcc_attribute_name(H) --> [id(H)].
  693gcc_attribute_name(H) --> [H], {atom(H)}.
  694
  695gcc_attribute_param_list([]), [')'] -->
  696    [')'], !.
  697gcc_attribute_param_list([H|T]) -->
  698    gcc_attribute_param(Name),
  699    (   {Name == introduced},		% Clang, MacOS
  700        [=],
  701        version(V)
  702    ->  {H = (Name=V)}
  703    ;   {atom(Name)},
  704        [=],
  705        constant_expression(V)
  706    ->  {H = (Name=V)}
  707    ;   {H = Name}
  708    ),
  709    (   [',']
  710    ->  gcc_attribute_param_list(T)
  711    ;   {T=[]}
  712    ).
  713
  714gcc_attribute_param(H) -->
  715    gcc_attribute_name(H).
  716gcc_attribute_param(H) -->
  717    constant_expression(H).
  718gcc_attribute_param(alignof(Decl)) -->
  719    ['__alignof__', '('], declaration_specifiers(Decl), [')'].
  720
  721version(String) -->
  722    [double(D), '.', i(I)],
  723    !,
  724    { format(string(String), '~w.~d', [D, I]) }.
  725version(String) -->
  726    [double(D)],
  727    !,
  728    { format(string(String), '~w', [D]) }.
  729
  730asm(ASM) -->
  731    ['__asm__', '('], asm_list(Statements), [')'],
  732    { ASM = asm(Statements) }.
  733
  734asm_list([H|T]) -->
  735    [ str(H) ], !,
  736    asm_list(T).
  737asm_list([]) --> [].
  738
  739
  740		 /*******************************
  741		 *       A.2.3 Statements	*
  742		 *******************************/
  743
  744statement(S) --> labeled_statement(S).
  745statement(S) --> compound_statement(S).
  746statement(S) --> expression_statement(S).
  747statement(S) --> selection_statement(S).
  748statement(S) --> iteration_statement(S).
  749statement(S) --> jump_statement(S).
  750
  751labeled_statement(label(L, Statement)) -->
  752    [id(L), :], !, statement(Statement).
  753labeled_statement(case(V, Statement)) -->
  754    [case], constant_expression(V), [:], !, statement(Statement).
  755labeled_statement(default(Statement)) -->
  756    [default, :], !, statement(Statement).
  757
  758compound_statement(block(Statements)) -->
  759    ['{'], block_item_list_opt(Statements), ['}'].
  760
  761block_item_list_opt([H|T]) -->
  762    block_item(H), !,
  763    block_item_list_opt(T).
  764block_item_list_opt([]) --> [].
  765
  766block_item(H) --> declaration(H).
  767block_item(H) --> statement(H).
  768
  769expression_statement(E) -->
  770    expression_opt(E), [;], !.
  771
  772expression_opt(E) -->
  773    expression(E), !.
  774expression_opt(void) -->
  775    [].
  776
  777selection_statement(if(Cond, If, Then)) -->
  778    [if, '('], expression(Cond), [')'],
  779    statement(If),
  780    (   [else]
  781    ->  statement(Then)
  782    ;   {Then = void}
  783    ).
  784selection_statement(switch(Expr, Statement)) -->
  785    [switch, '('], expression(Expr), [')'],
  786    statement(Statement).
  787
  788iteration_statement(while(Expr, Statement)) -->
  789    [while, '('], expression(Expr), [')'], statement(Statement).
  790iteration_statement(do_while(Expr, Statement)) -->
  791    [do], statement(Statement), [while, '('], expression(Expr), [')', ';'].
  792iteration_statement(for(Init, Cond, Iter, Statement)) -->
  793    [for, '('], expression_opt(Init), [;], expression_opt(Cond), [;],
  794    expression_opt(Iter), [')'], statement(Statement).
  795iteration_statement(for2(Decl, Expr1, Expr2, Statement)) -->
  796    [for, '('], declaration(Decl), expression_opt(Expr1), [;],
  797    expression_opt(Expr2), [')'], statement(Statement).
  798
  799jump_statement(goto(Id)) -->
  800    [ goto, id(Id), ';' ].
  801jump_statement(continue) -->
  802    [ continue, ';' ].
  803jump_statement(break) -->
  804    [ break, ';' ].
  805jump_statement(return(Expr)) -->
  806    [ return ], expression_statement(Expr).
  807
  808		 /*******************************
  809		 *            A.2.4		*
  810		 *******************************/
  811
  812translation_unit([H|T]) -->
  813    external_declaration(H), !,
  814    { update_types(H),
  815      (   debugging(c99(unit))
  816      ->  print_term(H, [output(user_error)]), nl(user_error)
  817      ;   true
  818      )
  819    },
  820    translation_unit(T).
  821translation_unit(List) -->
  822    skip_unit, !,
  823    translation_unit(List).
  824translation_unit([]) --> [].
  825
  826external_declaration(D) -->
  827    declaration_specifiers(DS), !,
  828    (   specifiers_declaration(DS, D)
  829    ;   function_definition(DS, D)
  830    ).
  831external_declaration(D) --> pp(D).
  832
  833function_definition(Specifiers,
  834                    function(Specifiers, Declarator, Params, Body)) -->
  835    declarator(Declarator),
  836    declaration_list_opt(Params),
  837    compound_statement(Body).
  838
  839declaration_list_opt([H|T]) -->
  840    declaration(H), !,
  841    declaration_list_opt(T).
  842declaration_list_opt([]) --> [].
  843
  844pp(pp(Line)) -->
  845    [pp(Line)].
  846
  847		 /*******************************
  848		 *             SKIP		*
  849		 *******************************/
  850
  851skip_unit -->
  852    here(Start),
  853    skip_unit([]),
  854    here(End),
  855    { diff(Start, End, Skipped),
  856      (   memberchk('__extension__', Skipped)
  857      ->  (   debugging(c99(extension))
  858          ->  print_message(informational, ffi(skipped_header(Skipped)))
  859          ;   true
  860          )
  861      ;   print_message(warning, ffi(skipped_header(Skipped)))
  862      )
  863    }.
  864
  865skip_unit(Stack) --> open_bracket(Close), !, skip_unit([Close|Stack]).
  866skip_unit(['}']) --> ['}'], !.
  867skip_unit([Close|Stack]) --> [Close], !, skip_unit(Stack).
  868skip_unit([]) --> [';'], !.
  869skip_unit(Stack) --> [_], skip_unit(Stack).
  870
  871here(List, List, List).
  872
  873diff(Start, End, Skipped) :- Start == End, !, Skipped = [].
  874diff([H|T0], End, [H|T]) :- diff(T0, End, T).
  875
  876open_bracket(')') --> ['('].
  877open_bracket(']') --> ['['].
  878open_bracket('}') --> ['{'].
  879
  880
  881		 /*******************************
  882		 *              STATE		*
  883		 *******************************/
  884
  885:- thread_local
  886    typedef/1,
  887    anon/2.  888
  889init_state :-
  890    retractall(typedef(_)),
  891    retractall(anon(_,_)).
  892
  893defined_type(Name) :-
  894    typedef(Name).
  895
  896update_types(decl(What, As, _GCC)) :-
  897    memberchk(storage(typedef), What), !,
  898    forall(( member(A, As),
  899             declarator_name(A, Name)
  900           ),
  901           assertz(typedef(Name))).
  902update_types(_).
  903
  904anon_id(Sort, Id) :-
  905    (   retract(anon(Sort, I0))
  906    ->  I is I0+1
  907    ;   I = 1
  908    ),
  909    asserta(anon(Sort, I)),
  910    atomic_list_concat(['_:', Sort, '_', I], Id).
  911
  912
  913		 /*******************************
  914		 *           EXAMINE AST	*
  915		 *******************************/
  916
  917declarator_name(declarator(_Ptr, dd(Name, _)), Name) :-
  918    atom(Name), !.
  919% typedef ssize_t (*Sread_function)(void *handle, char *buf, size_t bufsize);
  920declarator_name(declarator(_Ptr, dd(Declarator,_)), Name) :-
  921    declarator_name(Declarator, Name).
  922
  923
  924		 /*******************************
  925		 *            MESSAGES		*
  926		 *******************************/
  927
  928:- multifile
  929    prolog:message//1.  930
  931prolog:message(ffi(Msg)) -->
  932    message(Msg).
  933
  934message(skipped_header(Tokens)) -->
  935    [ 'FFI: Could not parse ~p'-[Tokens] ]