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 static int last_enum_value = -1;
47 static GHashTable *const_table = NULL;
54 GISourceSymbol *symbol;
56 StorageClassSpecifier storage_class_specifier;
57 TypeQualifier type_qualifier;
58 FunctionSpecifier function_specifier;
59 UnaryOperator unary_operator;
62 %parse-param { GISourceScanner* scanner }
63 %lex-param { GISourceScanner* scanner }
65 %token <str> IDENTIFIER "identifier"
66 %token <str> TYPEDEF_NAME "typedef-name"
68 %token INTEGER FLOATING CHARACTER STRING
70 %token ELLIPSIS ADDEQ SUBEQ MULEQ DIVEQ MODEQ XOREQ ANDEQ OREQ SL SR
71 %token SLEQ SREQ EQ NOTEQ LTEQ GTEQ ANDAND OROR PLUSPLUS MINUSMINUS ARROW
73 %token AUTO BOOL BREAK CASE CHAR CONST CONTINUE DEFAULT DO DOUBLE ELSE ENUM
74 %token EXTENSION EXTERN FLOAT FOR GOTO IF INLINE INT LONG REGISTER RESTRICT
75 %token RETURN SHORT SIGNED SIZEOF STATIC STRUCT SWITCH TYPEDEF UNION UNSIGNED
76 %token VOID VOLATILE WHILE
78 %token FUNCTION_MACRO OBJECT_MACRO
80 %start translation_unit
82 %type <ctype> declaration_specifiers
83 %type <ctype> enum_specifier
85 %type <ctype> specifier_qualifier_list
86 %type <ctype> type_name
87 %type <ctype> struct_or_union
88 %type <ctype> struct_or_union_specifier
89 %type <ctype> type_specifier
90 %type <str> identifier
91 %type <str> typedef_name
92 %type <str> identifier_or_typedef_name
93 %type <symbol> abstract_declarator
94 %type <symbol> init_declarator
95 %type <symbol> declarator
96 %type <symbol> enumerator
97 %type <symbol> direct_abstract_declarator
98 %type <symbol> direct_declarator
99 %type <symbol> parameter_declaration
100 %type <symbol> struct_declarator
101 %type <list> enumerator_list
102 %type <list> identifier_list
103 %type <list> init_declarator_list
104 %type <list> parameter_list
105 %type <list> struct_declaration
106 %type <list> struct_declaration_list
107 %type <list> struct_declarator_list
108 %type <storage_class_specifier> storage_class_specifier
109 %type <type_qualifier> type_qualifier
110 %type <type_qualifier> type_qualifier_list
111 %type <function_specifier> function_specifier
112 %type <symbol> expression
113 %type <symbol> constant_expression
114 %type <symbol> conditional_expression
115 %type <symbol> logical_and_expression
116 %type <symbol> logical_or_expression
117 %type <symbol> inclusive_or_expression
118 %type <symbol> exclusive_or_expression
119 %type <symbol> multiplicative_expression
120 %type <symbol> additive_expression
121 %type <symbol> shift_expression
122 %type <symbol> relational_expression
123 %type <symbol> equality_expression
124 %type <symbol> and_expression
125 %type <symbol> cast_expression
126 %type <symbol> assignment_expression
127 %type <symbol> unary_expression
128 %type <symbol> postfix_expression
129 %type <symbol> primary_expression
130 %type <unary_operator> unary_operator
131 %type <str> function_macro
132 %type <str> object_macro
133 %type <symbol> strings
137 /* A.2.1 Expressions. */
142 $$ = g_hash_table_lookup (const_table, $1);
144 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
146 $$ = gi_source_symbol_ref ($$);
151 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
152 $$->const_int_set = TRUE;
153 if (g_str_has_prefix (yytext, "0x") && strlen (yytext) > 2) {
154 $$->const_int = strtol (yytext + 2, NULL, 16);
155 } else if (g_str_has_prefix (yytext, "0") && strlen (yytext) > 1) {
156 $$->const_int = strtol (yytext + 1, NULL, 8);
158 $$->const_int = atoi (yytext);
163 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
167 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
176 /* concatenate adjacent string literal tokens */
180 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
181 yytext[strlen (yytext) - 1] = '\0';
182 $$->const_string = g_strcompress (yytext + 1);
183 if (!g_utf8_validate ($$->const_string, -1, NULL))
185 g_warning ("Ignoring non-UTF-8 constant string %s", $$->ident);
186 g_free($$->const_string);
187 $$->const_string = NULL;
193 char *strings, *string2;
195 yytext[strlen (yytext) - 1] = '\0';
196 string2 = g_strcompress (yytext + 1);
197 strings = g_strconcat ($$->const_string, string2, NULL);
198 g_free ($$->const_string);
200 $$->const_string = strings;
207 $$ = g_strdup (yytext);
211 identifier_or_typedef_name
218 | postfix_expression '[' expression ']'
220 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
222 | postfix_expression '(' argument_expression_list ')'
224 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
226 | postfix_expression '(' ')'
228 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
230 | postfix_expression '.' identifier_or_typedef_name
232 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
234 | postfix_expression ARROW identifier_or_typedef_name
236 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
238 | postfix_expression PLUSPLUS
240 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
242 | postfix_expression MINUSMINUS
244 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
248 argument_expression_list
249 : assignment_expression
250 | argument_expression_list ',' assignment_expression
255 | PLUSPLUS unary_expression
257 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
259 | MINUSMINUS unary_expression
261 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
263 | unary_operator cast_expression
271 $$->const_int = -$2->const_int;
273 case UNARY_BITWISE_COMPLEMENT:
275 $$->const_int = ~$2->const_int;
277 case UNARY_LOGICAL_NEGATION:
279 $$->const_int = !gi_source_symbol_get_const_boolean ($2);
282 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
286 | SIZEOF unary_expression
288 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
290 | SIZEOF '(' type_name ')'
293 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
300 $$ = UNARY_ADDRESS_OF;
304 $$ = UNARY_POINTER_INDIRECTION;
316 $$ = UNARY_BITWISE_COMPLEMENT;
320 $$ = UNARY_LOGICAL_NEGATION;
326 | '(' type_name ')' cast_expression
333 multiplicative_expression
335 | multiplicative_expression '*' cast_expression
337 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
338 $$->const_int_set = TRUE;
339 $$->const_int = $1->const_int * $3->const_int;
341 | multiplicative_expression '/' cast_expression
343 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
344 $$->const_int_set = TRUE;
345 if ($3->const_int != 0) {
346 $$->const_int = $1->const_int / $3->const_int;
349 | multiplicative_expression '%' cast_expression
351 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
352 $$->const_int_set = TRUE;
353 $$->const_int = $1->const_int % $3->const_int;
358 : multiplicative_expression
359 | additive_expression '+' multiplicative_expression
361 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
362 $$->const_int_set = TRUE;
363 $$->const_int = $1->const_int + $3->const_int;
365 | additive_expression '-' multiplicative_expression
367 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
368 $$->const_int_set = TRUE;
369 $$->const_int = $1->const_int - $3->const_int;
374 : additive_expression
375 | shift_expression SL additive_expression
377 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
378 $$->const_int_set = TRUE;
379 $$->const_int = $1->const_int << $3->const_int;
381 | shift_expression SR additive_expression
383 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
384 $$->const_int_set = TRUE;
385 $$->const_int = $1->const_int >> $3->const_int;
389 relational_expression
391 | relational_expression '<' shift_expression
393 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
394 $$->const_int_set = TRUE;
395 $$->const_int = $1->const_int < $3->const_int;
397 | relational_expression '>' shift_expression
399 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
400 $$->const_int_set = TRUE;
401 $$->const_int = $1->const_int > $3->const_int;
403 | relational_expression LTEQ shift_expression
405 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
406 $$->const_int_set = TRUE;
407 $$->const_int = $1->const_int <= $3->const_int;
409 | relational_expression GTEQ shift_expression
411 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
412 $$->const_int_set = TRUE;
413 $$->const_int = $1->const_int >= $3->const_int;
418 : relational_expression
419 | equality_expression EQ relational_expression
421 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
422 $$->const_int_set = TRUE;
423 $$->const_int = $1->const_int == $3->const_int;
425 | equality_expression NOTEQ relational_expression
427 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
428 $$->const_int_set = TRUE;
429 $$->const_int = $1->const_int != $3->const_int;
434 : equality_expression
435 | and_expression '&' equality_expression
437 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
438 $$->const_int_set = TRUE;
439 $$->const_int = $1->const_int & $3->const_int;
443 exclusive_or_expression
445 | exclusive_or_expression '^' and_expression
447 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
448 $$->const_int_set = TRUE;
449 $$->const_int = $1->const_int ^ $3->const_int;
453 inclusive_or_expression
454 : exclusive_or_expression
455 | inclusive_or_expression '|' exclusive_or_expression
457 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
458 $$->const_int_set = TRUE;
459 $$->const_int = $1->const_int | $3->const_int;
463 logical_and_expression
464 : inclusive_or_expression
465 | logical_and_expression ANDAND inclusive_or_expression
467 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
468 $$->const_int_set = TRUE;
470 gi_source_symbol_get_const_boolean ($1) &&
471 gi_source_symbol_get_const_boolean ($3);
475 logical_or_expression
476 : logical_and_expression
477 | logical_or_expression OROR logical_and_expression
479 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
480 $$->const_int_set = TRUE;
482 gi_source_symbol_get_const_boolean ($1) ||
483 gi_source_symbol_get_const_boolean ($3);
487 conditional_expression
488 : logical_or_expression
489 | logical_or_expression '?' expression ':' conditional_expression
491 $$ = gi_source_symbol_get_const_boolean ($1) ? $3 : $5;
495 assignment_expression
496 : conditional_expression
497 | unary_expression assignment_operator assignment_expression
499 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
518 : assignment_expression
519 | expression ',' assignment_expression
521 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
526 : conditional_expression
529 /* A.2.2 Declarations. */
532 : declaration_specifiers init_declarator_list ';'
535 for (l = $2; l != NULL; l = l->next) {
536 GISourceSymbol *sym = l->data;
537 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
538 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF) {
539 sym->type = CSYMBOL_TYPE_TYPEDEF;
540 } else if (sym->base_type->type == CTYPE_FUNCTION) {
541 sym->type = CSYMBOL_TYPE_FUNCTION;
543 sym->type = CSYMBOL_TYPE_OBJECT;
545 gi_source_scanner_add_symbol (scanner, sym);
546 gi_source_symbol_unref (sym);
550 | declaration_specifiers ';'
556 declaration_specifiers
557 : storage_class_specifier declaration_specifiers
560 $$->storage_class_specifier |= $1;
562 | storage_class_specifier
564 $$ = gi_source_type_new (CTYPE_INVALID);
565 $$->storage_class_specifier |= $1;
567 | type_specifier declaration_specifiers
570 /* combine basic types like unsigned int and long long */
571 if ($$->type == CTYPE_BASIC_TYPE && $2->type == CTYPE_BASIC_TYPE) {
572 char *name = g_strdup_printf ("%s %s", $$->name, $2->name);
581 | type_qualifier declaration_specifiers
584 $$->type_qualifier |= $1;
588 $$ = gi_source_type_new (CTYPE_INVALID);
589 $$->type_qualifier |= $1;
591 | function_specifier declaration_specifiers
594 $$->function_specifier |= $1;
598 $$ = gi_source_type_new (CTYPE_INVALID);
599 $$->function_specifier |= $1;
606 $$ = g_list_append (NULL, $1);
608 | init_declarator_list ',' init_declarator
610 $$ = g_list_append ($1, $3);
616 | declarator '=' initializer
619 storage_class_specifier
622 $$ = STORAGE_CLASS_TYPEDEF;
626 $$ = STORAGE_CLASS_EXTERN;
630 $$ = STORAGE_CLASS_STATIC;
634 $$ = STORAGE_CLASS_AUTO;
638 $$ = STORAGE_CLASS_REGISTER;
645 $$ = gi_source_type_new (CTYPE_VOID);
649 $$ = gi_source_basic_type_new ("char");
653 $$ = gi_source_basic_type_new ("short");
657 $$ = gi_source_basic_type_new ("int");
661 $$ = gi_source_basic_type_new ("long");
665 $$ = gi_source_basic_type_new ("float");
669 $$ = gi_source_basic_type_new ("double");
673 $$ = gi_source_basic_type_new ("signed");
677 $$ = gi_source_basic_type_new ("unsigned");
681 $$ = gi_source_basic_type_new ("bool");
683 | struct_or_union_specifier
687 $$ = gi_source_typedef_new ($1);
692 struct_or_union_specifier
693 : struct_or_union identifier_or_typedef_name '{' struct_declaration_list '}'
699 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
700 if ($$->type == CTYPE_STRUCT) {
701 sym->type = CSYMBOL_TYPE_STRUCT;
702 } else if ($$->type == CTYPE_UNION) {
703 sym->type = CSYMBOL_TYPE_UNION;
705 g_assert_not_reached ();
707 sym->ident = g_strdup ($$->name);
708 sym->base_type = gi_source_type_copy ($$);
709 gi_source_scanner_add_symbol (scanner, sym);
710 gi_source_symbol_unref (sym);
712 | struct_or_union '{' struct_declaration_list '}'
717 | struct_or_union identifier_or_typedef_name
727 $$ = gi_source_struct_new (NULL);
731 $$ = gi_source_union_new (NULL);
735 struct_declaration_list
737 | struct_declaration_list struct_declaration
739 $$ = g_list_concat ($1, $2);
744 : specifier_qualifier_list struct_declarator_list ';'
748 for (l = $2; l != NULL; l = l->next)
750 GISourceSymbol *sym = l->data;
751 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF)
752 sym->type = CSYMBOL_TYPE_TYPEDEF;
754 sym->type = CSYMBOL_TYPE_MEMBER;
755 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
756 $$ = g_list_append ($$, sym);
762 specifier_qualifier_list
763 : type_specifier specifier_qualifier_list
769 | type_qualifier specifier_qualifier_list
772 $$->type_qualifier |= $1;
776 $$ = gi_source_type_new (CTYPE_INVALID);
777 $$->type_qualifier |= $1;
781 struct_declarator_list
784 $$ = g_list_append (NULL, $1);
786 | struct_declarator_list ',' struct_declarator
788 $$ = g_list_append ($1, $3);
793 : /* empty, support for anonymous structs and unions */
795 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
798 | ':' constant_expression
800 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
802 | declarator ':' constant_expression
805 if ($3->const_int_set) {
806 $$->const_int_set = TRUE;
807 $$->const_int = $3->const_int;
813 : ENUM identifier_or_typedef_name '{' enumerator_list '}'
815 $$ = gi_source_enum_new ($2);
817 last_enum_value = -1;
819 | ENUM '{' enumerator_list '}'
821 $$ = gi_source_enum_new (NULL);
823 last_enum_value = -1;
825 | ENUM identifier_or_typedef_name '{' enumerator_list ',' '}'
827 $$ = gi_source_enum_new ($2);
829 last_enum_value = -1;
831 | ENUM '{' enumerator_list ',' '}'
833 $$ = gi_source_enum_new (NULL);
835 last_enum_value = -1;
837 | ENUM identifier_or_typedef_name
839 $$ = gi_source_enum_new ($2);
846 $$ = g_list_append (NULL, $1);
848 | enumerator_list ',' enumerator
850 $$ = g_list_append ($1, $3);
857 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
859 $$->const_int_set = TRUE;
860 $$->const_int = ++last_enum_value;
861 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
863 | identifier '=' constant_expression
865 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
867 $$->const_int_set = TRUE;
868 $$->const_int = $3->const_int;
869 last_enum_value = $$->const_int;
870 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
877 $$ = TYPE_QUALIFIER_CONST;
881 $$ = TYPE_QUALIFIER_RESTRICT;
885 $$ = TYPE_QUALIFIER_EXTENSION;
889 $$ = TYPE_QUALIFIER_VOLATILE;
896 $$ = FUNCTION_INLINE;
901 : pointer direct_declarator
904 gi_source_symbol_merge_type ($$, $1);
912 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
919 | direct_declarator '[' assignment_expression ']'
922 gi_source_symbol_merge_type ($$, gi_source_array_new ());
924 | direct_declarator '[' ']'
927 gi_source_symbol_merge_type ($$, gi_source_array_new ());
929 | direct_declarator '(' parameter_list ')'
931 GISourceType *func = gi_source_function_new ();
932 // ignore (void) parameter list
933 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
934 func->child_list = $3;
937 gi_source_symbol_merge_type ($$, func);
939 | direct_declarator '(' identifier_list ')'
941 GISourceType *func = gi_source_function_new ();
942 func->child_list = $3;
944 gi_source_symbol_merge_type ($$, func);
946 | direct_declarator '(' ')'
948 GISourceType *func = gi_source_function_new ();
950 gi_source_symbol_merge_type ($$, func);
955 : '*' type_qualifier_list
957 $$ = gi_source_pointer_new (NULL);
958 $$->type_qualifier = $2;
962 $$ = gi_source_pointer_new (NULL);
964 | '*' type_qualifier_list pointer
966 $$ = gi_source_pointer_new ($3);
967 $$->type_qualifier = $2;
971 $$ = gi_source_pointer_new ($2);
977 | type_qualifier_list type_qualifier
984 : parameter_declaration
986 $$ = g_list_append (NULL, $1);
988 | parameter_list ',' parameter_declaration
990 $$ = g_list_append ($1, $3);
994 parameter_declaration
995 : declaration_specifiers declarator
998 gi_source_symbol_merge_type ($$, $1);
1000 | declaration_specifiers abstract_declarator
1003 gi_source_symbol_merge_type ($$, $1);
1005 | declaration_specifiers
1007 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1012 $$ = gi_source_symbol_new (CSYMBOL_TYPE_ELLIPSIS);
1019 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1021 $$ = g_list_append (NULL, sym);
1023 | identifier_list ',' identifier
1025 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1027 $$ = g_list_append ($1, sym);
1032 : specifier_qualifier_list
1033 | specifier_qualifier_list abstract_declarator
1039 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1040 gi_source_symbol_merge_type ($$, $1);
1042 | direct_abstract_declarator
1043 | pointer direct_abstract_declarator
1046 gi_source_symbol_merge_type ($$, $1);
1050 direct_abstract_declarator
1051 : '(' abstract_declarator ')'
1057 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1058 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1060 | '[' assignment_expression ']'
1062 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1063 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1065 | direct_abstract_declarator '[' ']'
1068 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1070 | direct_abstract_declarator '[' assignment_expression ']'
1073 gi_source_symbol_merge_type ($$, gi_source_array_new ());
1077 GISourceType *func = gi_source_function_new ();
1078 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1079 gi_source_symbol_merge_type ($$, func);
1081 | '(' parameter_list ')'
1083 GISourceType *func = gi_source_function_new ();
1084 // ignore (void) parameter list
1085 if ($2 != NULL && ($2->next != NULL || ((GISourceSymbol *) $2->data)->base_type->type != CTYPE_VOID)) {
1086 func->child_list = $2;
1088 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1089 gi_source_symbol_merge_type ($$, func);
1091 | direct_abstract_declarator '(' ')'
1093 GISourceType *func = gi_source_function_new ();
1095 gi_source_symbol_merge_type ($$, func);
1097 | direct_abstract_declarator '(' parameter_list ')'
1099 GISourceType *func = gi_source_function_new ();
1100 // ignore (void) parameter list
1101 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1102 func->child_list = $3;
1105 gi_source_symbol_merge_type ($$, func);
1112 $$ = g_strdup (yytext);
1117 : assignment_expression
1118 | '{' initializer_list '}'
1119 | '{' initializer_list ',' '}'
1124 | initializer_list ',' initializer
1127 /* A.2.3 Statements. */
1131 | compound_statement
1132 | expression_statement
1133 | selection_statement
1134 | iteration_statement
1139 : identifier_or_typedef_name ':' statement
1140 | CASE constant_expression ':' statement
1141 | DEFAULT ':' statement
1146 | '{' block_item_list '}'
1151 | block_item_list block_item
1159 expression_statement
1165 : IF '(' expression ')' statement
1166 | IF '(' expression ')' statement ELSE statement
1167 | SWITCH '(' expression ')' statement
1171 : WHILE '(' expression ')' statement
1172 | DO statement WHILE '(' expression ')' ';'
1173 | FOR '(' ';' ';' ')' statement
1174 | FOR '(' expression ';' ';' ')' statement
1175 | FOR '(' ';' expression ';' ')' statement
1176 | FOR '(' expression ';' expression ';' ')' statement
1177 | FOR '(' ';' ';' expression ')' statement
1178 | FOR '(' expression ';' ';' expression ')' statement
1179 | FOR '(' ';' expression ';' expression ')' statement
1180 | FOR '(' expression ';' expression ';' expression ')' statement
1184 : GOTO identifier_or_typedef_name ';'
1188 | RETURN expression ';'
1191 /* A.2.4 External definitions. */
1194 : external_declaration
1195 | translation_unit external_declaration
1198 external_declaration
1199 : function_definition
1205 : declaration_specifiers declarator declaration_list compound_statement
1206 | declaration_specifiers declarator compound_statement
1211 | declaration_list declaration
1219 $$ = g_strdup (yytext + strlen ("#define "));
1226 $$ = g_strdup (yytext + strlen ("#define "));
1230 function_macro_define
1231 : function_macro '(' identifier_list ')'
1235 : object_macro constant_expression
1237 if ($2->const_int_set || $2->const_string != NULL) {
1239 gi_source_scanner_add_symbol (scanner, $2);
1240 gi_source_symbol_unref ($2);
1246 : function_macro_define
1247 | object_macro_define
1253 yyerror (GISourceScanner *scanner, const char *s)
1255 /* ignore errors while doing a macro scan as not all object macros
1256 * have valid expressions */
1257 if (!scanner->macro_scan)
1259 fprintf(stderr, "%s:%d: %s\n",
1260 scanner->current_filename, lineno, s);
1265 eat_hspace (FILE * f)
1272 while (c == ' ' || c == '\t');
1277 eat_line (FILE * f, int c)
1279 while (c != EOF && c != '\n')
1286 if (c == ' ' || c == '\t')
1295 read_identifier (FILE * f, int c, char **identifier)
1297 GString *id = g_string_new ("");
1298 while (g_ascii_isalnum (c) || c == '_')
1300 g_string_append_c (id, c);
1303 *identifier = g_string_free (id, FALSE);
1308 gi_source_scanner_parse_macros (GISourceScanner *scanner, GList *filenames)
1310 GError *error = NULL;
1311 char *tmp_name = NULL;
1313 fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error),
1315 g_unlink (tmp_name);
1318 for (l = filenames; l != NULL; l = l->next)
1320 FILE *f = fopen (l->data, "r");
1323 GString *define_line;
1325 gboolean error_line = FALSE;
1326 int c = eat_hspace (f);
1332 c = eat_line (f, c);
1337 /* print current location */
1338 str = g_strescape (l->data, "");
1339 fprintf (fmacros, "# %d \"%s\"\n", line, str);
1343 c = read_identifier (f, c, &str);
1344 if (strcmp (str, "define") != 0 || (c != ' ' && c != '\t'))
1348 c = eat_line (f, c);
1354 c = read_identifier (f, c, &str);
1355 if (strlen (str) == 0 || (c != ' ' && c != '\t' && c != '('))
1359 c = eat_line (f, c);
1363 define_line = g_string_new ("#define ");
1364 g_string_append (define_line, str);
1370 g_string_append_c (define_line, c);
1372 if (c == EOF || c == '\n')
1380 g_string_free (define_line, TRUE);
1382 c = eat_line (f, c);
1387 g_assert (c == ')');
1388 g_string_append_c (define_line, c);
1391 /* found function-like macro */
1392 fprintf (fmacros, "%s\n", define_line->str);
1394 g_string_free (define_line, TRUE);
1395 /* ignore rest of line */
1396 c = eat_line (f, c);
1400 if (c != ' ' && c != '\t')
1402 g_string_free (define_line, TRUE);
1404 c = eat_line (f, c);
1408 while (c != EOF && c != '\n')
1410 g_string_append_c (define_line, c);
1417 /* fold lines when seeing backslash new-line sequence */
1422 g_string_append_c (define_line, '\\');
1427 /* found object-like macro */
1428 fprintf (fmacros, "%s\n", define_line->str);
1430 c = eat_line (f, c);
1438 gi_source_scanner_parse_file (scanner, fmacros);
1442 gi_source_scanner_parse_file (GISourceScanner *scanner, FILE *file)
1444 g_return_val_if_fail (file != NULL, FALSE);
1446 const_table = g_hash_table_new_full (g_str_hash, g_str_equal,
1447 g_free, (GDestroyNotify)gi_source_symbol_unref);
1453 g_hash_table_destroy (const_table);
1462 gi_source_scanner_lex_filename (GISourceScanner *scanner, const gchar *filename)
1464 yyin = fopen (filename, "r");
1466 while (yylex (scanner) != YYEOF)