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