1 /* GObject introspection: C parser
3 * Copyright (c) 1997 Sandro Sigala <ssigala@globalnet.it>
4 * Copyright (c) 2007-2008 Jürg Billeter <j@bitron.ch>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
35 #include <glib/gstdio.h>
36 #include "sourcescanner.h"
37 #include "scannerparser.h"
43 extern int yylex (GISourceScanner *scanner);
44 static void yyerror (GISourceScanner *scanner, const char *str);
46 extern void ctype_free (GISourceType * type);
48 static int last_enum_value = -1;
49 static GHashTable *const_table = NULL;
56 GISourceSymbol *symbol;
58 StorageClassSpecifier storage_class_specifier;
59 TypeQualifier type_qualifier;
60 FunctionSpecifier function_specifier;
61 UnaryOperator unary_operator;
64 %parse-param { GISourceScanner* scanner }
65 %lex-param { GISourceScanner* scanner }
67 %token <str> IDENTIFIER "identifier"
68 %token <str> TYPEDEF_NAME "typedef-name"
70 %token INTEGER FLOATING CHARACTER STRING
72 %token ELLIPSIS ADDEQ SUBEQ MULEQ DIVEQ MODEQ XOREQ ANDEQ OREQ SL SR
73 %token SLEQ SREQ EQ NOTEQ LTEQ GTEQ ANDAND OROR PLUSPLUS MINUSMINUS ARROW
75 %token AUTO BOOL BREAK CASE CHAR CONST CONTINUE DEFAULT DO DOUBLE ELSE ENUM
76 %token EXTENSION EXTERN FLOAT FOR GOTO IF INLINE INT LONG REGISTER RESTRICT
77 %token RETURN SHORT SIGNED SIZEOF STATIC STRUCT SWITCH TYPEDEF UNION UNSIGNED
78 %token VOID VOLATILE WHILE
80 %token FUNCTION_MACRO OBJECT_MACRO
82 %start translation_unit
84 %type <ctype> declaration_specifiers
85 %type <ctype> enum_specifier
87 %type <ctype> specifier_qualifier_list
88 %type <ctype> type_name
89 %type <ctype> struct_or_union
90 %type <ctype> struct_or_union_specifier
91 %type <ctype> type_specifier
92 %type <str> identifier
93 %type <str> typedef_name
94 %type <str> identifier_or_typedef_name
95 %type <symbol> abstract_declarator
96 %type <symbol> init_declarator
97 %type <symbol> declarator
98 %type <symbol> enumerator
99 %type <symbol> direct_abstract_declarator
100 %type <symbol> direct_declarator
101 %type <symbol> parameter_declaration
102 %type <symbol> struct_declarator
103 %type <list> enumerator_list
104 %type <list> identifier_list
105 %type <list> init_declarator_list
106 %type <list> parameter_list
107 %type <list> struct_declaration
108 %type <list> struct_declaration_list
109 %type <list> struct_declarator_list
110 %type <storage_class_specifier> storage_class_specifier
111 %type <type_qualifier> type_qualifier
112 %type <type_qualifier> type_qualifier_list
113 %type <function_specifier> function_specifier
114 %type <symbol> expression
115 %type <symbol> constant_expression
116 %type <symbol> conditional_expression
117 %type <symbol> logical_and_expression
118 %type <symbol> logical_or_expression
119 %type <symbol> inclusive_or_expression
120 %type <symbol> exclusive_or_expression
121 %type <symbol> multiplicative_expression
122 %type <symbol> additive_expression
123 %type <symbol> shift_expression
124 %type <symbol> relational_expression
125 %type <symbol> equality_expression
126 %type <symbol> and_expression
127 %type <symbol> cast_expression
128 %type <symbol> assignment_expression
129 %type <symbol> unary_expression
130 %type <symbol> postfix_expression
131 %type <symbol> primary_expression
132 %type <unary_operator> unary_operator
133 %type <str> function_macro
134 %type <str> object_macro
135 %type <symbol> strings
139 /* A.2.1 Expressions. */
144 $$ = g_hash_table_lookup (const_table, $1);
146 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
148 $$ = gi_source_symbol_ref ($$);
153 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
154 $$->const_int_set = TRUE;
155 if (g_str_has_prefix (yytext, "0x") && strlen (yytext) > 2) {
156 $$->const_int = strtol (yytext + 2, NULL, 16);
157 } else if (g_str_has_prefix (yytext, "0") && strlen (yytext) > 1) {
158 $$->const_int = strtol (yytext + 1, NULL, 8);
160 $$->const_int = atoi (yytext);
165 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
169 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
178 /* concatenate adjacent string literal tokens */
182 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
183 yytext[strlen (yytext) - 1] = '\0';
184 $$->const_string = g_strcompress (yytext + 1);
185 if (!g_utf8_validate ($$->const_string, -1, NULL))
187 g_warning ("Ignoring non-UTF-8 constant string %s", $$->ident);
188 g_free($$->const_string);
189 $$->const_string = NULL;
195 char *strings, *string2;
197 yytext[strlen (yytext) - 1] = '\0';
198 string2 = g_strcompress (yytext + 1);
199 strings = g_strconcat ($$->const_string, string2, NULL);
200 g_free ($$->const_string);
202 $$->const_string = strings;
209 $$ = g_strdup (yytext);
213 identifier_or_typedef_name
220 | postfix_expression '[' expression ']'
222 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
224 | postfix_expression '(' argument_expression_list ')'
226 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
228 | postfix_expression '(' ')'
230 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
232 | postfix_expression '.' identifier_or_typedef_name
234 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
236 | postfix_expression ARROW identifier_or_typedef_name
238 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
240 | postfix_expression PLUSPLUS
242 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
244 | postfix_expression MINUSMINUS
246 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
250 argument_expression_list
251 : assignment_expression
252 | argument_expression_list ',' assignment_expression
257 | PLUSPLUS unary_expression
259 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
261 | MINUSMINUS unary_expression
263 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
265 | unary_operator cast_expression
273 $$->const_int = -$2->const_int;
275 case UNARY_BITWISE_COMPLEMENT:
277 $$->const_int = ~$2->const_int;
279 case UNARY_LOGICAL_NEGATION:
281 $$->const_int = !gi_source_symbol_get_const_boolean ($2);
284 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
288 | SIZEOF unary_expression
290 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
292 | SIZEOF '(' type_name ')'
295 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
302 $$ = UNARY_ADDRESS_OF;
306 $$ = UNARY_POINTER_INDIRECTION;
318 $$ = UNARY_BITWISE_COMPLEMENT;
322 $$ = UNARY_LOGICAL_NEGATION;
328 | '(' type_name ')' cast_expression
335 multiplicative_expression
337 | multiplicative_expression '*' cast_expression
339 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
340 $$->const_int_set = TRUE;
341 $$->const_int = $1->const_int * $3->const_int;
343 | multiplicative_expression '/' cast_expression
345 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
346 $$->const_int_set = TRUE;
347 if ($3->const_int != 0) {
348 $$->const_int = $1->const_int / $3->const_int;
351 | multiplicative_expression '%' cast_expression
353 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
354 $$->const_int_set = TRUE;
355 if ($3->const_int != 0) {
356 $$->const_int = $1->const_int % $3->const_int;
362 : multiplicative_expression
363 | additive_expression '+' multiplicative_expression
365 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
366 $$->const_int_set = TRUE;
367 $$->const_int = $1->const_int + $3->const_int;
369 | additive_expression '-' multiplicative_expression
371 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
372 $$->const_int_set = TRUE;
373 $$->const_int = $1->const_int - $3->const_int;
378 : additive_expression
379 | shift_expression SL additive_expression
381 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
382 $$->const_int_set = TRUE;
383 $$->const_int = $1->const_int << $3->const_int;
385 | shift_expression SR additive_expression
387 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
388 $$->const_int_set = TRUE;
389 $$->const_int = $1->const_int >> $3->const_int;
393 relational_expression
395 | relational_expression '<' shift_expression
397 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
398 $$->const_int_set = TRUE;
399 $$->const_int = $1->const_int < $3->const_int;
401 | relational_expression '>' shift_expression
403 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
404 $$->const_int_set = TRUE;
405 $$->const_int = $1->const_int > $3->const_int;
407 | relational_expression LTEQ shift_expression
409 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
410 $$->const_int_set = TRUE;
411 $$->const_int = $1->const_int <= $3->const_int;
413 | relational_expression GTEQ shift_expression
415 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
416 $$->const_int_set = TRUE;
417 $$->const_int = $1->const_int >= $3->const_int;
422 : relational_expression
423 | equality_expression EQ relational_expression
425 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
426 $$->const_int_set = TRUE;
427 $$->const_int = $1->const_int == $3->const_int;
429 | equality_expression NOTEQ relational_expression
431 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
432 $$->const_int_set = TRUE;
433 $$->const_int = $1->const_int != $3->const_int;
438 : equality_expression
439 | and_expression '&' equality_expression
441 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
442 $$->const_int_set = TRUE;
443 $$->const_int = $1->const_int & $3->const_int;
447 exclusive_or_expression
449 | exclusive_or_expression '^' and_expression
451 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
452 $$->const_int_set = TRUE;
453 $$->const_int = $1->const_int ^ $3->const_int;
457 inclusive_or_expression
458 : exclusive_or_expression
459 | inclusive_or_expression '|' exclusive_or_expression
461 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
462 $$->const_int_set = TRUE;
463 $$->const_int = $1->const_int | $3->const_int;
467 logical_and_expression
468 : inclusive_or_expression
469 | logical_and_expression ANDAND inclusive_or_expression
471 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
472 $$->const_int_set = TRUE;
474 gi_source_symbol_get_const_boolean ($1) &&
475 gi_source_symbol_get_const_boolean ($3);
479 logical_or_expression
480 : logical_and_expression
481 | logical_or_expression OROR logical_and_expression
483 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
484 $$->const_int_set = TRUE;
486 gi_source_symbol_get_const_boolean ($1) ||
487 gi_source_symbol_get_const_boolean ($3);
491 conditional_expression
492 : logical_or_expression
493 | logical_or_expression '?' expression ':' conditional_expression
495 $$ = gi_source_symbol_get_const_boolean ($1) ? $3 : $5;
499 assignment_expression
500 : conditional_expression
501 | unary_expression assignment_operator assignment_expression
503 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
522 : assignment_expression
523 | expression ',' assignment_expression
525 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
530 : conditional_expression
533 /* A.2.2 Declarations. */
536 : declaration_specifiers init_declarator_list ';'
539 for (l = $2; l != NULL; l = l->next) {
540 GISourceSymbol *sym = l->data;
541 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
542 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF) {
543 sym->type = CSYMBOL_TYPE_TYPEDEF;
544 } else if (sym->base_type->type == CTYPE_FUNCTION) {
545 sym->type = CSYMBOL_TYPE_FUNCTION;
547 sym->type = CSYMBOL_TYPE_OBJECT;
549 gi_source_scanner_add_symbol (scanner, sym);
550 gi_source_symbol_unref (sym);
554 | declaration_specifiers ';'
560 declaration_specifiers
561 : storage_class_specifier declaration_specifiers
564 $$->storage_class_specifier |= $1;
566 | storage_class_specifier
568 $$ = gi_source_type_new (CTYPE_INVALID);
569 $$->storage_class_specifier |= $1;
571 | type_specifier declaration_specifiers
574 /* combine basic types like unsigned int and long long */
575 if ($$->type == CTYPE_BASIC_TYPE && $2->type == CTYPE_BASIC_TYPE) {
576 char *name = g_strdup_printf ("%s %s", $$->name, $2->name);
585 | type_qualifier declaration_specifiers
588 $$->type_qualifier |= $1;
592 $$ = gi_source_type_new (CTYPE_INVALID);
593 $$->type_qualifier |= $1;
595 | function_specifier declaration_specifiers
598 $$->function_specifier |= $1;
602 $$ = gi_source_type_new (CTYPE_INVALID);
603 $$->function_specifier |= $1;
610 $$ = g_list_append (NULL, $1);
612 | init_declarator_list ',' init_declarator
614 $$ = g_list_append ($1, $3);
620 | declarator '=' initializer
623 storage_class_specifier
626 $$ = STORAGE_CLASS_TYPEDEF;
630 $$ = STORAGE_CLASS_EXTERN;
634 $$ = STORAGE_CLASS_STATIC;
638 $$ = STORAGE_CLASS_AUTO;
642 $$ = STORAGE_CLASS_REGISTER;
649 $$ = gi_source_type_new (CTYPE_VOID);
653 $$ = gi_source_basic_type_new ("char");
657 $$ = gi_source_basic_type_new ("short");
661 $$ = gi_source_basic_type_new ("int");
665 $$ = gi_source_basic_type_new ("long");
669 $$ = gi_source_basic_type_new ("float");
673 $$ = gi_source_basic_type_new ("double");
677 $$ = gi_source_basic_type_new ("signed");
681 $$ = gi_source_basic_type_new ("unsigned");
685 $$ = gi_source_basic_type_new ("bool");
687 | struct_or_union_specifier
691 $$ = gi_source_typedef_new ($1);
696 struct_or_union_specifier
697 : struct_or_union identifier_or_typedef_name '{' struct_declaration_list '}'
703 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
704 if ($$->type == CTYPE_STRUCT) {
705 sym->type = CSYMBOL_TYPE_STRUCT;
706 } else if ($$->type == CTYPE_UNION) {
707 sym->type = CSYMBOL_TYPE_UNION;
709 g_assert_not_reached ();
711 sym->ident = g_strdup ($$->name);
712 sym->base_type = gi_source_type_copy ($$);
713 gi_source_scanner_add_symbol (scanner, sym);
714 gi_source_symbol_unref (sym);
716 | struct_or_union '{' struct_declaration_list '}'
721 | struct_or_union identifier_or_typedef_name
731 $$ = gi_source_struct_new (NULL);
735 $$ = gi_source_union_new (NULL);
739 struct_declaration_list
741 | struct_declaration_list struct_declaration
743 $$ = g_list_concat ($1, $2);
748 : specifier_qualifier_list struct_declarator_list ';'
752 for (l = $2; l != NULL; l = l->next)
754 GISourceSymbol *sym = l->data;
755 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF)
756 sym->type = CSYMBOL_TYPE_TYPEDEF;
758 sym->type = CSYMBOL_TYPE_MEMBER;
759 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
760 $$ = g_list_append ($$, sym);
766 specifier_qualifier_list
767 : type_specifier specifier_qualifier_list
773 | type_qualifier specifier_qualifier_list
776 $$->type_qualifier |= $1;
780 $$ = gi_source_type_new (CTYPE_INVALID);
781 $$->type_qualifier |= $1;
785 struct_declarator_list
788 $$ = g_list_append (NULL, $1);
790 | struct_declarator_list ',' struct_declarator
792 $$ = g_list_append ($1, $3);
797 : /* empty, support for anonymous structs and unions */
799 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
802 | ':' constant_expression
804 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
806 | declarator ':' constant_expression
809 if ($3->const_int_set) {
810 $$->const_int_set = TRUE;
811 $$->const_int = $3->const_int;
817 : ENUM identifier_or_typedef_name '{' enumerator_list '}'
819 $$ = gi_source_enum_new ($2);
821 last_enum_value = -1;
823 | ENUM '{' enumerator_list '}'
825 $$ = gi_source_enum_new (NULL);
827 last_enum_value = -1;
829 | ENUM identifier_or_typedef_name '{' enumerator_list ',' '}'
831 $$ = gi_source_enum_new ($2);
833 last_enum_value = -1;
835 | ENUM '{' enumerator_list ',' '}'
837 $$ = gi_source_enum_new (NULL);
839 last_enum_value = -1;
841 | ENUM identifier_or_typedef_name
843 $$ = gi_source_enum_new ($2);
850 $$ = g_list_append (NULL, $1);
852 | enumerator_list ',' enumerator
854 $$ = g_list_append ($1, $3);
861 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
863 $$->const_int_set = TRUE;
864 $$->const_int = ++last_enum_value;
865 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
867 | identifier '=' constant_expression
869 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
871 $$->const_int_set = TRUE;
872 $$->const_int = $3->const_int;
873 last_enum_value = $$->const_int;
874 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
881 $$ = TYPE_QUALIFIER_CONST;
885 $$ = TYPE_QUALIFIER_RESTRICT;
889 $$ = TYPE_QUALIFIER_EXTENSION;
893 $$ = TYPE_QUALIFIER_VOLATILE;
900 $$ = FUNCTION_INLINE;
905 : pointer direct_declarator
908 gi_source_symbol_merge_type ($$, $1);
916 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
923 | direct_declarator '[' assignment_expression ']'
926 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
928 | direct_declarator '[' ']'
931 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
933 | direct_declarator '(' parameter_list ')'
935 GISourceType *func = gi_source_function_new ();
936 // ignore (void) parameter list
937 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
938 func->child_list = $3;
941 gi_source_symbol_merge_type ($$, func);
943 | direct_declarator '(' identifier_list ')'
945 GISourceType *func = gi_source_function_new ();
946 func->child_list = $3;
948 gi_source_symbol_merge_type ($$, func);
950 | direct_declarator '(' ')'
952 GISourceType *func = gi_source_function_new ();
954 gi_source_symbol_merge_type ($$, func);
959 : '*' type_qualifier_list
961 $$ = gi_source_pointer_new (NULL);
962 $$->type_qualifier = $2;
966 $$ = gi_source_pointer_new (NULL);
968 | '*' type_qualifier_list pointer
970 $$ = gi_source_pointer_new ($3);
971 $$->type_qualifier = $2;
975 $$ = gi_source_pointer_new ($2);
981 | type_qualifier_list type_qualifier
988 : parameter_declaration
990 $$ = g_list_append (NULL, $1);
992 | parameter_list ',' parameter_declaration
994 $$ = g_list_append ($1, $3);
998 parameter_declaration
999 : declaration_specifiers declarator
1002 gi_source_symbol_merge_type ($$, $1);
1004 | declaration_specifiers abstract_declarator
1007 gi_source_symbol_merge_type ($$, $1);
1009 | declaration_specifiers
1011 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1016 $$ = gi_source_symbol_new (CSYMBOL_TYPE_ELLIPSIS);
1023 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1025 $$ = g_list_append (NULL, sym);
1027 | identifier_list ',' identifier
1029 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1031 $$ = g_list_append ($1, sym);
1036 : specifier_qualifier_list
1037 | specifier_qualifier_list abstract_declarator
1043 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1044 gi_source_symbol_merge_type ($$, $1);
1046 | direct_abstract_declarator
1047 | pointer direct_abstract_declarator
1050 gi_source_symbol_merge_type ($$, $1);
1054 direct_abstract_declarator
1055 : '(' abstract_declarator ')'
1061 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1062 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1064 | '[' assignment_expression ']'
1066 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1067 gi_source_symbol_merge_type ($$, gi_source_array_new ($2));
1069 | direct_abstract_declarator '[' ']'
1072 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1074 | direct_abstract_declarator '[' assignment_expression ']'
1077 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
1081 GISourceType *func = gi_source_function_new ();
1082 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1083 gi_source_symbol_merge_type ($$, func);
1085 | '(' parameter_list ')'
1087 GISourceType *func = gi_source_function_new ();
1088 // ignore (void) parameter list
1089 if ($2 != NULL && ($2->next != NULL || ((GISourceSymbol *) $2->data)->base_type->type != CTYPE_VOID)) {
1090 func->child_list = $2;
1092 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1093 gi_source_symbol_merge_type ($$, func);
1095 | direct_abstract_declarator '(' ')'
1097 GISourceType *func = gi_source_function_new ();
1099 gi_source_symbol_merge_type ($$, func);
1101 | direct_abstract_declarator '(' parameter_list ')'
1103 GISourceType *func = gi_source_function_new ();
1104 // ignore (void) parameter list
1105 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1106 func->child_list = $3;
1109 gi_source_symbol_merge_type ($$, func);
1116 $$ = g_strdup (yytext);
1121 : assignment_expression
1122 | '{' initializer_list '}'
1123 | '{' initializer_list ',' '}'
1128 | initializer_list ',' initializer
1131 /* A.2.3 Statements. */
1135 | compound_statement
1136 | expression_statement
1137 | selection_statement
1138 | iteration_statement
1143 : identifier_or_typedef_name ':' statement
1144 | CASE constant_expression ':' statement
1145 | DEFAULT ':' statement
1150 | '{' block_item_list '}'
1155 | block_item_list block_item
1163 expression_statement
1169 : IF '(' expression ')' statement
1170 | IF '(' expression ')' statement ELSE statement
1171 | SWITCH '(' expression ')' statement
1175 : WHILE '(' expression ')' statement
1176 | DO statement WHILE '(' expression ')' ';'
1177 | FOR '(' ';' ';' ')' statement
1178 | FOR '(' expression ';' ';' ')' statement
1179 | FOR '(' ';' expression ';' ')' statement
1180 | FOR '(' expression ';' expression ';' ')' statement
1181 | FOR '(' ';' ';' expression ')' statement
1182 | FOR '(' expression ';' ';' expression ')' statement
1183 | FOR '(' ';' expression ';' expression ')' statement
1184 | FOR '(' expression ';' expression ';' expression ')' statement
1188 : GOTO identifier_or_typedef_name ';'
1192 | RETURN expression ';'
1195 /* A.2.4 External definitions. */
1198 : external_declaration
1199 | translation_unit external_declaration
1202 external_declaration
1203 : function_definition
1209 : declaration_specifiers declarator declaration_list compound_statement
1210 | declaration_specifiers declarator compound_statement
1215 | declaration_list declaration
1223 $$ = g_strdup (yytext + strlen ("#define "));
1230 $$ = g_strdup (yytext + strlen ("#define "));
1234 function_macro_define
1235 : function_macro '(' identifier_list ')'
1239 : object_macro constant_expression
1241 if ($2->const_int_set || $2->const_string != NULL) {
1243 gi_source_scanner_add_symbol (scanner, $2);
1244 gi_source_symbol_unref ($2);
1250 : function_macro_define
1251 | object_macro_define
1257 yyerror (GISourceScanner *scanner, const char *s)
1259 /* ignore errors while doing a macro scan as not all object macros
1260 * have valid expressions */
1261 if (!scanner->macro_scan)
1263 fprintf(stderr, "%s:%d: %s\n",
1264 scanner->current_filename, lineno, s);
1269 eat_hspace (FILE * f)
1276 while (c == ' ' || c == '\t');
1281 eat_line (FILE * f, int c)
1283 while (c != EOF && c != '\n')
1290 if (c == ' ' || c == '\t')
1299 read_identifier (FILE * f, int c, char **identifier)
1301 GString *id = g_string_new ("");
1302 while (g_ascii_isalnum (c) || c == '_')
1304 g_string_append_c (id, c);
1307 *identifier = g_string_free (id, FALSE);
1312 gi_source_scanner_parse_macros (GISourceScanner *scanner, GList *filenames)
1314 GError *error = NULL;
1315 char *tmp_name = NULL;
1317 fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error),
1319 g_unlink (tmp_name);
1322 for (l = filenames; l != NULL; l = l->next)
1324 FILE *f = fopen (l->data, "r");
1327 GString *define_line;
1329 gboolean error_line = FALSE;
1330 int c = eat_hspace (f);
1336 c = eat_line (f, c);
1341 /* print current location */
1342 str = g_strescape (l->data, "");
1343 fprintf (fmacros, "# %d \"%s\"\n", line, str);
1347 c = read_identifier (f, c, &str);
1348 if (strcmp (str, "define") != 0 || (c != ' ' && c != '\t'))
1352 c = eat_line (f, c);
1358 c = read_identifier (f, c, &str);
1359 if (strlen (str) == 0 || (c != ' ' && c != '\t' && c != '('))
1363 c = eat_line (f, c);
1367 define_line = g_string_new ("#define ");
1368 g_string_append (define_line, str);
1374 g_string_append_c (define_line, c);
1376 if (c == EOF || c == '\n')
1384 g_string_free (define_line, TRUE);
1386 c = eat_line (f, c);
1391 g_assert (c == ')');
1392 g_string_append_c (define_line, c);
1395 /* found function-like macro */
1396 fprintf (fmacros, "%s\n", define_line->str);
1398 g_string_free (define_line, TRUE);
1399 /* ignore rest of line */
1400 c = eat_line (f, c);
1404 if (c != ' ' && c != '\t')
1406 g_string_free (define_line, TRUE);
1408 c = eat_line (f, c);
1412 while (c != EOF && c != '\n')
1414 g_string_append_c (define_line, c);
1421 /* fold lines when seeing backslash new-line sequence */
1426 g_string_append_c (define_line, '\\');
1431 /* found object-like macro */
1432 fprintf (fmacros, "%s\n", define_line->str);
1434 c = eat_line (f, c);
1442 gi_source_scanner_parse_file (scanner, fmacros);
1446 gi_source_scanner_parse_file (GISourceScanner *scanner, FILE *file)
1448 g_return_val_if_fail (file != NULL, FALSE);
1450 const_table = g_hash_table_new_full (g_str_hash, g_str_equal,
1451 g_free, (GDestroyNotify)gi_source_symbol_unref);
1457 g_hash_table_destroy (const_table);
1466 gi_source_scanner_lex_filename (GISourceScanner *scanner, const gchar *filename)
1468 yyin = fopen (filename, "r");
1470 while (yylex (scanner) != YYEOF)