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