Bug 557786 - support fixed size arrays
[gnome.gobject-introspection] / giscanner / scannerparser.y
1 /* GObject introspection: C parser
2  *
3  * Copyright (c) 1997 Sandro Sigala  <ssigala@globalnet.it>
4  * Copyright (c) 2007-2008 Jürg Billeter  <j@bitron.ch>
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 %{
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <glib.h>
35 #include <glib/gstdio.h>
36 #include "sourcescanner.h"
37 #include "scannerparser.h"
38
39 extern FILE *yyin;
40 extern int lineno;
41 extern char *yytext;
42
43 extern int yylex (GISourceScanner *scanner);
44 static void yyerror (GISourceScanner *scanner, const char *str);
45  
46 extern void ctype_free (GISourceType * type);
47
48 static int last_enum_value = -1;
49 static GHashTable *const_table = NULL;
50 %}
51
52 %error-verbose
53 %union {
54   char *str;
55   GList *list;
56   GISourceSymbol *symbol;
57   GISourceType *ctype;
58   StorageClassSpecifier storage_class_specifier;
59   TypeQualifier type_qualifier;
60   FunctionSpecifier function_specifier;
61   UnaryOperator unary_operator;
62 }
63
64 %parse-param { GISourceScanner* scanner }
65 %lex-param { GISourceScanner* scanner }
66
67 %token <str> IDENTIFIER "identifier"
68 %token <str> TYPEDEF_NAME "typedef-name"
69
70 %token INTEGER FLOATING CHARACTER STRING
71
72 %token ELLIPSIS ADDEQ SUBEQ MULEQ DIVEQ MODEQ XOREQ ANDEQ OREQ SL SR
73 %token SLEQ SREQ EQ NOTEQ LTEQ GTEQ ANDAND OROR PLUSPLUS MINUSMINUS ARROW
74
75 %token AUTO BOOL BREAK CASE CHAR CONST CONTINUE DEFAULT DO DOUBLE ELSE ENUM
76 %token EXTENSION EXTERN FLOAT FOR GOTO IF INLINE INT LONG REGISTER RESTRICT
77 %token RETURN SHORT SIGNED SIZEOF STATIC STRUCT SWITCH TYPEDEF UNION UNSIGNED
78 %token VOID VOLATILE WHILE
79
80 %token FUNCTION_MACRO OBJECT_MACRO
81
82 %start translation_unit
83
84 %type <ctype> declaration_specifiers
85 %type <ctype> enum_specifier
86 %type <ctype> pointer
87 %type <ctype> specifier_qualifier_list
88 %type <ctype> type_name
89 %type <ctype> struct_or_union
90 %type <ctype> struct_or_union_specifier
91 %type <ctype> type_specifier
92 %type <str> identifier
93 %type <str> typedef_name
94 %type <str> identifier_or_typedef_name
95 %type <symbol> abstract_declarator
96 %type <symbol> init_declarator
97 %type <symbol> declarator
98 %type <symbol> enumerator
99 %type <symbol> direct_abstract_declarator
100 %type <symbol> direct_declarator
101 %type <symbol> parameter_declaration
102 %type <symbol> struct_declarator
103 %type <list> enumerator_list
104 %type <list> identifier_list
105 %type <list> init_declarator_list
106 %type <list> parameter_list
107 %type <list> struct_declaration
108 %type <list> struct_declaration_list
109 %type <list> struct_declarator_list
110 %type <storage_class_specifier> storage_class_specifier
111 %type <type_qualifier> type_qualifier
112 %type <type_qualifier> type_qualifier_list
113 %type <function_specifier> function_specifier
114 %type <symbol> expression
115 %type <symbol> constant_expression
116 %type <symbol> conditional_expression
117 %type <symbol> logical_and_expression
118 %type <symbol> logical_or_expression
119 %type <symbol> inclusive_or_expression
120 %type <symbol> exclusive_or_expression
121 %type <symbol> multiplicative_expression
122 %type <symbol> additive_expression
123 %type <symbol> shift_expression
124 %type <symbol> relational_expression
125 %type <symbol> equality_expression
126 %type <symbol> and_expression
127 %type <symbol> cast_expression
128 %type <symbol> assignment_expression
129 %type <symbol> unary_expression
130 %type <symbol> postfix_expression
131 %type <symbol> primary_expression
132 %type <unary_operator> unary_operator
133 %type <str> function_macro
134 %type <str> object_macro
135 %type <symbol> strings
136
137 %%
138
139 /* A.2.1 Expressions. */
140
141 primary_expression
142         : identifier
143           {
144                 $$ = g_hash_table_lookup (const_table, $1);
145                 if ($$ == NULL) {
146                         $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
147                 } else {
148                         $$ = gi_source_symbol_ref ($$);
149                 }
150           }
151         | INTEGER
152           {
153                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
154                 $$->const_int_set = TRUE;
155                 if (g_str_has_prefix (yytext, "0x") && strlen (yytext) > 2) {
156                         $$->const_int = strtol (yytext + 2, NULL, 16);
157                 } else if (g_str_has_prefix (yytext, "0") && strlen (yytext) > 1) {
158                         $$->const_int = strtol (yytext + 1, NULL, 8);
159                 } else {
160                         $$->const_int = atoi (yytext);
161                 }
162           }
163         | CHARACTER
164           {
165                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
166           }
167         | FLOATING
168           {
169                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
170           }
171         | strings
172         | '(' expression ')'
173           {
174                 $$ = $2;
175           }
176         ;
177
178 /* concatenate adjacent string literal tokens */
179 strings
180         : STRING
181           {
182                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
183                 yytext[strlen (yytext) - 1] = '\0';
184                 $$->const_string = g_strcompress (yytext + 1);
185                 if (!g_utf8_validate ($$->const_string, -1, NULL))
186                   {
187                     g_warning ("Ignoring non-UTF-8 constant string %s", $$->ident);
188                     g_free($$->const_string);
189                     $$->const_string = NULL;
190                   }
191
192           }
193         | strings STRING
194           {
195                 char *strings, *string2;
196                 $$ = $1;
197                 yytext[strlen (yytext) - 1] = '\0';
198                 string2 = g_strcompress (yytext + 1);
199                 strings = g_strconcat ($$->const_string, string2, NULL);
200                 g_free ($$->const_string);
201                 g_free (string2);
202                 $$->const_string = strings;
203           }
204         ;
205
206 identifier
207         : IDENTIFIER
208           {
209                 $$ = g_strdup (yytext);
210           }
211         ;
212
213 identifier_or_typedef_name
214         : identifier
215         | typedef_name
216         ;
217
218 postfix_expression
219         : primary_expression
220         | postfix_expression '[' expression ']'
221           {
222                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
223           }
224         | postfix_expression '(' argument_expression_list ')'
225           {
226                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
227           }
228         | postfix_expression '(' ')'
229           {
230                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
231           }
232         | postfix_expression '.' identifier_or_typedef_name
233           {
234                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
235           }
236         | postfix_expression ARROW identifier_or_typedef_name
237           {
238                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
239           }
240         | postfix_expression PLUSPLUS
241           {
242                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
243           }
244         | postfix_expression MINUSMINUS
245           {
246                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
247           }
248         ;
249
250 argument_expression_list
251         : assignment_expression
252         | argument_expression_list ',' assignment_expression
253         ;
254
255 unary_expression
256         : postfix_expression
257         | PLUSPLUS unary_expression
258           {
259                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
260           }
261         | MINUSMINUS unary_expression
262           {
263                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
264           }
265         | unary_operator cast_expression
266           {
267                 switch ($1) {
268                 case UNARY_PLUS:
269                         $$ = $2;
270                         break;
271                 case UNARY_MINUS:
272                         $$ = $2;
273                         $$->const_int = -$2->const_int;
274                         break;
275                 case UNARY_BITWISE_COMPLEMENT:
276                         $$ = $2;
277                         $$->const_int = ~$2->const_int;
278                         break;
279                 case UNARY_LOGICAL_NEGATION:
280                         $$ = $2;
281                         $$->const_int = !gi_source_symbol_get_const_boolean ($2);
282                         break;
283                 default:
284                         $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
285                         break;
286                 }
287           }
288         | SIZEOF unary_expression
289           {
290                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
291           }
292         | SIZEOF '(' type_name ')'
293           {
294                 ctype_free ($3);
295                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
296           }
297         ;
298
299 unary_operator
300         : '&'
301           {
302                 $$ = UNARY_ADDRESS_OF;
303           }
304         | '*'
305           {
306                 $$ = UNARY_POINTER_INDIRECTION;
307           }
308         | '+'
309           {
310                 $$ = UNARY_PLUS;
311           }
312         | '-'
313           {
314                 $$ = UNARY_MINUS;
315           }
316         | '~'
317           {
318                 $$ = UNARY_BITWISE_COMPLEMENT;
319           }
320         | '!'
321           {
322                 $$ = UNARY_LOGICAL_NEGATION;
323           }
324         ;
325
326 cast_expression
327         : unary_expression
328         | '(' type_name ')' cast_expression
329           {
330                 ctype_free ($2);
331                 $$ = $4;
332           }
333         ;
334
335 multiplicative_expression
336         : cast_expression
337         | multiplicative_expression '*' cast_expression
338           {
339                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
340                 $$->const_int_set = TRUE;
341                 $$->const_int = $1->const_int * $3->const_int;
342           }
343         | multiplicative_expression '/' cast_expression
344           {
345                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
346                 $$->const_int_set = TRUE;
347                 if ($3->const_int != 0) {
348                         $$->const_int = $1->const_int / $3->const_int;
349                 }
350           }
351         | multiplicative_expression '%' cast_expression
352           {
353                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
354                 $$->const_int_set = TRUE;
355                 if ($3->const_int != 0) {
356                         $$->const_int = $1->const_int % $3->const_int;
357                 }
358           }
359         ;
360
361 additive_expression
362         : multiplicative_expression
363         | additive_expression '+' multiplicative_expression
364           {
365                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
366                 $$->const_int_set = TRUE;
367                 $$->const_int = $1->const_int + $3->const_int;
368           }
369         | additive_expression '-' multiplicative_expression
370           {
371                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
372                 $$->const_int_set = TRUE;
373                 $$->const_int = $1->const_int - $3->const_int;
374           }
375         ;
376
377 shift_expression
378         : additive_expression
379         | shift_expression SL additive_expression
380           {
381                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
382                 $$->const_int_set = TRUE;
383                 $$->const_int = $1->const_int << $3->const_int;
384           }
385         | shift_expression SR additive_expression
386           {
387                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
388                 $$->const_int_set = TRUE;
389                 $$->const_int = $1->const_int >> $3->const_int;
390           }
391         ;
392
393 relational_expression
394         : shift_expression
395         | relational_expression '<' shift_expression
396           {
397                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
398                 $$->const_int_set = TRUE;
399                 $$->const_int = $1->const_int < $3->const_int;
400           }
401         | relational_expression '>' shift_expression
402           {
403                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
404                 $$->const_int_set = TRUE;
405                 $$->const_int = $1->const_int > $3->const_int;
406           }
407         | relational_expression LTEQ shift_expression
408           {
409                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
410                 $$->const_int_set = TRUE;
411                 $$->const_int = $1->const_int <= $3->const_int;
412           }
413         | relational_expression GTEQ shift_expression
414           {
415                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
416                 $$->const_int_set = TRUE;
417                 $$->const_int = $1->const_int >= $3->const_int;
418           }
419         ;
420
421 equality_expression
422         : relational_expression
423         | equality_expression EQ relational_expression
424           {
425                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
426                 $$->const_int_set = TRUE;
427                 $$->const_int = $1->const_int == $3->const_int;
428           }
429         | equality_expression NOTEQ relational_expression
430           {
431                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
432                 $$->const_int_set = TRUE;
433                 $$->const_int = $1->const_int != $3->const_int;
434           }
435         ;
436
437 and_expression
438         : equality_expression
439         | and_expression '&' equality_expression
440           {
441                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
442                 $$->const_int_set = TRUE;
443                 $$->const_int = $1->const_int & $3->const_int;
444           }
445         ;
446
447 exclusive_or_expression
448         : and_expression
449         | exclusive_or_expression '^' and_expression
450           {
451                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
452                 $$->const_int_set = TRUE;
453                 $$->const_int = $1->const_int ^ $3->const_int;
454           }
455         ;
456
457 inclusive_or_expression
458         : exclusive_or_expression
459         | inclusive_or_expression '|' exclusive_or_expression
460           {
461                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
462                 $$->const_int_set = TRUE;
463                 $$->const_int = $1->const_int | $3->const_int;
464           }
465         ;
466
467 logical_and_expression
468         : inclusive_or_expression
469         | logical_and_expression ANDAND inclusive_or_expression
470           {
471                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
472                 $$->const_int_set = TRUE;
473                 $$->const_int =
474                   gi_source_symbol_get_const_boolean ($1) &&
475                   gi_source_symbol_get_const_boolean ($3);
476           }
477         ;
478
479 logical_or_expression
480         : logical_and_expression
481         | logical_or_expression OROR logical_and_expression
482           {
483                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
484                 $$->const_int_set = TRUE;
485                 $$->const_int =
486                   gi_source_symbol_get_const_boolean ($1) ||
487                   gi_source_symbol_get_const_boolean ($3);
488           }
489         ;
490
491 conditional_expression
492         : logical_or_expression
493         | logical_or_expression '?' expression ':' conditional_expression
494           {
495                 $$ = gi_source_symbol_get_const_boolean ($1) ? $3 : $5;
496           }
497         ;
498
499 assignment_expression
500         : conditional_expression
501         | unary_expression assignment_operator assignment_expression
502           {
503                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
504           }
505         ;
506
507 assignment_operator
508         : '='
509         | MULEQ
510         | DIVEQ
511         | MODEQ
512         | ADDEQ
513         | SUBEQ
514         | SLEQ
515         | SREQ
516         | ANDEQ
517         | XOREQ
518         | OREQ
519         ;
520
521 expression
522         : assignment_expression
523         | expression ',' assignment_expression
524           {
525                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
526           }
527         ;
528
529 constant_expression
530         : conditional_expression
531         ;
532
533 /* A.2.2 Declarations. */
534
535 declaration
536         : declaration_specifiers init_declarator_list ';'
537           {
538                 GList *l;
539                 for (l = $2; l != NULL; l = l->next) {
540                         GISourceSymbol *sym = l->data;
541                         gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
542                         if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF) {
543                                 sym->type = CSYMBOL_TYPE_TYPEDEF;
544                         } else if (sym->base_type->type == CTYPE_FUNCTION) {
545                                 sym->type = CSYMBOL_TYPE_FUNCTION;
546                         } else {
547                                 sym->type = CSYMBOL_TYPE_OBJECT;
548                         }
549                         gi_source_scanner_add_symbol (scanner, sym);
550                         gi_source_symbol_unref (sym);
551                 }
552                 ctype_free ($1);
553           }
554         | declaration_specifiers ';'
555           {
556                 ctype_free ($1);
557           }
558         ;
559
560 declaration_specifiers
561         : storage_class_specifier declaration_specifiers
562           {
563                 $$ = $2;
564                 $$->storage_class_specifier |= $1;
565           }
566         | storage_class_specifier
567           {
568                 $$ = gi_source_type_new (CTYPE_INVALID);
569                 $$->storage_class_specifier |= $1;
570           }
571         | type_specifier declaration_specifiers
572           {
573                 $$ = $1;
574                 /* combine basic types like unsigned int and long long */
575                 if ($$->type == CTYPE_BASIC_TYPE && $2->type == CTYPE_BASIC_TYPE) {
576                         char *name = g_strdup_printf ("%s %s", $$->name, $2->name);
577                         g_free ($$->name);
578                         $$->name = name;
579                         ctype_free ($2);
580                 } else {
581                         $$->base_type = $2;
582                 }
583           }
584         | type_specifier
585         | type_qualifier declaration_specifiers
586           {
587                 $$ = $2;
588                 $$->type_qualifier |= $1;
589           }
590         | type_qualifier
591           {
592                 $$ = gi_source_type_new (CTYPE_INVALID);
593                 $$->type_qualifier |= $1;
594           }
595         | function_specifier declaration_specifiers
596           {
597                 $$ = $2;
598                 $$->function_specifier |= $1;
599           }
600         | function_specifier
601           {
602                 $$ = gi_source_type_new (CTYPE_INVALID);
603                 $$->function_specifier |= $1;
604           }
605         ;
606
607 init_declarator_list
608         : init_declarator
609           {
610                 $$ = g_list_append (NULL, $1);
611           }
612         | init_declarator_list ',' init_declarator
613           {
614                 $$ = g_list_append ($1, $3);
615           }
616         ;
617
618 init_declarator
619         : declarator
620         | declarator '=' initializer
621         ;
622
623 storage_class_specifier
624         : TYPEDEF
625           {
626                 $$ = STORAGE_CLASS_TYPEDEF;
627           }
628         | EXTERN
629           {
630                 $$ = STORAGE_CLASS_EXTERN;
631           }
632         | STATIC
633           {
634                 $$ = STORAGE_CLASS_STATIC;
635           }
636         | AUTO
637           {
638                 $$ = STORAGE_CLASS_AUTO;
639           }
640         | REGISTER
641           {
642                 $$ = STORAGE_CLASS_REGISTER;
643           }
644         ;
645
646 type_specifier
647         : VOID
648           {
649                 $$ = gi_source_type_new (CTYPE_VOID);
650           }
651         | CHAR
652           {
653                 $$ = gi_source_basic_type_new ("char");
654           }
655         | SHORT
656           {
657                 $$ = gi_source_basic_type_new ("short");
658           }
659         | INT
660           {
661                 $$ = gi_source_basic_type_new ("int");
662           }
663         | LONG
664           {
665                 $$ = gi_source_basic_type_new ("long");
666           }
667         | FLOAT
668           {
669                 $$ = gi_source_basic_type_new ("float");
670           }
671         | DOUBLE
672           {
673                 $$ = gi_source_basic_type_new ("double");
674           }
675         | SIGNED
676           {
677                 $$ = gi_source_basic_type_new ("signed");
678           }
679         | UNSIGNED
680           {
681                 $$ = gi_source_basic_type_new ("unsigned");
682           }
683         | BOOL
684           {
685                 $$ = gi_source_basic_type_new ("bool");
686           }
687         | struct_or_union_specifier
688         | enum_specifier
689         | typedef_name
690           {
691                 $$ = gi_source_typedef_new ($1);
692                 g_free ($1);
693           }
694         ;
695
696 struct_or_union_specifier
697         : struct_or_union identifier_or_typedef_name '{' struct_declaration_list '}'
698           {
699                 $$ = $1;
700                 $$->name = $2;
701                 $$->child_list = $4;
702
703                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
704                 if ($$->type == CTYPE_STRUCT) {
705                         sym->type = CSYMBOL_TYPE_STRUCT;
706                 } else if ($$->type == CTYPE_UNION) {
707                         sym->type = CSYMBOL_TYPE_UNION;
708                 } else {
709                         g_assert_not_reached ();
710                 }
711                 sym->ident = g_strdup ($$->name);
712                 sym->base_type = gi_source_type_copy ($$);
713                 gi_source_scanner_add_symbol (scanner, sym);
714                 gi_source_symbol_unref (sym);
715           }
716         | struct_or_union '{' struct_declaration_list '}'
717           {
718                 $$ = $1;
719                 $$->child_list = $3;
720           }
721         | struct_or_union identifier_or_typedef_name
722           {
723                 $$ = $1;
724                 $$->name = $2;
725           }
726         ;
727
728 struct_or_union
729         : STRUCT
730           {
731                 $$ = gi_source_struct_new (NULL);
732           }
733         | UNION
734           {
735                 $$ = gi_source_union_new (NULL);
736           }
737         ;
738
739 struct_declaration_list
740         : struct_declaration
741         | struct_declaration_list struct_declaration
742           {
743                 $$ = g_list_concat ($1, $2);
744           }
745         ;
746
747 struct_declaration
748         : specifier_qualifier_list struct_declarator_list ';'
749           {
750             GList *l;
751             $$ = NULL;
752             for (l = $2; l != NULL; l = l->next)
753               {
754                 GISourceSymbol *sym = l->data;
755                 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF)
756                     sym->type = CSYMBOL_TYPE_TYPEDEF;
757                 else
758                     sym->type = CSYMBOL_TYPE_MEMBER;
759                 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
760                 $$ = g_list_append ($$, sym);
761               }
762             ctype_free ($1);
763           }
764         ;
765
766 specifier_qualifier_list
767         : type_specifier specifier_qualifier_list
768           {
769                 $$ = $1;
770                 $$->base_type = $2;
771           }
772         | type_specifier
773         | type_qualifier specifier_qualifier_list
774           {
775                 $$ = $2;
776                 $$->type_qualifier |= $1;
777           }
778         | type_qualifier
779           {
780                 $$ = gi_source_type_new (CTYPE_INVALID);
781                 $$->type_qualifier |= $1;
782           }
783         ;
784
785 struct_declarator_list
786         : struct_declarator
787           {
788                 $$ = g_list_append (NULL, $1);
789           }
790         | struct_declarator_list ',' struct_declarator
791           {
792                 $$ = g_list_append ($1, $3);
793           }
794         ;
795
796 struct_declarator
797         : /* empty, support for anonymous structs and unions */
798           {
799                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
800           }
801         | declarator
802         | ':' constant_expression
803           {
804                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
805           }
806         | declarator ':' constant_expression
807           {
808                 $$ = $1;
809                 if ($3->const_int_set) {
810                   $$->const_int_set = TRUE;
811                   $$->const_int = $3->const_int;
812                 }
813           }
814         ;
815
816 enum_specifier
817         : ENUM identifier_or_typedef_name '{' enumerator_list '}'
818           {
819                 $$ = gi_source_enum_new ($2);
820                 $$->child_list = $4;
821                 last_enum_value = -1;
822           }
823         | ENUM '{' enumerator_list '}'
824           {
825                 $$ = gi_source_enum_new (NULL);
826                 $$->child_list = $3;
827                 last_enum_value = -1;
828           }
829         | ENUM identifier_or_typedef_name '{' enumerator_list ',' '}'
830           {
831                 $$ = gi_source_enum_new ($2);
832                 $$->child_list = $4;
833                 last_enum_value = -1;
834           }
835         | ENUM '{' enumerator_list ',' '}'
836           {
837                 $$ = gi_source_enum_new (NULL);
838                 $$->child_list = $3;
839                 last_enum_value = -1;
840           }
841         | ENUM identifier_or_typedef_name
842           {
843                 $$ = gi_source_enum_new ($2);
844           }
845         ;
846
847 enumerator_list
848         : enumerator
849           {
850                 $$ = g_list_append (NULL, $1);
851           }
852         | enumerator_list ',' enumerator
853           {
854                 $$ = g_list_append ($1, $3);
855           }
856         ;
857
858 enumerator
859         : identifier
860           {
861                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
862                 $$->ident = $1;
863                 $$->const_int_set = TRUE;
864                 $$->const_int = ++last_enum_value;
865                 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
866           }
867         | identifier '=' constant_expression
868           {
869                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
870                 $$->ident = $1;
871                 $$->const_int_set = TRUE;
872                 $$->const_int = $3->const_int;
873                 last_enum_value = $$->const_int;
874                 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
875           }
876         ;
877
878 type_qualifier
879         : CONST
880           {
881                 $$ = TYPE_QUALIFIER_CONST;
882           }
883         | RESTRICT
884           {
885                 $$ = TYPE_QUALIFIER_RESTRICT;
886           }
887         | EXTENSION
888           {
889                 $$ = TYPE_QUALIFIER_EXTENSION;
890           }
891         | VOLATILE
892           {
893                 $$ = TYPE_QUALIFIER_VOLATILE;
894           }
895         ;
896
897 function_specifier
898         : INLINE
899           {
900                 $$ = FUNCTION_INLINE;
901           }
902         ;
903
904 declarator
905         : pointer direct_declarator
906           {
907                 $$ = $2;
908                 gi_source_symbol_merge_type ($$, $1);
909           }
910         | direct_declarator
911         ;
912
913 direct_declarator
914         : identifier
915           {
916                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
917                 $$->ident = $1;
918           }
919         | '(' declarator ')'
920           {
921                 $$ = $2;
922           }
923         | direct_declarator '[' assignment_expression ']'
924           {
925                 $$ = $1;
926                 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
927           }
928         | direct_declarator '[' ']'
929           {
930                 $$ = $1;
931                 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
932           }
933         | direct_declarator '(' parameter_list ')'
934           {
935                 GISourceType *func = gi_source_function_new ();
936                 // ignore (void) parameter list
937                 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
938                         func->child_list = $3;
939                 }
940                 $$ = $1;
941                 gi_source_symbol_merge_type ($$, func);
942           }
943         | direct_declarator '(' identifier_list ')'
944           {
945                 GISourceType *func = gi_source_function_new ();
946                 func->child_list = $3;
947                 $$ = $1;
948                 gi_source_symbol_merge_type ($$, func);
949           }
950         | direct_declarator '(' ')'
951           {
952                 GISourceType *func = gi_source_function_new ();
953                 $$ = $1;
954                 gi_source_symbol_merge_type ($$, func);
955           }
956         ;
957
958 pointer
959         : '*' type_qualifier_list
960           {
961                 $$ = gi_source_pointer_new (NULL);
962                 $$->type_qualifier = $2;
963           }
964         | '*'
965           {
966                 $$ = gi_source_pointer_new (NULL);
967           }
968         | '*' type_qualifier_list pointer
969           {
970                 $$ = gi_source_pointer_new ($3);
971                 $$->type_qualifier = $2;
972           }
973         | '*' pointer
974           {
975                 $$ = gi_source_pointer_new ($2);
976           }
977         ;
978
979 type_qualifier_list
980         : type_qualifier
981         | type_qualifier_list type_qualifier
982           {
983                 $$ = $1 | $2;
984           }
985         ;
986
987 parameter_list
988         : parameter_declaration
989           {
990                 $$ = g_list_append (NULL, $1);
991           }
992         | parameter_list ',' parameter_declaration
993           {
994                 $$ = g_list_append ($1, $3);
995           }
996         ;
997
998 parameter_declaration
999         : declaration_specifiers declarator
1000           {
1001                 $$ = $2;
1002                 gi_source_symbol_merge_type ($$, $1);
1003           }
1004         | declaration_specifiers abstract_declarator
1005           {
1006                 $$ = $2;
1007                 gi_source_symbol_merge_type ($$, $1);
1008           }
1009         | declaration_specifiers
1010           {
1011                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1012                 $$->base_type = $1;
1013           }
1014         | ELLIPSIS
1015           {
1016                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_ELLIPSIS);
1017           }
1018         ;
1019
1020 identifier_list
1021         : identifier
1022           {
1023                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1024                 sym->ident = $1;
1025                 $$ = g_list_append (NULL, sym);
1026           }
1027         | identifier_list ',' identifier
1028           {
1029                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1030                 sym->ident = $3;
1031                 $$ = g_list_append ($1, sym);
1032           }
1033         ;
1034
1035 type_name
1036         : specifier_qualifier_list
1037         | specifier_qualifier_list abstract_declarator
1038         ;
1039
1040 abstract_declarator
1041         : pointer
1042           {
1043                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1044                 gi_source_symbol_merge_type ($$, $1);
1045           }
1046         | direct_abstract_declarator
1047         | pointer direct_abstract_declarator
1048           {
1049                 $$ = $2;
1050                 gi_source_symbol_merge_type ($$, $1);
1051           }
1052         ;
1053
1054 direct_abstract_declarator
1055         : '(' abstract_declarator ')'
1056           {
1057                 $$ = $2;
1058           }
1059         | '[' ']'
1060           {
1061                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1062                 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1063           }
1064         | '[' assignment_expression ']'
1065           {
1066                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1067                 gi_source_symbol_merge_type ($$, gi_source_array_new ($2));
1068           }
1069         | direct_abstract_declarator '[' ']'
1070           {
1071                 $$ = $1;
1072                 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1073           }
1074         | direct_abstract_declarator '[' assignment_expression ']'
1075           {
1076                 $$ = $1;
1077                 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
1078           }
1079         | '(' ')'
1080           {
1081                 GISourceType *func = gi_source_function_new ();
1082                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1083                 gi_source_symbol_merge_type ($$, func);
1084           }
1085         | '(' parameter_list ')'
1086           {
1087                 GISourceType *func = gi_source_function_new ();
1088                 // ignore (void) parameter list
1089                 if ($2 != NULL && ($2->next != NULL || ((GISourceSymbol *) $2->data)->base_type->type != CTYPE_VOID)) {
1090                         func->child_list = $2;
1091                 }
1092                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1093                 gi_source_symbol_merge_type ($$, func);
1094           }
1095         | direct_abstract_declarator '(' ')'
1096           {
1097                 GISourceType *func = gi_source_function_new ();
1098                 $$ = $1;
1099                 gi_source_symbol_merge_type ($$, func);
1100           }
1101         | direct_abstract_declarator '(' parameter_list ')'
1102           {
1103                 GISourceType *func = gi_source_function_new ();
1104                 // ignore (void) parameter list
1105                 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1106                         func->child_list = $3;
1107                 }
1108                 $$ = $1;
1109                 gi_source_symbol_merge_type ($$, func);
1110           }
1111         ;
1112
1113 typedef_name
1114         : TYPEDEF_NAME
1115           {
1116                 $$ = g_strdup (yytext);
1117           }
1118         ;
1119
1120 initializer
1121         : assignment_expression
1122         | '{' initializer_list '}'
1123         | '{' initializer_list ',' '}'
1124         ;
1125
1126 initializer_list
1127         : initializer
1128         | initializer_list ',' initializer
1129         ;
1130
1131 /* A.2.3 Statements. */
1132
1133 statement
1134         : labeled_statement
1135         | compound_statement
1136         | expression_statement
1137         | selection_statement
1138         | iteration_statement
1139         | jump_statement
1140         ;
1141
1142 labeled_statement
1143         : identifier_or_typedef_name ':' statement
1144         | CASE constant_expression ':' statement
1145         | DEFAULT ':' statement
1146         ;
1147
1148 compound_statement
1149         : '{' '}'
1150         | '{' block_item_list '}'
1151         ;
1152
1153 block_item_list
1154         : block_item
1155         | block_item_list block_item
1156         ;
1157
1158 block_item
1159         : declaration
1160         | statement
1161         ;
1162
1163 expression_statement
1164         : ';'
1165         | expression ';'
1166         ;
1167
1168 selection_statement
1169         : IF '(' expression ')' statement
1170         | IF '(' expression ')' statement ELSE statement
1171         | SWITCH '(' expression ')' statement
1172         ;
1173
1174 iteration_statement
1175         : WHILE '(' expression ')' statement
1176         | DO statement WHILE '(' expression ')' ';'
1177         | FOR '(' ';' ';' ')' statement
1178         | FOR '(' expression ';' ';' ')' statement
1179         | FOR '(' ';' expression ';' ')' statement
1180         | FOR '(' expression ';' expression ';' ')' statement
1181         | FOR '(' ';' ';' expression ')' statement
1182         | FOR '(' expression ';' ';' expression ')' statement
1183         | FOR '(' ';' expression ';' expression ')' statement
1184         | FOR '(' expression ';' expression ';' expression ')' statement
1185         ;
1186
1187 jump_statement
1188         : GOTO identifier_or_typedef_name ';'
1189         | CONTINUE ';'
1190         | BREAK ';'
1191         | RETURN ';'
1192         | RETURN expression ';'
1193         ;
1194
1195 /* A.2.4 External definitions. */
1196
1197 translation_unit
1198         : external_declaration
1199         | translation_unit external_declaration
1200         ;
1201
1202 external_declaration
1203         : function_definition
1204         | declaration
1205         | macro
1206         ;
1207
1208 function_definition
1209         : declaration_specifiers declarator declaration_list compound_statement
1210         | declaration_specifiers declarator compound_statement
1211         ;
1212
1213 declaration_list
1214         : declaration
1215         | declaration_list declaration
1216         ;
1217
1218 /* Macros */
1219
1220 function_macro
1221         : FUNCTION_MACRO
1222           {
1223                 $$ = g_strdup (yytext + strlen ("#define "));
1224           }
1225         ;
1226
1227 object_macro
1228         : OBJECT_MACRO
1229           {
1230                 $$ = g_strdup (yytext + strlen ("#define "));
1231           }
1232         ;
1233
1234 function_macro_define
1235         : function_macro '(' identifier_list ')'
1236         ;
1237
1238 object_macro_define
1239         : object_macro constant_expression
1240           {
1241                 if ($2->const_int_set || $2->const_string != NULL) {
1242                         $2->ident = $1;
1243                         gi_source_scanner_add_symbol (scanner, $2);
1244                         gi_source_symbol_unref ($2);
1245                 }
1246           }
1247         ;
1248
1249 macro
1250         : function_macro_define
1251         | object_macro_define
1252         | error
1253         ;
1254
1255 %%
1256 static void
1257 yyerror (GISourceScanner *scanner, const char *s)
1258 {
1259   /* ignore errors while doing a macro scan as not all object macros
1260    * have valid expressions */
1261   if (!scanner->macro_scan)
1262     {
1263       fprintf(stderr, "%s:%d: %s\n",
1264               scanner->current_filename, lineno, s);
1265     }
1266 }
1267
1268 static int
1269 eat_hspace (FILE * f)
1270 {
1271   int c;
1272   do
1273     {
1274       c = fgetc (f);
1275     }
1276   while (c == ' ' || c == '\t');
1277   return c;
1278 }
1279
1280 static int
1281 eat_line (FILE * f, int c)
1282 {
1283   while (c != EOF && c != '\n')
1284     {
1285       c = fgetc (f);
1286     }
1287   if (c == '\n')
1288     {
1289       c = fgetc (f);
1290       if (c == ' ' || c == '\t')
1291         {
1292           c = eat_hspace (f);
1293         }
1294     }
1295   return c;
1296 }
1297
1298 static int
1299 read_identifier (FILE * f, int c, char **identifier)
1300 {
1301   GString *id = g_string_new ("");
1302   while (g_ascii_isalnum (c) || c == '_')
1303     {
1304       g_string_append_c (id, c);
1305       c = fgetc (f);
1306     }
1307   *identifier = g_string_free (id, FALSE);
1308   return c;
1309 }
1310
1311 void
1312 gi_source_scanner_parse_macros (GISourceScanner *scanner, GList *filenames)
1313 {
1314   GError *error = NULL;
1315   char *tmp_name = NULL;
1316   FILE *fmacros =
1317     fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error),
1318             "w+");
1319   g_unlink (tmp_name);
1320
1321   GList *l;
1322   for (l = filenames; l != NULL; l = l->next)
1323     {
1324       FILE *f = fopen (l->data, "r");
1325       int line = 1;
1326
1327       GString *define_line;
1328       char *str;
1329       gboolean error_line = FALSE;
1330       int c = eat_hspace (f);
1331       while (c != EOF)
1332         {
1333           if (c != '#')
1334             {
1335               /* ignore line */
1336               c = eat_line (f, c);
1337               line++;
1338               continue;
1339             }
1340
1341           /* print current location */
1342           str = g_strescape (l->data, "");
1343           fprintf (fmacros, "# %d \"%s\"\n", line, str);
1344           g_free (str);
1345
1346           c = eat_hspace (f);
1347           c = read_identifier (f, c, &str);
1348           if (strcmp (str, "define") != 0 || (c != ' ' && c != '\t'))
1349             {
1350               g_free (str);
1351               /* ignore line */
1352               c = eat_line (f, c);
1353               line++;
1354               continue;
1355             }
1356           g_free (str);
1357           c = eat_hspace (f);
1358           c = read_identifier (f, c, &str);
1359           if (strlen (str) == 0 || (c != ' ' && c != '\t' && c != '('))
1360             {
1361               g_free (str);
1362               /* ignore line */
1363               c = eat_line (f, c);
1364               line++;
1365               continue;
1366             }
1367           define_line = g_string_new ("#define ");
1368           g_string_append (define_line, str);
1369           g_free (str);
1370           if (c == '(')
1371             {
1372               while (c != ')')
1373                 {
1374                   g_string_append_c (define_line, c);
1375                   c = fgetc (f);
1376                   if (c == EOF || c == '\n')
1377                     {
1378                       error_line = TRUE;
1379                       break;
1380                     }
1381                 }
1382               if (error_line)
1383                 {
1384                   g_string_free (define_line, TRUE);
1385                   /* ignore line */
1386                   c = eat_line (f, c);
1387                   line++;
1388                   continue;
1389                 }
1390
1391               g_assert (c == ')');
1392               g_string_append_c (define_line, c);
1393               c = fgetc (f);
1394
1395               /* found function-like macro */
1396               fprintf (fmacros, "%s\n", define_line->str);
1397
1398               g_string_free (define_line, TRUE);
1399               /* ignore rest of line */
1400               c = eat_line (f, c);
1401               line++;
1402               continue;
1403             }
1404           if (c != ' ' && c != '\t')
1405             {
1406               g_string_free (define_line, TRUE);
1407               /* ignore line */
1408               c = eat_line (f, c);
1409               line++;
1410               continue;
1411             }
1412           while (c != EOF && c != '\n')
1413             {
1414               g_string_append_c (define_line, c);
1415               c = fgetc (f);
1416               if (c == '\\')
1417                 {
1418                   c = fgetc (f);
1419                   if (c == '\n')
1420                     {
1421                       /* fold lines when seeing backslash new-line sequence */
1422                       c = fgetc (f);
1423                     }
1424                   else
1425                     {
1426                       g_string_append_c (define_line, '\\');
1427                     }
1428                 }
1429             }
1430
1431           /* found object-like macro */
1432           fprintf (fmacros, "%s\n", define_line->str);
1433
1434           c = eat_line (f, c);
1435           line++;
1436         }
1437
1438       fclose (f);
1439     }
1440
1441   rewind (fmacros);
1442   gi_source_scanner_parse_file (scanner, fmacros);
1443 }
1444
1445 gboolean
1446 gi_source_scanner_parse_file (GISourceScanner *scanner, FILE *file)
1447 {
1448   g_return_val_if_fail (file != NULL, FALSE);
1449   
1450   const_table = g_hash_table_new_full (g_str_hash, g_str_equal,
1451                                        g_free, (GDestroyNotify)gi_source_symbol_unref);
1452   
1453   lineno = 1;
1454   yyin = file;
1455   yyparse (scanner);
1456   
1457   g_hash_table_destroy (const_table);
1458   const_table = NULL;
1459   
1460   yyin = NULL;
1461
1462   return TRUE;
1463 }
1464
1465 gboolean
1466 gi_source_scanner_lex_filename (GISourceScanner *scanner, const gchar *filename)
1467 {
1468   yyin = fopen (filename, "r");
1469
1470   while (yylex (scanner) != YYEOF)
1471     ;
1472
1473   fclose (yyin);
1474   
1475   return TRUE;
1476 }