1 /* GObject introspection: C parser -*- indent-tabs-mode: t; tab-width: 8 -*-
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"
41 extern char linebuf[2000];
44 extern int yylex (GISourceScanner *scanner);
45 static void yyerror (GISourceScanner *scanner, const char *str);
47 extern void ctype_free (GISourceType * type);
49 static int last_enum_value = -1;
50 static gboolean is_bitfield;
51 static GHashTable *const_table = NULL;
54 * parse_c_string_literal:
55 * @str: A string containing a C string literal
57 * Based on g_strcompress(), but also handles
58 * hexadecimal escapes.
61 parse_c_string_literal (const char *str)
63 const gchar *p = str, *num;
64 gchar *dest = g_malloc (strlen (str) + 1);
75 g_warning ("parse_c_string_literal: trailing \\");
77 case '0': case '1': case '2': case '3': case '4':
78 case '5': case '6': case '7':
81 while ((p < num + 3) && (*p >= '0') && (*p <= '7'))
83 *q = (*q * 8) + (*p - '0');
93 while ((p < num + 2) && (g_ascii_isxdigit(*p)))
95 *q = (*q * 16) + g_ascii_xdigit_value(*p);
116 default: /* Also handles \" and \\ */
138 update_skipping (GISourceScanner *scanner)
141 for (l = scanner->conditionals.head; l != NULL; l = g_list_next (l))
143 if (GPOINTER_TO_INT (l->data) == NOT_GI_SCANNER)
145 scanner->skipping = TRUE;
150 scanner->skipping = FALSE;
154 push_conditional (GISourceScanner *scanner,
157 g_assert (type != 0);
158 g_queue_push_head (&scanner->conditionals, GINT_TO_POINTER (type));
162 pop_conditional (GISourceScanner *scanner)
164 gint type = GPOINTER_TO_INT (g_queue_pop_head (&scanner->conditionals));
168 gchar *filename = g_file_get_path (scanner->current_file);
169 fprintf (stderr, "%s:%d: mismatched %s", filename, lineno, yytext);
177 warn_if_cond_has_gi_scanner (GISourceScanner *scanner,
180 /* Some other conditional that is not __GI_SCANNER__ */
181 if (strstr (text, "__GI_SCANNER__"))
183 gchar *filename = g_file_get_path (scanner->current_file);
184 fprintf (stderr, "%s:%d: the __GI_SCANNER__ constant should only be used with simple #ifdef or #endif: %s",
185 filename, lineno, text);
191 toggle_conditional (GISourceScanner *scanner)
193 switch (pop_conditional (scanner))
196 push_conditional (scanner, NOT_GI_SCANNER);
199 push_conditional (scanner, FOR_GI_SCANNER);
204 push_conditional (scanner, IRRELEVANT);
215 GISourceSymbol *symbol;
217 StorageClassSpecifier storage_class_specifier;
218 TypeQualifier type_qualifier;
219 FunctionSpecifier function_specifier;
220 UnaryOperator unary_operator;
223 %parse-param { GISourceScanner* scanner }
224 %lex-param { GISourceScanner* scanner }
226 %token <str> IDENTIFIER "identifier"
227 %token <str> TYPEDEF_NAME "typedef-name"
229 %token INTEGER FLOATING BOOLEAN CHARACTER STRING
231 %token INTL_CONST INTUL_CONST
232 %token ELLIPSIS ADDEQ SUBEQ MULEQ DIVEQ MODEQ XOREQ ANDEQ OREQ SL SR
233 %token SLEQ SREQ EQ NOTEQ LTEQ GTEQ ANDAND OROR PLUSPLUS MINUSMINUS ARROW
235 %token AUTO BOOL BREAK CASE CHAR CONST CONTINUE DEFAULT DO DOUBLE ELSE ENUM
236 %token EXTENSION EXTERN FLOAT FOR GOTO IF INLINE INT LONG REGISTER RESTRICT
237 %token RETURN SHORT SIGNED SIZEOF STATIC STRUCT SWITCH TYPEDEF UNION UNSIGNED
238 %token VOID VOLATILE WHILE
240 %token FUNCTION_MACRO OBJECT_MACRO
241 %token IFDEF_GI_SCANNER IFNDEF_GI_SCANNER
242 %token IFDEF_COND IFNDEF_COND IF_COND ELIF_COND ELSE_COND ENDIF_COND
244 %start translation_unit
246 %type <ctype> declaration_specifiers
247 %type <ctype> enum_specifier
248 %type <ctype> pointer
249 %type <ctype> specifier_qualifier_list
250 %type <ctype> type_name
251 %type <ctype> struct_or_union
252 %type <ctype> struct_or_union_specifier
253 %type <ctype> type_specifier
254 %type <str> identifier
255 %type <str> typedef_name
256 %type <str> identifier_or_typedef_name
257 %type <symbol> abstract_declarator
258 %type <symbol> init_declarator
259 %type <symbol> declarator
260 %type <symbol> enumerator
261 %type <symbol> direct_abstract_declarator
262 %type <symbol> direct_declarator
263 %type <symbol> parameter_declaration
264 %type <symbol> struct_declarator
265 %type <list> enumerator_list
266 %type <list> identifier_list
267 %type <list> init_declarator_list
268 %type <list> parameter_list
269 %type <list> struct_declaration
270 %type <list> struct_declaration_list
271 %type <list> struct_declarator_list
272 %type <storage_class_specifier> storage_class_specifier
273 %type <type_qualifier> type_qualifier
274 %type <type_qualifier> type_qualifier_list
275 %type <function_specifier> function_specifier
276 %type <symbol> expression
277 %type <symbol> constant_expression
278 %type <symbol> conditional_expression
279 %type <symbol> logical_and_expression
280 %type <symbol> logical_or_expression
281 %type <symbol> inclusive_or_expression
282 %type <symbol> exclusive_or_expression
283 %type <symbol> multiplicative_expression
284 %type <symbol> additive_expression
285 %type <symbol> shift_expression
286 %type <symbol> relational_expression
287 %type <symbol> equality_expression
288 %type <symbol> and_expression
289 %type <symbol> cast_expression
290 %type <symbol> assignment_expression
291 %type <symbol> unary_expression
292 %type <symbol> postfix_expression
293 %type <symbol> primary_expression
294 %type <unary_operator> unary_operator
295 %type <str> function_macro
296 %type <str> object_macro
297 %type <symbol> strings
301 /* A.2.1 Expressions. */
306 $$ = g_hash_table_lookup (const_table, $1);
308 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
310 $$ = gi_source_symbol_ref ($$);
317 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
318 $$->const_int_set = TRUE;
319 if (g_str_has_prefix (yytext, "0x") && strlen (yytext) > 2) {
320 value = g_ascii_strtoull (yytext + 2, &rest, 16);
321 } else if (g_str_has_prefix (yytext, "0") && strlen (yytext) > 1) {
322 value = g_ascii_strtoull (yytext + 1, &rest, 8);
324 value = g_ascii_strtoull (yytext, &rest, 10);
326 $$->const_int = value;
327 $$->const_int_is_unsigned = (rest && (rest[0] == 'U'));
331 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
332 $$->const_boolean_set = TRUE;
333 $$->const_boolean = g_ascii_strcasecmp (yytext, "true") == 0 ? TRUE : FALSE;
337 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
338 $$->const_int_set = TRUE;
339 $$->const_int = g_utf8_get_char(yytext + 1);
343 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
344 $$->const_double_set = TRUE;
345 $$->const_double = 0.0;
346 sscanf (yytext, "%lf", &($$->const_double));
353 | EXTENSION '(' '{' block_item_list '}' ')'
355 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
359 /* concatenate adjacent string literal tokens */
363 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
364 yytext[strlen (yytext) - 1] = '\0';
365 $$->const_string = parse_c_string_literal (yytext + 1);
366 if (!g_utf8_validate ($$->const_string, -1, NULL))
369 g_warning ("Ignoring non-UTF-8 constant string \"%s\"", yytext + 1);
371 g_free($$->const_string);
372 $$->const_string = NULL;
378 char *strings, *string2;
380 yytext[strlen (yytext) - 1] = '\0';
381 string2 = parse_c_string_literal (yytext + 1);
382 strings = g_strconcat ($$->const_string, string2, NULL);
383 g_free ($$->const_string);
385 $$->const_string = strings;
392 $$ = g_strdup (yytext);
396 identifier_or_typedef_name
403 | postfix_expression '[' expression ']'
405 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
407 | postfix_expression '(' argument_expression_list ')'
409 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
411 | postfix_expression '(' ')'
413 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
415 | postfix_expression '.' identifier_or_typedef_name
417 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
419 | postfix_expression ARROW identifier_or_typedef_name
421 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
423 | postfix_expression PLUSPLUS
425 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
427 | postfix_expression MINUSMINUS
429 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
433 argument_expression_list
434 : assignment_expression
435 | argument_expression_list ',' assignment_expression
440 | PLUSPLUS unary_expression
442 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
444 | MINUSMINUS unary_expression
446 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
448 | unary_operator cast_expression
455 $$ = gi_source_symbol_copy ($2);
456 $$->const_int = -$2->const_int;
458 case UNARY_BITWISE_COMPLEMENT:
459 $$ = gi_source_symbol_copy ($2);
460 $$->const_int = ~$2->const_int;
462 case UNARY_LOGICAL_NEGATION:
463 $$ = gi_source_symbol_copy ($2);
464 $$->const_int = !gi_source_symbol_get_const_boolean ($2);
467 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
471 | INTL_CONST '(' unary_expression ')'
474 if ($$->const_int_set) {
475 $$->base_type = gi_source_basic_type_new ($$->const_int_is_unsigned ? "guint64" : "gint64");
478 | INTUL_CONST '(' unary_expression ')'
481 if ($$->const_int_set) {
482 $$->base_type = gi_source_basic_type_new ("guint64");
485 | SIZEOF unary_expression
487 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
489 | SIZEOF '(' type_name ')'
492 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
499 $$ = UNARY_ADDRESS_OF;
503 $$ = UNARY_POINTER_INDIRECTION;
515 $$ = UNARY_BITWISE_COMPLEMENT;
519 $$ = UNARY_LOGICAL_NEGATION;
525 | '(' type_name ')' cast_expression
528 if ($$->const_int_set || $$->const_double_set || $$->const_string != NULL) {
536 multiplicative_expression
538 | multiplicative_expression '*' cast_expression
540 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
541 $$->const_int_set = TRUE;
542 $$->const_int = $1->const_int * $3->const_int;
544 | multiplicative_expression '/' cast_expression
546 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
547 $$->const_int_set = TRUE;
548 if ($3->const_int != 0) {
549 $$->const_int = $1->const_int / $3->const_int;
552 | multiplicative_expression '%' cast_expression
554 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
555 $$->const_int_set = TRUE;
556 if ($3->const_int != 0) {
557 $$->const_int = $1->const_int % $3->const_int;
563 : multiplicative_expression
564 | additive_expression '+' multiplicative_expression
566 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
567 $$->const_int_set = TRUE;
568 $$->const_int = $1->const_int + $3->const_int;
570 | additive_expression '-' multiplicative_expression
572 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
573 $$->const_int_set = TRUE;
574 $$->const_int = $1->const_int - $3->const_int;
579 : additive_expression
580 | shift_expression SL additive_expression
582 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
583 $$->const_int_set = TRUE;
584 $$->const_int = $1->const_int << $3->const_int;
586 /* assume this is a bitfield/flags declaration
587 * if a left shift operator is sued in an enum value
588 * This mimics the glib-mkenum behavior.
592 | shift_expression SR additive_expression
594 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
595 $$->const_int_set = TRUE;
596 $$->const_int = $1->const_int >> $3->const_int;
600 relational_expression
602 | relational_expression '<' shift_expression
604 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
605 $$->const_int_set = TRUE;
606 $$->const_int = $1->const_int < $3->const_int;
608 | relational_expression '>' shift_expression
610 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
611 $$->const_int_set = TRUE;
612 $$->const_int = $1->const_int > $3->const_int;
614 | relational_expression LTEQ shift_expression
616 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
617 $$->const_int_set = TRUE;
618 $$->const_int = $1->const_int <= $3->const_int;
620 | relational_expression GTEQ shift_expression
622 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
623 $$->const_int_set = TRUE;
624 $$->const_int = $1->const_int >= $3->const_int;
629 : relational_expression
630 | equality_expression EQ relational_expression
632 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
633 $$->const_int_set = TRUE;
634 $$->const_int = $1->const_int == $3->const_int;
636 | equality_expression NOTEQ relational_expression
638 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
639 $$->const_int_set = TRUE;
640 $$->const_int = $1->const_int != $3->const_int;
645 : equality_expression
646 | and_expression '&' equality_expression
648 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
649 $$->const_int_set = TRUE;
650 $$->const_int = $1->const_int & $3->const_int;
654 exclusive_or_expression
656 | exclusive_or_expression '^' and_expression
658 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
659 $$->const_int_set = TRUE;
660 $$->const_int = $1->const_int ^ $3->const_int;
664 inclusive_or_expression
665 : exclusive_or_expression
666 | inclusive_or_expression '|' exclusive_or_expression
668 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
669 $$->const_int_set = TRUE;
670 $$->const_int = $1->const_int | $3->const_int;
674 logical_and_expression
675 : inclusive_or_expression
676 | logical_and_expression ANDAND inclusive_or_expression
678 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
679 $$->const_int_set = TRUE;
681 gi_source_symbol_get_const_boolean ($1) &&
682 gi_source_symbol_get_const_boolean ($3);
686 logical_or_expression
687 : logical_and_expression
688 | logical_or_expression OROR logical_and_expression
690 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_file, lineno);
691 $$->const_int_set = TRUE;
693 gi_source_symbol_get_const_boolean ($1) ||
694 gi_source_symbol_get_const_boolean ($3);
698 conditional_expression
699 : logical_or_expression
700 | logical_or_expression '?' expression ':' expression
702 $$ = gi_source_symbol_get_const_boolean ($1) ? $3 : $5;
706 assignment_expression
707 : conditional_expression
708 | unary_expression assignment_operator assignment_expression
710 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
729 : assignment_expression
730 | expression ',' assignment_expression
731 | EXTENSION expression
733 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
738 : conditional_expression
741 /* A.2.2 Declarations. */
744 : declaration_specifiers init_declarator_list ';'
747 for (l = $2; l != NULL; l = l->next) {
748 GISourceSymbol *sym = l->data;
749 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
750 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF) {
751 sym->type = CSYMBOL_TYPE_TYPEDEF;
752 } else if (sym->base_type->type == CTYPE_FUNCTION) {
753 sym->type = CSYMBOL_TYPE_FUNCTION;
755 sym->type = CSYMBOL_TYPE_OBJECT;
757 gi_source_scanner_add_symbol (scanner, sym);
758 gi_source_symbol_unref (sym);
762 | declaration_specifiers ';'
768 declaration_specifiers
769 : storage_class_specifier declaration_specifiers
772 $$->storage_class_specifier |= $1;
774 | storage_class_specifier
776 $$ = gi_source_type_new (CTYPE_INVALID);
777 $$->storage_class_specifier |= $1;
779 | type_specifier declaration_specifiers
782 /* combine basic types like unsigned int and long long */
783 if ($$->type == CTYPE_BASIC_TYPE && $2->type == CTYPE_BASIC_TYPE) {
784 char *name = g_strdup_printf ("%s %s", $$->name, $2->name);
793 | type_qualifier declaration_specifiers
796 $$->type_qualifier |= $1;
800 $$ = gi_source_type_new (CTYPE_INVALID);
801 $$->type_qualifier |= $1;
803 | function_specifier declaration_specifiers
806 $$->function_specifier |= $1;
810 $$ = gi_source_type_new (CTYPE_INVALID);
811 $$->function_specifier |= $1;
818 $$ = g_list_append (NULL, $1);
820 | init_declarator_list ',' init_declarator
822 $$ = g_list_append ($1, $3);
828 | declarator '=' initializer
831 storage_class_specifier
834 $$ = STORAGE_CLASS_TYPEDEF;
838 $$ = STORAGE_CLASS_EXTERN;
842 $$ = STORAGE_CLASS_STATIC;
846 $$ = STORAGE_CLASS_AUTO;
850 $$ = STORAGE_CLASS_REGISTER;
857 $$ = gi_source_type_new (CTYPE_VOID);
861 $$ = gi_source_basic_type_new ("char");
865 $$ = gi_source_basic_type_new ("short");
869 $$ = gi_source_basic_type_new ("int");
873 $$ = gi_source_basic_type_new ("long");
877 $$ = gi_source_basic_type_new ("float");
881 $$ = gi_source_basic_type_new ("double");
885 $$ = gi_source_basic_type_new ("signed");
889 $$ = gi_source_basic_type_new ("unsigned");
893 $$ = gi_source_basic_type_new ("bool");
895 | struct_or_union_specifier
899 $$ = gi_source_typedef_new ($1);
904 struct_or_union_specifier
905 : struct_or_union identifier_or_typedef_name '{' struct_declaration_list '}'
912 sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
913 if ($$->type == CTYPE_STRUCT) {
914 sym->type = CSYMBOL_TYPE_STRUCT;
915 } else if ($$->type == CTYPE_UNION) {
916 sym->type = CSYMBOL_TYPE_UNION;
918 g_assert_not_reached ();
920 sym->ident = g_strdup ($$->name);
921 sym->base_type = gi_source_type_copy ($$);
922 gi_source_scanner_add_symbol (scanner, sym);
923 gi_source_symbol_unref (sym);
925 | struct_or_union '{' struct_declaration_list '}'
930 | struct_or_union identifier_or_typedef_name
940 scanner->private = FALSE;
941 $$ = gi_source_struct_new (NULL);
945 scanner->private = FALSE;
946 $$ = gi_source_union_new (NULL);
950 struct_declaration_list
952 | struct_declaration_list struct_declaration
954 $$ = g_list_concat ($1, $2);
959 : specifier_qualifier_list struct_declarator_list ';'
963 for (l = $2; l != NULL; l = l->next)
965 GISourceSymbol *sym = l->data;
966 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF)
967 sym->type = CSYMBOL_TYPE_TYPEDEF;
969 sym->type = CSYMBOL_TYPE_MEMBER;
970 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
971 sym->private = scanner->private;
972 $$ = g_list_append ($$, sym);
978 specifier_qualifier_list
979 : type_specifier specifier_qualifier_list
985 | type_qualifier specifier_qualifier_list
988 $$->type_qualifier |= $1;
992 $$ = gi_source_type_new (CTYPE_INVALID);
993 $$->type_qualifier |= $1;
997 struct_declarator_list
1000 $$ = g_list_append (NULL, $1);
1002 | struct_declarator_list ',' struct_declarator
1004 $$ = g_list_append ($1, $3);
1009 : /* empty, support for anonymous structs and unions */
1011 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
1014 | ':' constant_expression
1016 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
1018 | declarator ':' constant_expression
1021 if ($3->const_int_set) {
1022 $$->const_int_set = TRUE;
1023 $$->const_int = $3->const_int;
1029 : enum_keyword identifier_or_typedef_name '{' enumerator_list '}'
1031 $$ = gi_source_enum_new ($2);
1032 $$->child_list = $4;
1033 $$->is_bitfield = is_bitfield || scanner->flags;
1034 last_enum_value = -1;
1036 | enum_keyword '{' enumerator_list '}'
1038 $$ = gi_source_enum_new (NULL);
1039 $$->child_list = $3;
1040 $$->is_bitfield = is_bitfield || scanner->flags;
1041 last_enum_value = -1;
1043 | enum_keyword identifier_or_typedef_name '{' enumerator_list ',' '}'
1045 $$ = gi_source_enum_new ($2);
1046 $$->child_list = $4;
1047 $$->is_bitfield = is_bitfield || scanner->flags;
1048 last_enum_value = -1;
1050 | enum_keyword '{' enumerator_list ',' '}'
1052 $$ = gi_source_enum_new (NULL);
1053 $$->child_list = $3;
1054 $$->is_bitfield = is_bitfield || scanner->flags;
1055 last_enum_value = -1;
1057 | enum_keyword identifier_or_typedef_name
1059 $$ = gi_source_enum_new ($2);
1066 scanner->flags = FALSE;
1067 scanner->private = FALSE;
1074 /* reset flag before the first enum value */
1075 is_bitfield = FALSE;
1079 $2->private = scanner->private;
1080 $$ = g_list_append (NULL, $2);
1082 | enumerator_list ',' enumerator
1084 $3->private = scanner->private;
1085 $$ = g_list_append ($1, $3);
1092 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT, scanner->current_file, lineno);
1094 $$->const_int_set = TRUE;
1095 $$->const_int = ++last_enum_value;
1096 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
1098 | identifier '=' constant_expression
1100 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT, scanner->current_file, lineno);
1102 $$->const_int_set = TRUE;
1103 $$->const_int = $3->const_int;
1104 last_enum_value = $$->const_int;
1105 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
1112 $$ = TYPE_QUALIFIER_CONST;
1116 $$ = TYPE_QUALIFIER_RESTRICT;
1120 $$ = TYPE_QUALIFIER_EXTENSION;
1124 $$ = TYPE_QUALIFIER_VOLATILE;
1131 $$ = FUNCTION_INLINE;
1136 : pointer direct_declarator
1139 gi_source_symbol_merge_type ($$, $1);
1147 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
1150 | '(' declarator ')'
1154 | direct_declarator '[' assignment_expression ']'
1157 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
1159 | direct_declarator '[' ']'
1162 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1164 | direct_declarator '(' parameter_list ')'
1166 GISourceType *func = gi_source_function_new ();
1167 // ignore (void) parameter list
1168 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1169 func->child_list = $3;
1172 gi_source_symbol_merge_type ($$, func);
1174 | direct_declarator '(' identifier_list ')'
1176 GISourceType *func = gi_source_function_new ();
1177 func->child_list = $3;
1179 gi_source_symbol_merge_type ($$, func);
1181 | direct_declarator '(' ')'
1183 GISourceType *func = gi_source_function_new ();
1185 gi_source_symbol_merge_type ($$, func);
1190 : '*' type_qualifier_list
1192 $$ = gi_source_pointer_new (NULL);
1193 $$->type_qualifier = $2;
1197 $$ = gi_source_pointer_new (NULL);
1199 | '*' type_qualifier_list pointer
1201 GISourceType **base = &($3->base_type);
1203 while (*base != NULL) {
1204 base = &((*base)->base_type);
1206 *base = gi_source_pointer_new (NULL);
1207 (*base)->type_qualifier = $2;
1212 GISourceType **base = &($2->base_type);
1214 while (*base != NULL) {
1215 base = &((*base)->base_type);
1217 *base = gi_source_pointer_new (NULL);
1224 | type_qualifier_list type_qualifier
1231 : parameter_declaration
1233 $$ = g_list_append (NULL, $1);
1235 | parameter_list ',' parameter_declaration
1237 $$ = g_list_append ($1, $3);
1241 parameter_declaration
1242 : declaration_specifiers declarator
1245 gi_source_symbol_merge_type ($$, $1);
1247 | declaration_specifiers abstract_declarator
1250 gi_source_symbol_merge_type ($$, $1);
1252 | declaration_specifiers
1254 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
1259 $$ = gi_source_symbol_new (CSYMBOL_TYPE_ELLIPSIS, scanner->current_file, lineno);
1266 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
1268 $$ = g_list_append (NULL, sym);
1270 | identifier_list ',' identifier
1272 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
1274 $$ = g_list_append ($1, sym);
1279 : specifier_qualifier_list
1280 | specifier_qualifier_list abstract_declarator
1286 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
1287 gi_source_symbol_merge_type ($$, $1);
1289 | direct_abstract_declarator
1290 | pointer direct_abstract_declarator
1293 gi_source_symbol_merge_type ($$, $1);
1297 direct_abstract_declarator
1298 : '(' abstract_declarator ')'
1304 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
1305 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1307 | '[' assignment_expression ']'
1309 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
1310 gi_source_symbol_merge_type ($$, gi_source_array_new ($2));
1312 | direct_abstract_declarator '[' ']'
1315 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1317 | direct_abstract_declarator '[' assignment_expression ']'
1320 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
1324 GISourceType *func = gi_source_function_new ();
1325 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
1326 gi_source_symbol_merge_type ($$, func);
1328 | '(' parameter_list ')'
1330 GISourceType *func = gi_source_function_new ();
1331 // ignore (void) parameter list
1332 if ($2 != NULL && ($2->next != NULL || ((GISourceSymbol *) $2->data)->base_type->type != CTYPE_VOID)) {
1333 func->child_list = $2;
1335 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, scanner->current_file, lineno);
1336 gi_source_symbol_merge_type ($$, func);
1338 | direct_abstract_declarator '(' ')'
1340 GISourceType *func = gi_source_function_new ();
1342 gi_source_symbol_merge_type ($$, func);
1344 | direct_abstract_declarator '(' parameter_list ')'
1346 GISourceType *func = gi_source_function_new ();
1347 // ignore (void) parameter list
1348 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1349 func->child_list = $3;
1352 gi_source_symbol_merge_type ($$, func);
1359 $$ = g_strdup (yytext);
1364 : assignment_expression
1365 | '{' initializer_list '}'
1366 | '{' initializer_list ',' '}'
1371 | initializer_list ',' initializer
1374 /* A.2.3 Statements. */
1378 | compound_statement
1379 | expression_statement
1380 | selection_statement
1381 | iteration_statement
1386 : identifier_or_typedef_name ':' statement
1387 | CASE constant_expression ':' statement
1388 | DEFAULT ':' statement
1393 | '{' block_item_list '}'
1398 | block_item_list block_item
1406 expression_statement
1412 : IF '(' expression ')' statement
1413 | IF '(' expression ')' statement ELSE statement
1414 | SWITCH '(' expression ')' statement
1418 : WHILE '(' expression ')' statement
1419 | DO statement WHILE '(' expression ')' ';'
1420 | FOR '(' ';' ';' ')' statement
1421 | FOR '(' expression ';' ';' ')' statement
1422 | FOR '(' ';' expression ';' ')' statement
1423 | FOR '(' expression ';' expression ';' ')' statement
1424 | FOR '(' ';' ';' expression ')' statement
1425 | FOR '(' expression ';' ';' expression ')' statement
1426 | FOR '(' ';' expression ';' expression ')' statement
1427 | FOR '(' expression ';' expression ';' expression ')' statement
1431 : GOTO identifier_or_typedef_name ';'
1435 | RETURN expression ';'
1438 /* A.2.4 External definitions. */
1441 : external_declaration
1442 | translation_unit external_declaration
1445 external_declaration
1446 : function_definition
1452 : declaration_specifiers declarator declaration_list compound_statement
1453 | declaration_specifiers declarator compound_statement
1458 | declaration_list declaration
1466 $$ = g_strdup (yytext + strlen ("#define "));
1473 $$ = g_strdup (yytext + strlen ("#define "));
1477 function_macro_define
1478 : function_macro '(' identifier_list ')'
1482 : object_macro constant_expression
1484 if ($2->const_int_set || $2->const_boolean_set || $2->const_double_set || $2->const_string != NULL) {
1486 gi_source_scanner_add_symbol (scanner, $2);
1487 gi_source_symbol_unref ($2);
1495 push_conditional (scanner, FOR_GI_SCANNER);
1496 update_skipping (scanner);
1500 push_conditional (scanner, NOT_GI_SCANNER);
1501 update_skipping (scanner);
1505 warn_if_cond_has_gi_scanner (scanner, yytext);
1506 push_conditional (scanner, IRRELEVANT);
1510 warn_if_cond_has_gi_scanner (scanner, yytext);
1511 push_conditional (scanner, IRRELEVANT);
1515 warn_if_cond_has_gi_scanner (scanner, yytext);
1516 push_conditional (scanner, IRRELEVANT);
1520 warn_if_cond_has_gi_scanner (scanner, yytext);
1521 pop_conditional (scanner);
1522 push_conditional (scanner, IRRELEVANT);
1523 update_skipping (scanner);
1527 toggle_conditional (scanner);
1528 update_skipping (scanner);
1532 pop_conditional (scanner);
1533 update_skipping (scanner);
1538 : function_macro_define
1539 | object_macro_define
1540 | preproc_conditional
1546 yyerror (GISourceScanner *scanner, const char *s)
1548 /* ignore errors while doing a macro scan as not all object macros
1549 * have valid expressions */
1550 if (!scanner->macro_scan)
1552 fprintf(stderr, "%s:%d: %s in '%s' at '%s'\n",
1553 g_file_get_parse_name (scanner->current_file), lineno, s, linebuf, yytext);
1558 eat_hspace (FILE * f)
1565 while (c == ' ' || c == '\t');
1570 pass_line (FILE * f, int c,
1573 while (c != EOF && c != '\n')
1584 if (c == ' ' || c == '\t')
1593 eat_line (FILE * f, int c)
1595 return pass_line (f, c, NULL);
1599 read_identifier (FILE * f, int c, char **identifier)
1601 GString *id = g_string_new ("");
1602 while (g_ascii_isalnum (c) || c == '_')
1604 g_string_append_c (id, c);
1607 *identifier = g_string_free (id, FALSE);
1612 gi_source_scanner_parse_macros (GISourceScanner *scanner, GList *filenames)
1614 GError *error = NULL;
1615 char *tmp_name = NULL;
1617 fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error),
1620 g_unlink (tmp_name);
1622 for (l = filenames; l != NULL; l = l->next)
1624 FILE *f = fopen (l->data, "r");
1627 GString *define_line;
1629 gboolean error_line = FALSE;
1630 gboolean end_of_word;
1631 int c = eat_hspace (f);
1637 c = eat_line (f, c);
1642 /* print current location */
1643 str = g_strescape (l->data, "");
1644 fprintf (fmacros, "# %d \"%s\"\n", line, str);
1648 c = read_identifier (f, c, &str);
1649 end_of_word = (c == ' ' || c == '\t' || c == '\n' || c == EOF);
1651 (g_str_equal (str, "if") ||
1652 g_str_equal (str, "endif") ||
1653 g_str_equal (str, "ifndef") ||
1654 g_str_equal (str, "ifdef") ||
1655 g_str_equal (str, "else") ||
1656 g_str_equal (str, "elif")))
1658 fprintf (fmacros, "#%s ", str);
1660 c = pass_line (f, c, fmacros);
1664 else if (strcmp (str, "define") != 0 || !end_of_word)
1668 c = eat_line (f, c);
1674 c = read_identifier (f, c, &str);
1675 if (strlen (str) == 0 || (c != ' ' && c != '\t' && c != '('))
1679 c = eat_line (f, c);
1683 define_line = g_string_new ("#define ");
1684 g_string_append (define_line, str);
1690 g_string_append_c (define_line, c);
1692 if (c == EOF || c == '\n')
1700 g_string_free (define_line, TRUE);
1702 c = eat_line (f, c);
1707 g_assert (c == ')');
1708 g_string_append_c (define_line, c);
1711 /* found function-like macro */
1712 fprintf (fmacros, "%s\n", define_line->str);
1714 g_string_free (define_line, TRUE);
1715 /* ignore rest of line */
1716 c = eat_line (f, c);
1720 if (c != ' ' && c != '\t')
1722 g_string_free (define_line, TRUE);
1724 c = eat_line (f, c);
1728 while (c != EOF && c != '\n')
1730 g_string_append_c (define_line, c);
1737 /* fold lines when seeing backslash new-line sequence */
1742 g_string_append_c (define_line, '\\');
1747 /* found object-like macro */
1748 fprintf (fmacros, "%s\n", define_line->str);
1750 c = eat_line (f, c);
1758 gi_source_scanner_parse_file (scanner, fmacros);
1762 gi_source_scanner_parse_file (GISourceScanner *scanner, FILE *file)
1764 g_return_val_if_fail (file != NULL, FALSE);
1766 const_table = g_hash_table_new_full (g_str_hash, g_str_equal,
1767 g_free, (GDestroyNotify)gi_source_symbol_unref);
1773 g_hash_table_destroy (const_table);
1782 gi_source_scanner_lex_filename (GISourceScanner *scanner, const gchar *filename)
1785 yyin = fopen (filename, "r");
1787 while (yylex (scanner) != YYEOF)