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