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(op(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(float))      --> [float].
  344type_specifier(type(double))     --> [double].
  345type_specifier(type(signed))     --> [signed].
  346type_specifier(type(unsigned))   --> [unsigned].
  347type_specifier(type('_Bool'))    --> ['_Bool'].
  348type_specifier(type('_Complex')) --> ['_Complex'].
  349type_specifier(type('_Float128')) --> ['_Float128'].
  350type_specifier(type('__builtin_va_list')) --> ['__builtin_va_list'].
  351type_specifier(type('__gnuc_va_list')) --> ['__gnuc_va_list'].
  352type_specifier(type(Type))       --> [struct],   struct_specifier(Type).
  353type_specifier(type(Type))       --> [union],    union_specifier(Type).
  354type_specifier(type(Type))       --> [enum],     enum_specifier(Type).
  355type_specifier(type(Type))       --> [id(Name)], {typedef_name(Name, Type)}.
  356
  357struct_specifier(struct(Id, Fields)) -->
  358    opt_id(struct, Id),
  359    ['{'], struct_declaration_list(Fields), ['}'].
  360struct_specifier(struct(Id)) -->
  361    [ id(Id) ].
  362
  363union_specifier(union(Id, Fields)) -->
  364    opt_id(union, Id),
  365    ['{'], struct_declaration_list(Fields), ['}'].
  366union_specifier(union(Id)) -->
  367    [ id(Id) ].
  368
  369opt_id(_, Id)    --> [id(Id)], !.
  370opt_id(Sort, Id) -->
  371    { anon_id(Sort, Id) }.
  372
  373struct_declaration_list([H|T]) -->
  374    struct_declaration(H), !,
  375    struct_declaration_list(T).
  376struct_declaration_list([]) --> [].
  377
  378struct_declaration(f(QL, DL, GCC)) -->
  379    specifier_qualifier_list(QL),
  380    struct_declarator_list_opt(DL),             % GCC: optional
  381    gcc_attributes_opt(GCC),
  382    [;].
  383
  384specifier_qualifier_list([H|T]) -->
  385    specifier_qualifier(H), !,
  386    specifier_qualifier_list(T).
  387specifier_qualifier_list([]) --> [].
  388
  389specifier_qualifier(SQ) --> type_specifier(SQ).
  390specifier_qualifier(SQ) --> type_qualifier(SQ).
  391
  392struct_declarator_list_opt(List) -->
  393    struct_declarator_list(List), !.
  394struct_declarator_list_opt([]) --> [].
  395
  396struct_declarator_list([H|T]) -->
  397    struct_declarator(H),
  398    (   [',']
  399    ->  struct_declarator_list(T)
  400    ;   {T=[]}
  401    ).
  402
  403struct_declarator(SD) -->
  404    declarator(D),
  405    (   [:]
  406    ->  constant_expression(E),
  407        {SD = bitfield(D, E)}
  408    ;   {SD = d(D)}
  409    ).
  410struct_declarator(SD) -->
  411    [:], constant_expression(E),
  412    {SD = bitfield(-, E)}.
  413
  414enum_specifier(enum(ID, EL)) -->
  415    opt_id(enum, ID),
  416    ['{'], enumerator_list(EL), opt_comma, ['}'].
  417enum_specifier(enum(ID)) -->
  418    [id(ID)].
  419
  420enumerator_list([H|T]) -->
  421    enumerator(H), !,
  422    (   [','], \+ ['}']
  423    ->  enumerator_list(T)
  424    ;   {T=[]}
  425    ).
  426
  427enumerator(enum_value(H, V)) -->
  428    enumeration_constant(H),
  429    (   [=]
  430    ->  constant_expression(V)
  431    ;   {V = (-)}
  432    ).
  433
  434enumeration_constant(Id) -->
  435    [id(Id)].
  436
  437opt_comma --> [','], !.
  438opt_comma --> [].
  439
  440type_qualifier(const)    --> [const].
  441type_qualifier(restrict) --> [restrict].
  442type_qualifier(volatile) --> [volatile].
  443type_qualifier('__restrict__') --> ['__restrict__']. % GCC
  444type_qualifier('__extension__') --> ['__extension__']. % GCC
  445
  446function_specifier(inline) --> [inline].
  447
  448declarator(declarator(P, DD)) --> pointer(P), !, direct_declarator(DD).
  449declarator(declarator(-, DD)) --> direct_declarator(DD).
  450
  451direct_declarator(Decl) -->
  452    gcc_attributes(_),   % GCC: we ignore <type> * __attribute((...))) ...
  453    !,
  454    direct_declarator(Decl).
  455direct_declarator(dd(Id, DDS)) -->
  456    [id(Id)], !,
  457    direct_declarator_suffix_opt(DDS).
  458direct_declarator(dd(D, DDS))  -->
  459    ['('], declarator(D), [')'],
  460    direct_declarator_suffix_opt(DDS).
  461
  462direct_declarator_suffix_opt(DDS) -->
  463    direct_declarator_suffix(DDS), !.
  464direct_declarator_suffix_opt(-) --> [].
  465
  466direct_declarator_suffix(DDS) -->
  467    ['['], array_direct_declarator_suffix(DDS), [']'].
  468direct_declarator_suffix(DDS) -->
  469    ['('], param_direct_declarator_suffix(DDS), [')'].
  470
  471array_direct_declarator_suffix(dds(TQL, Ass)) -->
  472    type_qualifier_list_opt(TQL), assignment_expression_opt(Ass).
  473array_direct_declarator_suffix(dds(TQL, Ass)) -->
  474    [static],
  475    type_qualifier_list_opt(TQL), assignment_expression(Ass).
  476array_direct_declarator_suffix(dds(TQL, Ass)) -->
  477    type_qualifier_list(TQL), [static], assignment_expression(Ass).
  478array_direct_declarator_suffix(dds(TQL, *)) -->
  479    type_qualifier_list_opt(TQL), [*].
  480
  481param_direct_declarator_suffix(dds(PTL)) -->
  482    parameter_type_list(PTL), !.
  483param_direct_declarator_suffix(dds(IDList)) -->
  484    identifier_list_opt(IDList), !.
  485
  486
  487pointer([ptr(TQL)|T]) -->
  488    [*], type_qualifier_list_opt(TQL),
  489    pointers(T).
  490
  491pointers([ptr(TQL)|T]) -->
  492    [*], type_qualifier_list_opt(TQL), !,
  493    pointers(T).
  494pointers([]) --> [].
  495
  496type_qualifier_list([H|T]) -->
  497    type_qualifier(H), !,
  498    type_qualifier_list_opt(T).
  499
  500type_qualifier_list_opt([H|T]) -->
  501    type_qualifier(H), !,
  502    type_qualifier_list_opt(T).
  503type_qualifier_list_opt([]) --> [].
  504
  505parameter_type_list(List) -->
  506    parameter_list(List, T),
  507    (   [',', '...']
  508    ->  {T=[param([], '...')]}
  509    ;   {T=[]}
  510    ).
  511
  512parameter_type_list_opt(List) -->
  513    parameter_type_list(List).
  514parameter_type_list_opt([]) --> [].
  515
  516parameter_list([H|T0], T) -->
  517    parameter_declaration(H),
  518    (   [','], \+ ['...']
  519    ->  parameter_list(T0, T)
  520    ;   {T=T0}
  521    ).
  522
  523parameter_declaration(param(S,D)) -->
  524    declaration_specifiers(S),
  525    (   declarator(D)
  526    ->  []
  527    ;   abstract_declarator_opt(D)
  528    ).
  529
  530identifier_list([H|T]) -->
  531    [id(H)],
  532    (   [',']
  533    ->  identifier_list(T)
  534    ;   {T=[]}
  535    ).
  536
  537identifier_list_opt(IDL) -->
  538    identifier_list(IDL), !.
  539identifier_list_opt([]) --> [].
  540
  541type_name(type_name(QL, D)) -->
  542    specifier_qualifier_list(QL), abstract_declarator_opt(D).
  543
  544abstract_declarator(ad(AD,DAD)) -->
  545    pointer_or_block(AD), !,
  546    (   direct_abstract_declarator(DAD)
  547    ->  []
  548    ;   {DAD = (-)}
  549    ).
  550abstract_declarator(ad(-,DAD)) -->
  551    direct_abstract_declarator(DAD).
  552
  553pointer_or_block(AD) -->
  554    pointer(AD), !.
  555pointer_or_block(AD) -->
  556    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.
  564block([block(TQL)|T]) -->
  565    [^], type_qualifier_list_opt(TQL),
  566    blocks(T).
  567
  568blocks([block(TQL)|T]) -->
  569    [^], type_qualifier_list_opt(TQL), !,
  570    blocks(T).
  571blocks([]) --> [].
  572
  573abstract_declarator_opt(AD) -->
  574    abstract_declarator(AD), !.
  575abstract_declarator_opt(ad(-,-)) --> [].
  576
  577direct_abstract_declarator(dad(AD,S)) -->
  578    (   ['('], abstract_declarator(AD), [')']
  579    ->  []
  580    ;   {AD = (-)}
  581    ),
  582    direct_abstract_declarator_suffix(S).
  583
  584direct_abstract_declarator_suffix(dads(TQL, Ass)) -->
  585    ['['],
  586    type_qualifier_list_opt(TQL), assignment_expression_opt(Ass),
  587    [']'], !.
  588direct_abstract_declarator_suffix(dads(TQL, Ass)) -->
  589    ['[', static],
  590    type_qualifier_list_opt(TQL), assignment_expression(Ass),
  591    [']'], !.
  592direct_abstract_declarator_suffix(dads(TQL, Ass)) -->
  593    ['['],
  594    type_qualifier_list(TQL), [static], assignment_expression(Ass),
  595    [']'], !.
  596direct_abstract_declarator_suffix(dads(*)) -->
  597    ['[',*,']'], !.
  598direct_abstract_declarator_suffix(dads(PTL)) -->
  599    ['('], parameter_type_list_opt(PTL), [')'], !.
  600direct_abstract_declarator_suffix(-) -->
  601    [].
  602
  603typedef_name(Name, Type) :-
  604    defined_type(Name),
  605    Type = user_type(Name).
  606
  607initializer(init(E)) -->
  608    assignment_expression(E).
  609initializer(init(IL)) -->
  610    ['{'], initializer_list(IL), opt_comma, ['}'], !.
  611
  612initializer_list([H|T]) -->
  613    initializer1(H), !,
  614    (   [',']
  615    ->  initializer_list(T)
  616    ;   []
  617    ).
  618initializer_list([]) --> [].
  619
  620initializer1(init(D,I)) -->
  621    designation(D), !,
  622    initializer(I).
  623initializer1(init(-,I)) -->
  624    initializer(I).
  625
  626designation(D) -->
  627    designator_list(D), [=], !.
  628
  629designator_list([H|T]) -->
  630    designator(H),
  631    designator_list_opt(T).
  632
  633designator_list_opt([H|T]) -->
  634    designator(H), !,
  635    designator_list_opt(T).
  636designator_list_opt([]) --> [].
  637
  638designator([E]) -->
  639    constant_expression(E).
  640designator(.(Id)) -->
  641    [id(Id)].
 gcc_attributes(-Term)
Process GCC __attribute((List)) syntax @see https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
  648gcc_attributes_opt([H|T]) -->
  649    gcc_attributes(H), !,
  650    gcc_attributes_opt(T).
  651gcc_attributes_opt([]) --> [].
  652
  653gcc_attributes(gcc_attributes(List)) -->
  654    ['__attribute__', '(', '('], gcc_attribute_list(List), [')', ')'].
  655gcc_attributes(ASM) -->
  656    asm(ASM).
  657
  658gcc_attribute_list(List) -->
  659    [','], !,
  660    gcc_attribute_list(List).
  661gcc_attribute_list([H|T]) -->
  662    gcc_attribute(H),
  663    (   [',']
  664    ->  gcc_attribute_list(T)
  665    ;   {T=[]}
  666    ).
  667
  668gcc_attribute(H) -->
  669    gcc_attribute_name(Name),
  670    (   ['(']
  671    ->  gcc_attribute_param_list(Params), [')'],
  672        { H =.. [Name|Params] }
  673    ;   { H = Name }
  674    ).
  675
  676gcc_attribute_name(H) --> [id(H)].
  677gcc_attribute_name(H) --> [H], {atom(H)}.
  678
  679gcc_attribute_param_list([]), [')'] -->
  680    [')'], !.
  681gcc_attribute_param_list([H|T]) -->
  682    gcc_attribute_param(Name),
  683    (   {atom(Name)},
  684        [=],
  685        constant_expression(V)
  686    ->  {H = (Name=V)}
  687    ;   {H = Name}
  688    ),
  689    (   [',']
  690    ->  gcc_attribute_param_list(T)
  691    ;   {T=[]}
  692    ).
  693
  694gcc_attribute_param(H) -->
  695    gcc_attribute_name(H).
  696gcc_attribute_param(H) -->
  697    constant_expression(H).
  698gcc_attribute_param(alignof(Decl)) -->
  699    ['__alignof__', '('], declaration_specifiers(Decl), [')'].
  700
  701asm(ASM) -->
  702    ['__asm__', '('], asm_list(Statements), [')'],
  703    { ASM = asm(Statements) }.
  704
  705asm_list([H|T]) -->
  706    [ str(H) ], !,
  707    asm_list(T).
  708asm_list([]) --> [].
  709
  710
  711		 /*******************************
  712		 *       A.2.3 Statements	*
  713		 *******************************/
  714
  715statement(S) --> labeled_statement(S).
  716statement(S) --> compound_statement(S).
  717statement(S) --> expression_statement(S).
  718statement(S) --> selection_statement(S).
  719statement(S) --> iteration_statement(S).
  720statement(S) --> jump_statement(S).
  721
  722labeled_statement(label(L, Statement)) -->
  723    [id(L), :], !, statement(Statement).
  724labeled_statement(case(V, Statement)) -->
  725    [case], constant_expression(V), [:], !, statement(Statement).
  726labeled_statement(default(Statement)) -->
  727    [default, :], !, statement(Statement).
  728
  729compound_statement(block(Statements)) -->
  730    ['{'], block_item_list_opt(Statements), ['}'].
  731
  732block_item_list_opt([H|T]) -->
  733    block_item(H), !,
  734    block_item_list_opt(T).
  735block_item_list_opt([]) --> [].
  736
  737block_item(H) --> declaration(H).
  738block_item(H) --> statement(H).
  739
  740expression_statement(E) -->
  741    expression_opt(E), [;], !.
  742
  743expression_opt(E) -->
  744    expression(E), !.
  745expression_opt(void) -->
  746    [].
  747
  748selection_statement(if(Cond, If, Then)) -->
  749    [if, '('], expression(Cond), [')'],
  750    statement(If),
  751    (   [else]
  752    ->  statement(Then)
  753    ;   {Then = void}
  754    ).
  755selection_statement(switch(Expr, Statement)) -->
  756    [switch, '('], expression(Expr), [')'],
  757    statement(Statement).
  758
  759iteration_statement(while(Expr, Statement)) -->
  760    [while, '('], expression(Expr), [')'], statement(Statement).
  761iteration_statement(do_while(Expr, Statement)) -->
  762    [do], statement(Statement), [while, '('], expression(Expr), [')', ';'].
  763iteration_statement(for(Init, Cond, Iter, Statement)) -->
  764    [for, '('], expression_opt(Init), [;], expression_opt(Cond), [;],
  765    expression_opt(Iter), [')'], statement(Statement).
  766iteration_statement(for2(Decl, Expr1, Expr2, Statement)) -->
  767    [for, '('], declaration(Decl), expression_opt(Expr1), [;],
  768    expression_opt(Expr2), [')'], statement(Statement).
  769
  770jump_statement(goto(Id)) -->
  771    [ goto, id(Id), ';' ].
  772jump_statement(continue) -->
  773    [ continue, ';' ].
  774jump_statement(break) -->
  775    [ break, ';' ].
  776jump_statement(return(Expr)) -->
  777    [ return ], expression_statement(Expr).
  778
  779		 /*******************************
  780		 *            A.2.4		*
  781		 *******************************/
  782
  783translation_unit([H|T]) -->
  784    external_declaration(H), !,
  785    { update_types(H),
  786      (   debugging(c99(unit))
  787      ->  print_term(H, [output(user_error)]), nl(user_error)
  788      ;   true
  789      )
  790    },
  791    translation_unit(T).
  792translation_unit(List) -->
  793    skip_unit, !,
  794    translation_unit(List).
  795translation_unit([]) --> [].
  796
  797external_declaration(D) -->
  798    declaration_specifiers(DS), !,
  799    (   specifiers_declaration(DS, D)
  800    ;   function_definition(DS, D)
  801    ).
  802external_declaration(D) --> pp(D).
  803
  804function_definition(Specifiers,
  805                    function(Specifiers, Declarator, Params, Body)) -->
  806    declarator(Declarator),
  807    declaration_list_opt(Params),
  808    compound_statement(Body).
  809
  810declaration_list_opt([H|T]) -->
  811    declaration(H), !,
  812    declaration_list_opt(T).
  813declaration_list_opt([]) --> [].
  814
  815pp(pp(Line)) -->
  816    [pp(Line)].
  817
  818		 /*******************************
  819		 *             SKIP		*
  820		 *******************************/
  821
  822skip_unit -->
  823    here(Start),
  824    skip_unit([]),
  825    here(End),
  826    { diff(Start, End, Skipped),
  827      (   memberchk('__extension__', Skipped)
  828      ->  (   debugging(c99(extension))
  829          ->  print_message(informational, ffi(skipped_header(Skipped)))
  830          ;   true
  831          )
  832      ;   print_message(warning, ffi(skipped_header(Skipped)))
  833      )
  834    }.
  835
  836skip_unit(Stack) --> open_bracket(Close), !, skip_unit([Close|Stack]).
  837skip_unit(['}']) --> ['}'], !.
  838skip_unit([Close|Stack]) --> [Close], !, skip_unit(Stack).
  839skip_unit([]) --> [';'], !.
  840skip_unit(Stack) --> [_], skip_unit(Stack).
  841
  842here(List, List, List).
  843
  844diff(Start, End, Skipped) :- Start == End, !, Skipped = [].
  845diff([H|T0], End, [H|T]) :- diff(T0, End, T).
  846
  847open_bracket(')') --> ['('].
  848open_bracket(']') --> ['['].
  849open_bracket('}') --> ['{'].
  850
  851
  852		 /*******************************
  853		 *              STATE		*
  854		 *******************************/
  855
  856:- thread_local
  857    typedef/1,
  858    anon/2.  859
  860init_state :-
  861    retractall(typedef(_)),
  862    retractall(anon(_,_)).
  863
  864defined_type(Name) :-
  865    typedef(Name).
  866
  867update_types(decl(What, As, _GCC)) :-
  868    memberchk(storage(typedef), What), !,
  869    forall(( member(A, As),
  870             declarator_name(A, Name)
  871           ),
  872           assertz(typedef(Name))).
  873update_types(_).
  874
  875anon_id(Sort, Id) :-
  876    (   retract(anon(Sort, I0))
  877    ->  I is I0+1
  878    ;   I = 1
  879    ),
  880    asserta(anon(Sort, I)),
  881    atomic_list_concat(['_:', Sort, '_', I], Id).
  882
  883
  884		 /*******************************
  885		 *           EXAMINE AST	*
  886		 *******************************/
  887
  888declarator_name(declarator(_Ptr, dd(Name, _)), Name) :-
  889    atom(Name), !.
  890% typedef ssize_t (*Sread_function)(void *handle, char *buf, size_t bufsize);
  891declarator_name(declarator(_Ptr, dd(Declarator,_)), Name) :-
  892    declarator_name(Declarator, Name).
  893
  894
  895		 /*******************************
  896		 *            MESSAGES		*
  897		 *******************************/
  898
  899:- multifile
  900    prolog:message//1.  901
  902prolog:message(ffi(Msg)) -->
  903    message(Msg).
  904
  905message(skipped_header(Tokens)) -->
  906    [ 'FFI: Could not parse ~p'-[Tokens] ]