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