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 gboolean is_bitfield;
50 static GHashTable *const_table = NULL;
57 GISourceSymbol *symbol;
59 StorageClassSpecifier storage_class_specifier;
60 TypeQualifier type_qualifier;
61 FunctionSpecifier function_specifier;
62 UnaryOperator unary_operator;
65 %parse-param { GISourceScanner* scanner }
66 %lex-param { GISourceScanner* scanner }
68 %token <str> IDENTIFIER "identifier"
69 %token <str> TYPEDEF_NAME "typedef-name"
71 %token INTEGER FLOATING CHARACTER STRING
73 %token ELLIPSIS ADDEQ SUBEQ MULEQ DIVEQ MODEQ XOREQ ANDEQ OREQ SL SR
74 %token SLEQ SREQ EQ NOTEQ LTEQ GTEQ ANDAND OROR PLUSPLUS MINUSMINUS ARROW
76 %token AUTO BOOL BREAK CASE CHAR CONST CONTINUE DEFAULT DO DOUBLE ELSE ENUM
77 %token EXTENSION EXTERN FLOAT FOR GOTO IF INLINE INT LONG REGISTER RESTRICT
78 %token RETURN SHORT SIGNED SIZEOF STATIC STRUCT SWITCH TYPEDEF UNION UNSIGNED
79 %token VOID VOLATILE WHILE
81 %token FUNCTION_MACRO OBJECT_MACRO
83 %start translation_unit
85 %type <ctype> declaration_specifiers
86 %type <ctype> enum_specifier
88 %type <ctype> specifier_qualifier_list
89 %type <ctype> type_name
90 %type <ctype> struct_or_union
91 %type <ctype> struct_or_union_specifier
92 %type <ctype> type_specifier
93 %type <str> identifier
94 %type <str> typedef_name
95 %type <str> identifier_or_typedef_name
96 %type <symbol> abstract_declarator
97 %type <symbol> init_declarator
98 %type <symbol> declarator
99 %type <symbol> enumerator
100 %type <symbol> direct_abstract_declarator
101 %type <symbol> direct_declarator
102 %type <symbol> parameter_declaration
103 %type <symbol> struct_declarator
104 %type <list> enumerator_list
105 %type <list> identifier_list
106 %type <list> init_declarator_list
107 %type <list> parameter_list
108 %type <list> struct_declaration
109 %type <list> struct_declaration_list
110 %type <list> struct_declarator_list
111 %type <storage_class_specifier> storage_class_specifier
112 %type <type_qualifier> type_qualifier
113 %type <type_qualifier> type_qualifier_list
114 %type <function_specifier> function_specifier
115 %type <symbol> expression
116 %type <symbol> constant_expression
117 %type <symbol> conditional_expression
118 %type <symbol> logical_and_expression
119 %type <symbol> logical_or_expression
120 %type <symbol> inclusive_or_expression
121 %type <symbol> exclusive_or_expression
122 %type <symbol> multiplicative_expression
123 %type <symbol> additive_expression
124 %type <symbol> shift_expression
125 %type <symbol> relational_expression
126 %type <symbol> equality_expression
127 %type <symbol> and_expression
128 %type <symbol> cast_expression
129 %type <symbol> assignment_expression
130 %type <symbol> unary_expression
131 %type <symbol> postfix_expression
132 %type <symbol> primary_expression
133 %type <unary_operator> unary_operator
134 %type <str> function_macro
135 %type <str> object_macro
136 %type <symbol> strings
140 /* A.2.1 Expressions. */
145 $$ = g_hash_table_lookup (const_table, $1);
147 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
149 $$ = gi_source_symbol_ref ($$);
154 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
155 $$->const_int_set = TRUE;
156 if (g_str_has_prefix (yytext, "0x") && strlen (yytext) > 2) {
157 $$->const_int = strtol (yytext + 2, NULL, 16);
158 } else if (g_str_has_prefix (yytext, "0") && strlen (yytext) > 1) {
159 $$->const_int = strtol (yytext + 1, NULL, 8);
161 $$->const_int = atoi (yytext);
166 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
170 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
171 $$->const_double_set = TRUE;
172 $$->const_double = 0.0;
173 sscanf (yytext, "%lf", &($$->const_double));
182 /* concatenate adjacent string literal tokens */
186 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
187 yytext[strlen (yytext) - 1] = '\0';
188 $$->const_string = g_strcompress (yytext + 1);
189 if (!g_utf8_validate ($$->const_string, -1, NULL))
192 g_warning ("Ignoring non-UTF-8 constant string \"%s\"", yytext + 1);
194 g_free($$->const_string);
195 $$->const_string = NULL;
201 char *strings, *string2;
203 yytext[strlen (yytext) - 1] = '\0';
204 string2 = g_strcompress (yytext + 1);
205 strings = g_strconcat ($$->const_string, string2, NULL);
206 g_free ($$->const_string);
208 $$->const_string = strings;
215 $$ = g_strdup (yytext);
219 identifier_or_typedef_name
226 | postfix_expression '[' expression ']'
228 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
230 | postfix_expression '(' argument_expression_list ')'
232 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
234 | postfix_expression '(' ')'
236 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
238 | postfix_expression '.' identifier_or_typedef_name
240 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
242 | postfix_expression ARROW identifier_or_typedef_name
244 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
246 | postfix_expression PLUSPLUS
248 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
250 | postfix_expression MINUSMINUS
252 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
256 argument_expression_list
257 : assignment_expression
258 | argument_expression_list ',' assignment_expression
263 | PLUSPLUS unary_expression
265 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
267 | MINUSMINUS unary_expression
269 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
271 | unary_operator cast_expression
279 $$->const_int = -$2->const_int;
281 case UNARY_BITWISE_COMPLEMENT:
283 $$->const_int = ~$2->const_int;
285 case UNARY_LOGICAL_NEGATION:
287 $$->const_int = !gi_source_symbol_get_const_boolean ($2);
290 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
294 | SIZEOF unary_expression
296 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
298 | SIZEOF '(' type_name ')'
301 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
308 $$ = UNARY_ADDRESS_OF;
312 $$ = UNARY_POINTER_INDIRECTION;
324 $$ = UNARY_BITWISE_COMPLEMENT;
328 $$ = UNARY_LOGICAL_NEGATION;
334 | '(' type_name ')' cast_expression
341 multiplicative_expression
343 | multiplicative_expression '*' cast_expression
345 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
346 $$->const_int_set = TRUE;
347 $$->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 if ($3->const_int != 0) {
354 $$->const_int = $1->const_int / $3->const_int;
357 | multiplicative_expression '%' cast_expression
359 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
360 $$->const_int_set = TRUE;
361 if ($3->const_int != 0) {
362 $$->const_int = $1->const_int % $3->const_int;
368 : multiplicative_expression
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;
375 | additive_expression '-' multiplicative_expression
377 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
378 $$->const_int_set = TRUE;
379 $$->const_int = $1->const_int - $3->const_int;
384 : additive_expression
385 | shift_expression SL additive_expression
387 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
388 $$->const_int_set = TRUE;
389 $$->const_int = $1->const_int << $3->const_int;
391 /* assume this is a bitfield/flags declaration
392 * if a left shift operator is sued in an enum value
393 * This mimics the glib-mkenum behavior.
397 | shift_expression SR additive_expression
399 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
400 $$->const_int_set = TRUE;
401 $$->const_int = $1->const_int >> $3->const_int;
405 relational_expression
407 | relational_expression '<' 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 '>' shift_expression
415 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
416 $$->const_int_set = TRUE;
417 $$->const_int = $1->const_int > $3->const_int;
419 | relational_expression LTEQ shift_expression
421 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
422 $$->const_int_set = TRUE;
423 $$->const_int = $1->const_int <= $3->const_int;
425 | relational_expression GTEQ shift_expression
427 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
428 $$->const_int_set = TRUE;
429 $$->const_int = $1->const_int >= $3->const_int;
434 : relational_expression
435 | equality_expression EQ relational_expression
437 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
438 $$->const_int_set = TRUE;
439 $$->const_int = $1->const_int == $3->const_int;
441 | equality_expression NOTEQ relational_expression
443 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
444 $$->const_int_set = TRUE;
445 $$->const_int = $1->const_int != $3->const_int;
450 : equality_expression
451 | and_expression '&' equality_expression
453 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
454 $$->const_int_set = TRUE;
455 $$->const_int = $1->const_int & $3->const_int;
459 exclusive_or_expression
461 | exclusive_or_expression '^' and_expression
463 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
464 $$->const_int_set = TRUE;
465 $$->const_int = $1->const_int ^ $3->const_int;
469 inclusive_or_expression
470 : exclusive_or_expression
471 | inclusive_or_expression '|' exclusive_or_expression
473 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
474 $$->const_int_set = TRUE;
475 $$->const_int = $1->const_int | $3->const_int;
479 logical_and_expression
480 : inclusive_or_expression
481 | logical_and_expression ANDAND inclusive_or_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 logical_or_expression
492 : logical_and_expression
493 | logical_or_expression OROR logical_and_expression
495 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST);
496 $$->const_int_set = TRUE;
498 gi_source_symbol_get_const_boolean ($1) ||
499 gi_source_symbol_get_const_boolean ($3);
503 conditional_expression
504 : logical_or_expression
505 | logical_or_expression '?' expression ':' conditional_expression
507 $$ = gi_source_symbol_get_const_boolean ($1) ? $3 : $5;
511 assignment_expression
512 : conditional_expression
513 | unary_expression assignment_operator assignment_expression
515 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
534 : assignment_expression
535 | expression ',' assignment_expression
537 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
542 : conditional_expression
545 /* A.2.2 Declarations. */
548 : declaration_specifiers init_declarator_list ';'
551 for (l = $2; l != NULL; l = l->next) {
552 GISourceSymbol *sym = l->data;
553 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
554 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF) {
555 sym->type = CSYMBOL_TYPE_TYPEDEF;
556 } else if (sym->base_type->type == CTYPE_FUNCTION) {
557 sym->type = CSYMBOL_TYPE_FUNCTION;
559 sym->type = CSYMBOL_TYPE_OBJECT;
561 gi_source_scanner_add_symbol (scanner, sym);
562 gi_source_symbol_unref (sym);
566 | declaration_specifiers ';'
572 declaration_specifiers
573 : storage_class_specifier declaration_specifiers
576 $$->storage_class_specifier |= $1;
578 | storage_class_specifier
580 $$ = gi_source_type_new (CTYPE_INVALID);
581 $$->storage_class_specifier |= $1;
583 | type_specifier declaration_specifiers
586 /* combine basic types like unsigned int and long long */
587 if ($$->type == CTYPE_BASIC_TYPE && $2->type == CTYPE_BASIC_TYPE) {
588 char *name = g_strdup_printf ("%s %s", $$->name, $2->name);
597 | type_qualifier declaration_specifiers
600 $$->type_qualifier |= $1;
604 $$ = gi_source_type_new (CTYPE_INVALID);
605 $$->type_qualifier |= $1;
607 | function_specifier declaration_specifiers
610 $$->function_specifier |= $1;
614 $$ = gi_source_type_new (CTYPE_INVALID);
615 $$->function_specifier |= $1;
622 $$ = g_list_append (NULL, $1);
624 | init_declarator_list ',' init_declarator
626 $$ = g_list_append ($1, $3);
632 | declarator '=' initializer
635 storage_class_specifier
638 $$ = STORAGE_CLASS_TYPEDEF;
642 $$ = STORAGE_CLASS_EXTERN;
646 $$ = STORAGE_CLASS_STATIC;
650 $$ = STORAGE_CLASS_AUTO;
654 $$ = STORAGE_CLASS_REGISTER;
661 $$ = gi_source_type_new (CTYPE_VOID);
665 $$ = gi_source_basic_type_new ("char");
669 $$ = gi_source_basic_type_new ("short");
673 $$ = gi_source_basic_type_new ("int");
677 $$ = gi_source_basic_type_new ("long");
681 $$ = gi_source_basic_type_new ("float");
685 $$ = gi_source_basic_type_new ("double");
689 $$ = gi_source_basic_type_new ("signed");
693 $$ = gi_source_basic_type_new ("unsigned");
697 $$ = gi_source_basic_type_new ("bool");
699 | struct_or_union_specifier
703 $$ = gi_source_typedef_new ($1);
708 struct_or_union_specifier
709 : struct_or_union identifier_or_typedef_name '{' struct_declaration_list '}'
715 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
716 if ($$->type == CTYPE_STRUCT) {
717 sym->type = CSYMBOL_TYPE_STRUCT;
718 } else if ($$->type == CTYPE_UNION) {
719 sym->type = CSYMBOL_TYPE_UNION;
721 g_assert_not_reached ();
723 sym->ident = g_strdup ($$->name);
724 sym->base_type = gi_source_type_copy ($$);
725 gi_source_scanner_add_symbol (scanner, sym);
726 gi_source_symbol_unref (sym);
728 | struct_or_union '{' struct_declaration_list '}'
733 | struct_or_union identifier_or_typedef_name
743 $$ = gi_source_struct_new (NULL);
747 $$ = gi_source_union_new (NULL);
751 struct_declaration_list
753 | struct_declaration_list struct_declaration
755 $$ = g_list_concat ($1, $2);
760 : specifier_qualifier_list struct_declarator_list ';'
764 for (l = $2; l != NULL; l = l->next)
766 GISourceSymbol *sym = l->data;
767 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF)
768 sym->type = CSYMBOL_TYPE_TYPEDEF;
770 sym->type = CSYMBOL_TYPE_MEMBER;
771 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
772 $$ = g_list_append ($$, sym);
778 specifier_qualifier_list
779 : type_specifier specifier_qualifier_list
785 | type_qualifier specifier_qualifier_list
788 $$->type_qualifier |= $1;
792 $$ = gi_source_type_new (CTYPE_INVALID);
793 $$->type_qualifier |= $1;
797 struct_declarator_list
800 $$ = g_list_append (NULL, $1);
802 | struct_declarator_list ',' struct_declarator
804 $$ = g_list_append ($1, $3);
809 : /* empty, support for anonymous structs and unions */
811 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
814 | ':' constant_expression
816 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
818 | declarator ':' constant_expression
821 if ($3->const_int_set) {
822 $$->const_int_set = TRUE;
823 $$->const_int = $3->const_int;
829 : ENUM identifier_or_typedef_name '{' enumerator_list '}'
831 $$ = gi_source_enum_new ($2);
833 $$->is_bitfield = is_bitfield;
834 last_enum_value = -1;
836 | ENUM '{' enumerator_list '}'
838 $$ = gi_source_enum_new (NULL);
840 $$->is_bitfield = is_bitfield;
841 last_enum_value = -1;
843 | ENUM identifier_or_typedef_name '{' enumerator_list ',' '}'
845 $$ = gi_source_enum_new ($2);
847 $$->is_bitfield = is_bitfield;
848 last_enum_value = -1;
850 | ENUM '{' enumerator_list ',' '}'
852 $$ = gi_source_enum_new (NULL);
854 $$->is_bitfield = is_bitfield;
855 last_enum_value = -1;
857 | ENUM identifier_or_typedef_name
859 $$ = gi_source_enum_new ($2);
866 /* reset flag before the first enum value */
871 $$ = g_list_append (NULL, $2);
873 | enumerator_list ',' enumerator
875 $$ = g_list_append ($1, $3);
882 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
884 $$->const_int_set = TRUE;
885 $$->const_int = ++last_enum_value;
886 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
888 | identifier '=' constant_expression
890 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT);
892 $$->const_int_set = TRUE;
893 $$->const_int = $3->const_int;
894 last_enum_value = $$->const_int;
895 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
902 $$ = TYPE_QUALIFIER_CONST;
906 $$ = TYPE_QUALIFIER_RESTRICT;
910 $$ = TYPE_QUALIFIER_EXTENSION;
914 $$ = TYPE_QUALIFIER_VOLATILE;
921 $$ = FUNCTION_INLINE;
926 : pointer direct_declarator
929 gi_source_symbol_merge_type ($$, $1);
937 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
944 | direct_declarator '[' assignment_expression ']'
947 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
949 | direct_declarator '[' ']'
952 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
954 | direct_declarator '(' parameter_list ')'
956 GISourceType *func = gi_source_function_new ();
957 // ignore (void) parameter list
958 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
959 func->child_list = $3;
962 gi_source_symbol_merge_type ($$, func);
964 | direct_declarator '(' identifier_list ')'
966 GISourceType *func = gi_source_function_new ();
967 func->child_list = $3;
969 gi_source_symbol_merge_type ($$, func);
971 | direct_declarator '(' ')'
973 GISourceType *func = gi_source_function_new ();
975 gi_source_symbol_merge_type ($$, func);
980 : '*' type_qualifier_list
982 $$ = gi_source_pointer_new (NULL);
983 $$->type_qualifier = $2;
987 $$ = gi_source_pointer_new (NULL);
989 | '*' type_qualifier_list pointer
991 $$ = gi_source_pointer_new ($3);
992 $$->type_qualifier = $2;
996 $$ = gi_source_pointer_new ($2);
1002 | type_qualifier_list type_qualifier
1009 : parameter_declaration
1011 $$ = g_list_append (NULL, $1);
1013 | parameter_list ',' parameter_declaration
1015 $$ = g_list_append ($1, $3);
1019 parameter_declaration
1020 : declaration_specifiers declarator
1023 gi_source_symbol_merge_type ($$, $1);
1025 | declaration_specifiers abstract_declarator
1028 gi_source_symbol_merge_type ($$, $1);
1030 | declaration_specifiers
1032 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1037 $$ = gi_source_symbol_new (CSYMBOL_TYPE_ELLIPSIS);
1044 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1046 $$ = g_list_append (NULL, sym);
1048 | identifier_list ',' identifier
1050 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1052 $$ = g_list_append ($1, sym);
1057 : specifier_qualifier_list
1058 | specifier_qualifier_list abstract_declarator
1064 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1065 gi_source_symbol_merge_type ($$, $1);
1067 | direct_abstract_declarator
1068 | pointer direct_abstract_declarator
1071 gi_source_symbol_merge_type ($$, $1);
1075 direct_abstract_declarator
1076 : '(' abstract_declarator ')'
1082 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1083 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1085 | '[' assignment_expression ']'
1087 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1088 gi_source_symbol_merge_type ($$, gi_source_array_new ($2));
1090 | direct_abstract_declarator '[' ']'
1093 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1095 | direct_abstract_declarator '[' assignment_expression ']'
1098 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
1102 GISourceType *func = gi_source_function_new ();
1103 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1104 gi_source_symbol_merge_type ($$, func);
1106 | '(' parameter_list ')'
1108 GISourceType *func = gi_source_function_new ();
1109 // ignore (void) parameter list
1110 if ($2 != NULL && ($2->next != NULL || ((GISourceSymbol *) $2->data)->base_type->type != CTYPE_VOID)) {
1111 func->child_list = $2;
1113 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID);
1114 gi_source_symbol_merge_type ($$, func);
1116 | direct_abstract_declarator '(' ')'
1118 GISourceType *func = gi_source_function_new ();
1120 gi_source_symbol_merge_type ($$, func);
1122 | direct_abstract_declarator '(' parameter_list ')'
1124 GISourceType *func = gi_source_function_new ();
1125 // ignore (void) parameter list
1126 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1127 func->child_list = $3;
1130 gi_source_symbol_merge_type ($$, func);
1137 $$ = g_strdup (yytext);
1142 : assignment_expression
1143 | '{' initializer_list '}'
1144 | '{' initializer_list ',' '}'
1149 | initializer_list ',' initializer
1152 /* A.2.3 Statements. */
1156 | compound_statement
1157 | expression_statement
1158 | selection_statement
1159 | iteration_statement
1164 : identifier_or_typedef_name ':' statement
1165 | CASE constant_expression ':' statement
1166 | DEFAULT ':' statement
1171 | '{' block_item_list '}'
1176 | block_item_list block_item
1184 expression_statement
1190 : IF '(' expression ')' statement
1191 | IF '(' expression ')' statement ELSE statement
1192 | SWITCH '(' expression ')' statement
1196 : WHILE '(' expression ')' statement
1197 | DO statement WHILE '(' expression ')' ';'
1198 | FOR '(' ';' ';' ')' statement
1199 | FOR '(' expression ';' ';' ')' statement
1200 | FOR '(' ';' expression ';' ')' statement
1201 | FOR '(' expression ';' expression ';' ')' statement
1202 | FOR '(' ';' ';' expression ')' statement
1203 | FOR '(' expression ';' ';' expression ')' statement
1204 | FOR '(' ';' expression ';' expression ')' statement
1205 | FOR '(' expression ';' expression ';' expression ')' statement
1209 : GOTO identifier_or_typedef_name ';'
1213 | RETURN expression ';'
1216 /* A.2.4 External definitions. */
1219 : external_declaration
1220 | translation_unit external_declaration
1223 external_declaration
1224 : function_definition
1230 : declaration_specifiers declarator declaration_list compound_statement
1231 | declaration_specifiers declarator compound_statement
1236 | declaration_list declaration
1244 $$ = g_strdup (yytext + strlen ("#define "));
1251 $$ = g_strdup (yytext + strlen ("#define "));
1255 function_macro_define
1256 : function_macro '(' identifier_list ')'
1260 : object_macro constant_expression
1262 if ($2->const_int_set || $2->const_double_set || $2->const_string != NULL) {
1264 gi_source_scanner_add_symbol (scanner, $2);
1265 gi_source_symbol_unref ($2);
1271 : function_macro_define
1272 | object_macro_define
1278 yyerror (GISourceScanner *scanner, const char *s)
1280 /* ignore errors while doing a macro scan as not all object macros
1281 * have valid expressions */
1282 if (!scanner->macro_scan)
1284 fprintf(stderr, "%s:%d: %s\n",
1285 scanner->current_filename, lineno, s);
1290 eat_hspace (FILE * f)
1297 while (c == ' ' || c == '\t');
1302 eat_line (FILE * f, int c)
1304 while (c != EOF && c != '\n')
1311 if (c == ' ' || c == '\t')
1320 read_identifier (FILE * f, int c, char **identifier)
1322 GString *id = g_string_new ("");
1323 while (g_ascii_isalnum (c) || c == '_')
1325 g_string_append_c (id, c);
1328 *identifier = g_string_free (id, FALSE);
1333 gi_source_scanner_parse_macros (GISourceScanner *scanner, GList *filenames)
1335 GError *error = NULL;
1336 char *tmp_name = NULL;
1338 fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error),
1340 g_unlink (tmp_name);
1343 for (l = filenames; l != NULL; l = l->next)
1345 FILE *f = fopen (l->data, "r");
1348 GString *define_line;
1350 gboolean error_line = FALSE;
1351 int c = eat_hspace (f);
1357 c = eat_line (f, c);
1362 /* print current location */
1363 str = g_strescape (l->data, "");
1364 fprintf (fmacros, "# %d \"%s\"\n", line, str);
1368 c = read_identifier (f, c, &str);
1369 if (strcmp (str, "define") != 0 || (c != ' ' && c != '\t'))
1373 c = eat_line (f, c);
1379 c = read_identifier (f, c, &str);
1380 if (strlen (str) == 0 || (c != ' ' && c != '\t' && c != '('))
1384 c = eat_line (f, c);
1388 define_line = g_string_new ("#define ");
1389 g_string_append (define_line, str);
1395 g_string_append_c (define_line, c);
1397 if (c == EOF || c == '\n')
1405 g_string_free (define_line, TRUE);
1407 c = eat_line (f, c);
1412 g_assert (c == ')');
1413 g_string_append_c (define_line, c);
1416 /* found function-like macro */
1417 fprintf (fmacros, "%s\n", define_line->str);
1419 g_string_free (define_line, TRUE);
1420 /* ignore rest of line */
1421 c = eat_line (f, c);
1425 if (c != ' ' && c != '\t')
1427 g_string_free (define_line, TRUE);
1429 c = eat_line (f, c);
1433 while (c != EOF && c != '\n')
1435 g_string_append_c (define_line, c);
1442 /* fold lines when seeing backslash new-line sequence */
1447 g_string_append_c (define_line, '\\');
1452 /* found object-like macro */
1453 fprintf (fmacros, "%s\n", define_line->str);
1455 c = eat_line (f, c);
1463 gi_source_scanner_parse_file (scanner, fmacros);
1467 gi_source_scanner_parse_file (GISourceScanner *scanner, FILE *file)
1469 g_return_val_if_fail (file != NULL, FALSE);
1471 const_table = g_hash_table_new_full (g_str_hash, g_str_equal,
1472 g_free, (GDestroyNotify)gi_source_symbol_unref);
1478 g_hash_table_destroy (const_table);
1487 gi_source_scanner_lex_filename (GISourceScanner *scanner, const gchar *filename)
1489 yyin = fopen (filename, "r");
1491 while (yylex (scanner) != YYEOF)