Support glib-mkenums comment /*< flags >*/
[platform/upstream/gobject-introspection.git] / giscanner / scannerparser.y
1 /* GObject introspection: C parser
2  *
3  * Copyright (c) 1997 Sandro Sigala  <ssigala@globalnet.it>
4  * Copyright (c) 2007-2008 Jürg Billeter  <j@bitron.ch>
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 %{
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <glib.h>
35 #include <glib/gstdio.h>
36 #include "sourcescanner.h"
37 #include "scannerparser.h"
38
39 extern FILE *yyin;
40 extern int lineno;
41 extern char linebuf[2000];
42 extern char *yytext;
43
44 extern int yylex (GISourceScanner *scanner);
45 static void yyerror (GISourceScanner *scanner, const char *str);
46
47 extern void ctype_free (GISourceType * type);
48
49 static int last_enum_value = -1;
50 static gboolean is_bitfield;
51 static GHashTable *const_table = NULL;
52
53 /**
54  * parse_c_string_literal:
55  * @str: A string containing a C string literal
56  *
57  * Based on g_strcompress(), but also handles
58  * hexadecimal escapes.
59  */
60 static char *
61 parse_c_string_literal (const char *str)
62 {
63   const gchar *p = str, *num;
64   gchar *dest = g_malloc (strlen (str) + 1);
65   gchar *q = dest;
66
67   while (*p)
68     {
69       if (*p == '\\')
70         {
71           p++;
72           switch (*p)
73             {
74             case '\0':
75               g_warning ("parse_c_string_literal: trailing \\");
76               goto out;
77             case '0':  case '1':  case '2':  case '3':  case '4':
78             case '5':  case '6':  case '7':
79               *q = 0;
80               num = p;
81               while ((p < num + 3) && (*p >= '0') && (*p <= '7'))
82                 {
83                   *q = (*q * 8) + (*p - '0');
84                   p++;
85                 }
86               q++;
87               p--;
88               break;
89             case 'x':
90               *q = 0;
91               p++;
92               num = p;
93               while ((p < num + 2) && (g_ascii_isxdigit(*p)))
94                 {
95                   *q = (*q * 16) + g_ascii_xdigit_value(*p);
96                   p++;
97                 }
98               q++;
99               p--;
100               break;
101             case 'b':
102               *q++ = '\b';
103               break;
104             case 'f':
105               *q++ = '\f';
106               break;
107             case 'n':
108               *q++ = '\n';
109               break;
110             case 'r':
111               *q++ = '\r';
112               break;
113             case 't':
114               *q++ = '\t';
115               break;
116             default:            /* Also handles \" and \\ */
117               *q++ = *p;
118               break;
119             }
120         }
121       else
122         *q++ = *p;
123       p++;
124     }
125 out:
126   *q = 0;
127
128   return dest;
129 }
130
131 %}
132
133 %error-verbose
134 %union {
135   char *str;
136   GList *list;
137   GISourceSymbol *symbol;
138   GISourceType *ctype;
139   StorageClassSpecifier storage_class_specifier;
140   TypeQualifier type_qualifier;
141   FunctionSpecifier function_specifier;
142   UnaryOperator unary_operator;
143 }
144
145 %parse-param { GISourceScanner* scanner }
146 %lex-param { GISourceScanner* scanner }
147
148 %token <str> IDENTIFIER "identifier"
149 %token <str> TYPEDEF_NAME "typedef-name"
150
151 %token INTEGER FLOATING CHARACTER STRING
152
153 %token ELLIPSIS ADDEQ SUBEQ MULEQ DIVEQ MODEQ XOREQ ANDEQ OREQ SL SR
154 %token SLEQ SREQ EQ NOTEQ LTEQ GTEQ ANDAND OROR PLUSPLUS MINUSMINUS ARROW
155
156 %token AUTO BOOL BREAK CASE CHAR CONST CONTINUE DEFAULT DO DOUBLE ELSE ENUM
157 %token EXTENSION EXTERN FLOAT FOR GOTO IF INLINE INT LONG REGISTER RESTRICT
158 %token RETURN SHORT SIGNED SIZEOF STATIC STRUCT SWITCH TYPEDEF UNION UNSIGNED
159 %token VOID VOLATILE WHILE
160
161 %token FUNCTION_MACRO OBJECT_MACRO
162
163 %start translation_unit
164
165 %type <ctype> declaration_specifiers
166 %type <ctype> enum_specifier
167 %type <ctype> pointer
168 %type <ctype> specifier_qualifier_list
169 %type <ctype> type_name
170 %type <ctype> struct_or_union
171 %type <ctype> struct_or_union_specifier
172 %type <ctype> type_specifier
173 %type <str> identifier
174 %type <str> typedef_name
175 %type <str> identifier_or_typedef_name
176 %type <symbol> abstract_declarator
177 %type <symbol> init_declarator
178 %type <symbol> declarator
179 %type <symbol> enumerator
180 %type <symbol> direct_abstract_declarator
181 %type <symbol> direct_declarator
182 %type <symbol> parameter_declaration
183 %type <symbol> struct_declarator
184 %type <list> enumerator_list
185 %type <list> identifier_list
186 %type <list> init_declarator_list
187 %type <list> parameter_list
188 %type <list> struct_declaration
189 %type <list> struct_declaration_list
190 %type <list> struct_declarator_list
191 %type <storage_class_specifier> storage_class_specifier
192 %type <type_qualifier> type_qualifier
193 %type <type_qualifier> type_qualifier_list
194 %type <function_specifier> function_specifier
195 %type <symbol> expression
196 %type <symbol> constant_expression
197 %type <symbol> conditional_expression
198 %type <symbol> logical_and_expression
199 %type <symbol> logical_or_expression
200 %type <symbol> inclusive_or_expression
201 %type <symbol> exclusive_or_expression
202 %type <symbol> multiplicative_expression
203 %type <symbol> additive_expression
204 %type <symbol> shift_expression
205 %type <symbol> relational_expression
206 %type <symbol> equality_expression
207 %type <symbol> and_expression
208 %type <symbol> cast_expression
209 %type <symbol> assignment_expression
210 %type <symbol> unary_expression
211 %type <symbol> postfix_expression
212 %type <symbol> primary_expression
213 %type <unary_operator> unary_operator
214 %type <str> function_macro
215 %type <str> object_macro
216 %type <symbol> strings
217
218 %%
219
220 /* A.2.1 Expressions. */
221
222 primary_expression
223         : identifier
224           {
225                 $$ = g_hash_table_lookup (const_table, $1);
226                 if ($$ == NULL) {
227                         $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
228                 } else {
229                         $$ = gi_source_symbol_ref ($$);
230                 }
231           }
232         | INTEGER
233           {
234                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
235                 $$->const_int_set = TRUE;
236                 if (g_str_has_prefix (yytext, "0x") && strlen (yytext) > 2) {
237                         $$->const_int = g_ascii_strtoll (yytext + 2, NULL, 16);
238                 } else if (g_str_has_prefix (yytext, "0") && strlen (yytext) > 1) {
239                         $$->const_int = g_ascii_strtoll (yytext + 1, NULL, 8);
240                 } else {
241                         $$->const_int = g_ascii_strtoll (yytext, NULL, 10);
242                 }
243           }
244         | CHARACTER
245           {
246                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
247           }
248         | FLOATING
249           {
250                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
251                 $$->const_double_set = TRUE;
252                 $$->const_double = 0.0;
253         sscanf (yytext, "%lf", &($$->const_double));
254           }
255         | strings
256         | '(' expression ')'
257           {
258                 $$ = $2;
259           }
260         ;
261
262 /* concatenate adjacent string literal tokens */
263 strings
264         : STRING
265           {
266                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
267                 yytext[strlen (yytext) - 1] = '\0';
268                 $$->const_string = parse_c_string_literal (yytext + 1);
269                 if (!g_utf8_validate ($$->const_string, -1, NULL))
270                   {
271 #if 0
272                     g_warning ("Ignoring non-UTF-8 constant string \"%s\"", yytext + 1);
273 #endif
274                     g_free($$->const_string);
275                     $$->const_string = NULL;
276                   }
277
278           }
279         | strings STRING
280           {
281                 char *strings, *string2;
282                 $$ = $1;
283                 yytext[strlen (yytext) - 1] = '\0';
284                 string2 = parse_c_string_literal (yytext + 1);
285                 strings = g_strconcat ($$->const_string, string2, NULL);
286                 g_free ($$->const_string);
287                 g_free (string2);
288                 $$->const_string = strings;
289           }
290         ;
291
292 identifier
293         : IDENTIFIER
294           {
295                 $$ = g_strdup (yytext);
296           }
297         ;
298
299 identifier_or_typedef_name
300         : identifier
301         | typedef_name
302         ;
303
304 postfix_expression
305         : primary_expression
306         | postfix_expression '[' expression ']'
307           {
308                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
309           }
310         | postfix_expression '(' argument_expression_list ')'
311           {
312                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
313           }
314         | postfix_expression '(' ')'
315           {
316                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
317           }
318         | postfix_expression '.' identifier_or_typedef_name
319           {
320                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
321           }
322         | postfix_expression ARROW identifier_or_typedef_name
323           {
324                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
325           }
326         | postfix_expression PLUSPLUS
327           {
328                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
329           }
330         | postfix_expression MINUSMINUS
331           {
332                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
333           }
334         ;
335
336 argument_expression_list
337         : assignment_expression
338         | argument_expression_list ',' assignment_expression
339         ;
340
341 unary_expression
342         : postfix_expression
343         | PLUSPLUS unary_expression
344           {
345                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
346           }
347         | MINUSMINUS unary_expression
348           {
349                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
350           }
351         | unary_operator cast_expression
352           {
353                 switch ($1) {
354                 case UNARY_PLUS:
355                         $$ = $2;
356                         break;
357                 case UNARY_MINUS:
358                         $$ = $2;
359                         $$->const_int = -$2->const_int;
360                         break;
361                 case UNARY_BITWISE_COMPLEMENT:
362                         $$ = $2;
363                         $$->const_int = ~$2->const_int;
364                         break;
365                 case UNARY_LOGICAL_NEGATION:
366                         $$ = $2;
367                         $$->const_int = !gi_source_symbol_get_const_boolean ($2);
368                         break;
369                 default:
370                         $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
371                         break;
372                 }
373           }
374         | SIZEOF unary_expression
375           {
376                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
377           }
378         | SIZEOF '(' type_name ')'
379           {
380                 ctype_free ($3);
381                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
382           }
383         ;
384
385 unary_operator
386         : '&'
387           {
388                 $$ = UNARY_ADDRESS_OF;
389           }
390         | '*'
391           {
392                 $$ = UNARY_POINTER_INDIRECTION;
393           }
394         | '+'
395           {
396                 $$ = UNARY_PLUS;
397           }
398         | '-'
399           {
400                 $$ = UNARY_MINUS;
401           }
402         | '~'
403           {
404                 $$ = UNARY_BITWISE_COMPLEMENT;
405           }
406         | '!'
407           {
408                 $$ = UNARY_LOGICAL_NEGATION;
409           }
410         ;
411
412 cast_expression
413         : unary_expression
414         | '(' type_name ')' cast_expression
415           {
416                 ctype_free ($2);
417                 $$ = $4;
418           }
419         ;
420
421 multiplicative_expression
422         : cast_expression
423         | multiplicative_expression '*' cast_expression
424           {
425                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
426                 $$->const_int_set = TRUE;
427                 $$->const_int = $1->const_int * $3->const_int;
428           }
429         | multiplicative_expression '/' cast_expression
430           {
431                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
432                 $$->const_int_set = TRUE;
433                 if ($3->const_int != 0) {
434                         $$->const_int = $1->const_int / $3->const_int;
435                 }
436           }
437         | multiplicative_expression '%' cast_expression
438           {
439                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
440                 $$->const_int_set = TRUE;
441                 if ($3->const_int != 0) {
442                         $$->const_int = $1->const_int % $3->const_int;
443                 }
444           }
445         ;
446
447 additive_expression
448         : multiplicative_expression
449         | additive_expression '+' multiplicative_expression
450           {
451                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
452                 $$->const_int_set = TRUE;
453                 $$->const_int = $1->const_int + $3->const_int;
454           }
455         | additive_expression '-' multiplicative_expression
456           {
457                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
458                 $$->const_int_set = TRUE;
459                 $$->const_int = $1->const_int - $3->const_int;
460           }
461         ;
462
463 shift_expression
464         : additive_expression
465         | shift_expression SL additive_expression
466           {
467                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
468                 $$->const_int_set = TRUE;
469                 $$->const_int = $1->const_int << $3->const_int;
470
471                 /* assume this is a bitfield/flags declaration
472                  * if a left shift operator is sued in an enum value
473                  * This mimics the glib-mkenum behavior.
474                  */
475                 is_bitfield = TRUE;
476           }
477         | shift_expression SR additive_expression
478           {
479                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
480                 $$->const_int_set = TRUE;
481                 $$->const_int = $1->const_int >> $3->const_int;
482           }
483         ;
484
485 relational_expression
486         : shift_expression
487         | relational_expression '<' shift_expression
488           {
489                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
490                 $$->const_int_set = TRUE;
491                 $$->const_int = $1->const_int < $3->const_int;
492           }
493         | relational_expression '>' shift_expression
494           {
495                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
496                 $$->const_int_set = TRUE;
497                 $$->const_int = $1->const_int > $3->const_int;
498           }
499         | relational_expression LTEQ shift_expression
500           {
501                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
502                 $$->const_int_set = TRUE;
503                 $$->const_int = $1->const_int <= $3->const_int;
504           }
505         | relational_expression GTEQ shift_expression
506           {
507                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
508                 $$->const_int_set = TRUE;
509                 $$->const_int = $1->const_int >= $3->const_int;
510           }
511         ;
512
513 equality_expression
514         : relational_expression
515         | equality_expression EQ relational_expression
516           {
517                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
518                 $$->const_int_set = TRUE;
519                 $$->const_int = $1->const_int == $3->const_int;
520           }
521         | equality_expression NOTEQ relational_expression
522           {
523                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
524                 $$->const_int_set = TRUE;
525                 $$->const_int = $1->const_int != $3->const_int;
526           }
527         ;
528
529 and_expression
530         : equality_expression
531         | and_expression '&' equality_expression
532           {
533                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
534                 $$->const_int_set = TRUE;
535                 $$->const_int = $1->const_int & $3->const_int;
536           }
537         ;
538
539 exclusive_or_expression
540         : and_expression
541         | exclusive_or_expression '^' and_expression
542           {
543                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
544                 $$->const_int_set = TRUE;
545                 $$->const_int = $1->const_int ^ $3->const_int;
546           }
547         ;
548
549 inclusive_or_expression
550         : exclusive_or_expression
551         | inclusive_or_expression '|' exclusive_or_expression
552           {
553                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
554                 $$->const_int_set = TRUE;
555                 $$->const_int = $1->const_int | $3->const_int;
556           }
557         ;
558
559 logical_and_expression
560         : inclusive_or_expression
561         | logical_and_expression ANDAND inclusive_or_expression
562           {
563                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
564                 $$->const_int_set = TRUE;
565                 $$->const_int =
566                   gi_source_symbol_get_const_boolean ($1) &&
567                   gi_source_symbol_get_const_boolean ($3);
568           }
569         ;
570
571 logical_or_expression
572         : logical_and_expression
573         | logical_or_expression OROR logical_and_expression
574           {
575                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
576                 $$->const_int_set = TRUE;
577                 $$->const_int =
578                   gi_source_symbol_get_const_boolean ($1) ||
579                   gi_source_symbol_get_const_boolean ($3);
580           }
581         ;
582
583 conditional_expression
584         : logical_or_expression
585         | logical_or_expression '?' expression ':' conditional_expression
586           {
587                 $$ = gi_source_symbol_get_const_boolean ($1) ? $3 : $5;
588           }
589         ;
590
591 assignment_expression
592         : conditional_expression
593         | unary_expression assignment_operator assignment_expression
594           {
595                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
596           }
597         ;
598
599 assignment_operator
600         : '='
601         | MULEQ
602         | DIVEQ
603         | MODEQ
604         | ADDEQ
605         | SUBEQ
606         | SLEQ
607         | SREQ
608         | ANDEQ
609         | XOREQ
610         | OREQ
611         ;
612
613 expression
614         : assignment_expression
615         | expression ',' assignment_expression
616         | EXTENSION expression
617           {
618                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
619           }
620         ;
621
622 constant_expression
623         : conditional_expression
624         ;
625
626 /* A.2.2 Declarations. */
627
628 declaration
629         : declaration_specifiers init_declarator_list ';'
630           {
631                 GList *l;
632                 for (l = $2; l != NULL; l = l->next) {
633                         GISourceSymbol *sym = l->data;
634                         gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
635                         if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF) {
636                                 sym->type = CSYMBOL_TYPE_TYPEDEF;
637                         } else if (sym->base_type->type == CTYPE_FUNCTION) {
638                                 sym->type = CSYMBOL_TYPE_FUNCTION;
639                         } else {
640                                 sym->type = CSYMBOL_TYPE_OBJECT;
641                         }
642                         gi_source_scanner_add_symbol (scanner, sym);
643                         gi_source_symbol_unref (sym);
644                 }
645                 ctype_free ($1);
646           }
647         | declaration_specifiers ';'
648           {
649                 ctype_free ($1);
650           }
651         ;
652
653 declaration_specifiers
654         : storage_class_specifier declaration_specifiers
655           {
656                 $$ = $2;
657                 $$->storage_class_specifier |= $1;
658           }
659         | storage_class_specifier
660           {
661                 $$ = gi_source_type_new (CTYPE_INVALID);
662                 $$->storage_class_specifier |= $1;
663           }
664         | type_specifier declaration_specifiers
665           {
666                 $$ = $1;
667                 /* combine basic types like unsigned int and long long */
668                 if ($$->type == CTYPE_BASIC_TYPE && $2->type == CTYPE_BASIC_TYPE) {
669                         char *name = g_strdup_printf ("%s %s", $$->name, $2->name);
670                         g_free ($$->name);
671                         $$->name = name;
672                         ctype_free ($2);
673                 } else {
674                         $$->base_type = $2;
675                 }
676           }
677         | type_specifier
678         | type_qualifier declaration_specifiers
679           {
680                 $$ = $2;
681                 $$->type_qualifier |= $1;
682           }
683         | type_qualifier
684           {
685                 $$ = gi_source_type_new (CTYPE_INVALID);
686                 $$->type_qualifier |= $1;
687           }
688         | function_specifier declaration_specifiers
689           {
690                 $$ = $2;
691                 $$->function_specifier |= $1;
692           }
693         | function_specifier
694           {
695                 $$ = gi_source_type_new (CTYPE_INVALID);
696                 $$->function_specifier |= $1;
697           }
698         ;
699
700 init_declarator_list
701         : init_declarator
702           {
703                 $$ = g_list_append (NULL, $1);
704           }
705         | init_declarator_list ',' init_declarator
706           {
707                 $$ = g_list_append ($1, $3);
708           }
709         ;
710
711 init_declarator
712         : declarator
713         | declarator '=' initializer
714         ;
715
716 storage_class_specifier
717         : TYPEDEF
718           {
719                 $$ = STORAGE_CLASS_TYPEDEF;
720           }
721         | EXTERN
722           {
723                 $$ = STORAGE_CLASS_EXTERN;
724           }
725         | STATIC
726           {
727                 $$ = STORAGE_CLASS_STATIC;
728           }
729         | AUTO
730           {
731                 $$ = STORAGE_CLASS_AUTO;
732           }
733         | REGISTER
734           {
735                 $$ = STORAGE_CLASS_REGISTER;
736           }
737         ;
738
739 type_specifier
740         : VOID
741           {
742                 $$ = gi_source_type_new (CTYPE_VOID);
743           }
744         | CHAR
745           {
746                 $$ = gi_source_basic_type_new ("char");
747           }
748         | SHORT
749           {
750                 $$ = gi_source_basic_type_new ("short");
751           }
752         | INT
753           {
754                 $$ = gi_source_basic_type_new ("int");
755           }
756         | LONG
757           {
758                 $$ = gi_source_basic_type_new ("long");
759           }
760         | FLOAT
761           {
762                 $$ = gi_source_basic_type_new ("float");
763           }
764         | DOUBLE
765           {
766                 $$ = gi_source_basic_type_new ("double");
767           }
768         | SIGNED
769           {
770                 $$ = gi_source_basic_type_new ("signed");
771           }
772         | UNSIGNED
773           {
774                 $$ = gi_source_basic_type_new ("unsigned");
775           }
776         | BOOL
777           {
778                 $$ = gi_source_basic_type_new ("bool");
779           }
780         | struct_or_union_specifier
781         | enum_specifier
782         | typedef_name
783           {
784                 $$ = gi_source_typedef_new ($1);
785                 g_free ($1);
786           }
787         ;
788
789 struct_or_union_specifier
790         : struct_or_union identifier_or_typedef_name '{' struct_declaration_list '}'
791           {
792                 $$ = $1;
793                 $$->name = $2;
794                 $$->child_list = $4;
795
796                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
797                 if ($$->type == CTYPE_STRUCT) {
798                         sym->type = CSYMBOL_TYPE_STRUCT;
799                 } else if ($$->type == CTYPE_UNION) {
800                         sym->type = CSYMBOL_TYPE_UNION;
801                 } else {
802                         g_assert_not_reached ();
803                 }
804                 sym->ident = g_strdup ($$->name);
805                 sym->base_type = gi_source_type_copy ($$);
806                 gi_source_scanner_add_symbol (scanner, sym);
807                 gi_source_symbol_unref (sym);
808           }
809         | struct_or_union '{' struct_declaration_list '}'
810           {
811                 $$ = $1;
812                 $$->child_list = $3;
813           }
814         | struct_or_union identifier_or_typedef_name
815           {
816                 $$ = $1;
817                 $$->name = $2;
818           }
819         ;
820
821 struct_or_union
822         : STRUCT
823           {
824                 scanner->private = FALSE;
825                 $$ = gi_source_struct_new (NULL);
826           }
827         | UNION
828           {
829                 scanner->private = FALSE;
830                 $$ = gi_source_union_new (NULL);
831           }
832         ;
833
834 struct_declaration_list
835         : struct_declaration
836         | struct_declaration_list struct_declaration
837           {
838                 $$ = g_list_concat ($1, $2);
839           }
840         ;
841
842 struct_declaration
843         : specifier_qualifier_list struct_declarator_list ';'
844           {
845             GList *l;
846             $$ = NULL;
847             for (l = $2; l != NULL; l = l->next)
848               {
849                 GISourceSymbol *sym = l->data;
850                 if ($1->storage_class_specifier & STORAGE_CLASS_TYPEDEF)
851                     sym->type = CSYMBOL_TYPE_TYPEDEF;
852                 else
853                     sym->type = CSYMBOL_TYPE_MEMBER;
854                 gi_source_symbol_merge_type (sym, gi_source_type_copy ($1));
855                 sym->private = scanner->private;
856                 $$ = g_list_append ($$, sym);
857               }
858             ctype_free ($1);
859           }
860         ;
861
862 specifier_qualifier_list
863         : type_specifier specifier_qualifier_list
864           {
865                 $$ = $1;
866                 $$->base_type = $2;
867           }
868         | type_specifier
869         | type_qualifier specifier_qualifier_list
870           {
871                 $$ = $2;
872                 $$->type_qualifier |= $1;
873           }
874         | type_qualifier
875           {
876                 $$ = gi_source_type_new (CTYPE_INVALID);
877                 $$->type_qualifier |= $1;
878           }
879         ;
880
881 struct_declarator_list
882         : struct_declarator
883           {
884                 $$ = g_list_append (NULL, $1);
885           }
886         | struct_declarator_list ',' struct_declarator
887           {
888                 $$ = g_list_append ($1, $3);
889           }
890         ;
891
892 struct_declarator
893         : /* empty, support for anonymous structs and unions */
894           {
895                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
896           }
897         | declarator
898         | ':' constant_expression
899           {
900                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
901           }
902         | declarator ':' constant_expression
903           {
904                 $$ = $1;
905                 if ($3->const_int_set) {
906                   $$->const_int_set = TRUE;
907                   $$->const_int = $3->const_int;
908                 }
909           }
910         ;
911
912 enum_specifier
913         : enum_keyword identifier_or_typedef_name '{' enumerator_list '}'
914           {
915                 $$ = gi_source_enum_new ($2);
916                 $$->child_list = $4;
917                 $$->is_bitfield = is_bitfield || scanner->flags;
918                 last_enum_value = -1;
919           }
920         | enum_keyword '{' enumerator_list '}'
921           {
922                 $$ = gi_source_enum_new (NULL);
923                 $$->child_list = $3;
924                 $$->is_bitfield = is_bitfield || scanner->flags;
925                 last_enum_value = -1;
926           }
927         | enum_keyword identifier_or_typedef_name '{' enumerator_list ',' '}'
928           {
929                 $$ = gi_source_enum_new ($2);
930                 $$->child_list = $4;
931                 $$->is_bitfield = is_bitfield || scanner->flags;
932                 last_enum_value = -1;
933           }
934         | enum_keyword '{' enumerator_list ',' '}'
935           {
936                 $$ = gi_source_enum_new (NULL);
937                 $$->child_list = $3;
938                 $$->is_bitfield = is_bitfield || scanner->flags;
939                 last_enum_value = -1;
940           }
941         | enum_keyword identifier_or_typedef_name
942           {
943                 $$ = gi_source_enum_new ($2);
944           }
945         ;
946
947 enum_keyword
948         : ENUM
949           {
950                 scanner->flags = FALSE;
951                 scanner->private = FALSE;
952           }
953         ;
954
955 enumerator_list
956         :
957           {
958                 /* reset flag before the first enum value */
959                 is_bitfield = FALSE;
960           }
961           enumerator
962           {
963             $2->private = scanner->private;
964             $$ = g_list_append (NULL, $2);
965           }
966         | enumerator_list ',' enumerator
967           {
968             $3->private = scanner->private;
969             $$ = g_list_append ($1, $3);
970           }
971         ;
972
973 enumerator
974         : identifier
975           {
976                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT, lineno);
977                 $$->ident = $1;
978                 $$->const_int_set = TRUE;
979                 $$->const_int = ++last_enum_value;
980                 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
981           }
982         | identifier '=' constant_expression
983           {
984                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT, lineno);
985                 $$->ident = $1;
986                 $$->const_int_set = TRUE;
987                 $$->const_int = $3->const_int;
988                 last_enum_value = $$->const_int;
989                 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
990           }
991         ;
992
993 type_qualifier
994         : CONST
995           {
996                 $$ = TYPE_QUALIFIER_CONST;
997           }
998         | RESTRICT
999           {
1000                 $$ = TYPE_QUALIFIER_RESTRICT;
1001           }
1002         | EXTENSION
1003           {
1004                 $$ = TYPE_QUALIFIER_EXTENSION;
1005           }
1006         | VOLATILE
1007           {
1008                 $$ = TYPE_QUALIFIER_VOLATILE;
1009           }
1010         ;
1011
1012 function_specifier
1013         : INLINE
1014           {
1015                 $$ = FUNCTION_INLINE;
1016           }
1017         ;
1018
1019 declarator
1020         : pointer direct_declarator
1021           {
1022                 $$ = $2;
1023                 gi_source_symbol_merge_type ($$, $1);
1024           }
1025         | direct_declarator
1026         ;
1027
1028 direct_declarator
1029         : identifier
1030           {
1031                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1032                 $$->ident = $1;
1033           }
1034         | '(' declarator ')'
1035           {
1036                 $$ = $2;
1037           }
1038         | direct_declarator '[' assignment_expression ']'
1039           {
1040                 $$ = $1;
1041                 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
1042           }
1043         | direct_declarator '[' ']'
1044           {
1045                 $$ = $1;
1046                 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1047           }
1048         | direct_declarator '(' parameter_list ')'
1049           {
1050                 GISourceType *func = gi_source_function_new ();
1051                 // ignore (void) parameter list
1052                 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1053                         func->child_list = $3;
1054                 }
1055                 $$ = $1;
1056                 gi_source_symbol_merge_type ($$, func);
1057           }
1058         | direct_declarator '(' identifier_list ')'
1059           {
1060                 GISourceType *func = gi_source_function_new ();
1061                 func->child_list = $3;
1062                 $$ = $1;
1063                 gi_source_symbol_merge_type ($$, func);
1064           }
1065         | direct_declarator '(' ')'
1066           {
1067                 GISourceType *func = gi_source_function_new ();
1068                 $$ = $1;
1069                 gi_source_symbol_merge_type ($$, func);
1070           }
1071         ;
1072
1073 pointer
1074         : '*' type_qualifier_list
1075           {
1076                 $$ = gi_source_pointer_new (NULL);
1077                 $$->type_qualifier = $2;
1078           }
1079         | '*'
1080           {
1081                 $$ = gi_source_pointer_new (NULL);
1082           }
1083         | '*' type_qualifier_list pointer
1084           {
1085                 $$ = gi_source_pointer_new ($3);
1086                 $$->type_qualifier = $2;
1087           }
1088         | '*' pointer
1089           {
1090                 $$ = gi_source_pointer_new ($2);
1091           }
1092         ;
1093
1094 type_qualifier_list
1095         : type_qualifier
1096         | type_qualifier_list type_qualifier
1097           {
1098                 $$ = $1 | $2;
1099           }
1100         ;
1101
1102 parameter_list
1103         : parameter_declaration
1104           {
1105                 $$ = g_list_append (NULL, $1);
1106           }
1107         | parameter_list ',' parameter_declaration
1108           {
1109                 $$ = g_list_append ($1, $3);
1110           }
1111         ;
1112
1113 parameter_declaration
1114         : declaration_specifiers declarator
1115           {
1116                 $$ = $2;
1117                 gi_source_symbol_merge_type ($$, $1);
1118           }
1119         | declaration_specifiers abstract_declarator
1120           {
1121                 $$ = $2;
1122                 gi_source_symbol_merge_type ($$, $1);
1123           }
1124         | declaration_specifiers
1125           {
1126                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1127                 $$->base_type = $1;
1128           }
1129         | ELLIPSIS
1130           {
1131                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_ELLIPSIS, lineno);
1132           }
1133         ;
1134
1135 identifier_list
1136         : identifier
1137           {
1138                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1139                 sym->ident = $1;
1140                 $$ = g_list_append (NULL, sym);
1141           }
1142         | identifier_list ',' identifier
1143           {
1144                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1145                 sym->ident = $3;
1146                 $$ = g_list_append ($1, sym);
1147           }
1148         ;
1149
1150 type_name
1151         : specifier_qualifier_list
1152         | specifier_qualifier_list abstract_declarator
1153         ;
1154
1155 abstract_declarator
1156         : pointer
1157           {
1158                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1159                 gi_source_symbol_merge_type ($$, $1);
1160           }
1161         | direct_abstract_declarator
1162         | pointer direct_abstract_declarator
1163           {
1164                 $$ = $2;
1165                 gi_source_symbol_merge_type ($$, $1);
1166           }
1167         ;
1168
1169 direct_abstract_declarator
1170         : '(' abstract_declarator ')'
1171           {
1172                 $$ = $2;
1173           }
1174         | '[' ']'
1175           {
1176                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1177                 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1178           }
1179         | '[' assignment_expression ']'
1180           {
1181                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1182                 gi_source_symbol_merge_type ($$, gi_source_array_new ($2));
1183           }
1184         | direct_abstract_declarator '[' ']'
1185           {
1186                 $$ = $1;
1187                 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1188           }
1189         | direct_abstract_declarator '[' assignment_expression ']'
1190           {
1191                 $$ = $1;
1192                 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
1193           }
1194         | '(' ')'
1195           {
1196                 GISourceType *func = gi_source_function_new ();
1197                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1198                 gi_source_symbol_merge_type ($$, func);
1199           }
1200         | '(' parameter_list ')'
1201           {
1202                 GISourceType *func = gi_source_function_new ();
1203                 // ignore (void) parameter list
1204                 if ($2 != NULL && ($2->next != NULL || ((GISourceSymbol *) $2->data)->base_type->type != CTYPE_VOID)) {
1205                         func->child_list = $2;
1206                 }
1207                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1208                 gi_source_symbol_merge_type ($$, func);
1209           }
1210         | direct_abstract_declarator '(' ')'
1211           {
1212                 GISourceType *func = gi_source_function_new ();
1213                 $$ = $1;
1214                 gi_source_symbol_merge_type ($$, func);
1215           }
1216         | direct_abstract_declarator '(' parameter_list ')'
1217           {
1218                 GISourceType *func = gi_source_function_new ();
1219                 // ignore (void) parameter list
1220                 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1221                         func->child_list = $3;
1222                 }
1223                 $$ = $1;
1224                 gi_source_symbol_merge_type ($$, func);
1225           }
1226         ;
1227
1228 typedef_name
1229         : TYPEDEF_NAME
1230           {
1231                 $$ = g_strdup (yytext);
1232           }
1233         ;
1234
1235 initializer
1236         : assignment_expression
1237         | '{' initializer_list '}'
1238         | '{' initializer_list ',' '}'
1239         ;
1240
1241 initializer_list
1242         : initializer
1243         | initializer_list ',' initializer
1244         ;
1245
1246 /* A.2.3 Statements. */
1247
1248 statement
1249         : labeled_statement
1250         | compound_statement
1251         | expression_statement
1252         | selection_statement
1253         | iteration_statement
1254         | jump_statement
1255         ;
1256
1257 labeled_statement
1258         : identifier_or_typedef_name ':' statement
1259         | CASE constant_expression ':' statement
1260         | DEFAULT ':' statement
1261         ;
1262
1263 compound_statement
1264         : '{' '}'
1265         | '{' block_item_list '}'
1266         ;
1267
1268 block_item_list
1269         : block_item
1270         | block_item_list block_item
1271         ;
1272
1273 block_item
1274         : declaration
1275         | statement
1276         ;
1277
1278 expression_statement
1279         : ';'
1280         | expression ';'
1281         ;
1282
1283 selection_statement
1284         : IF '(' expression ')' statement
1285         | IF '(' expression ')' statement ELSE statement
1286         | SWITCH '(' expression ')' statement
1287         ;
1288
1289 iteration_statement
1290         : WHILE '(' expression ')' statement
1291         | DO statement WHILE '(' expression ')' ';'
1292         | FOR '(' ';' ';' ')' statement
1293         | FOR '(' expression ';' ';' ')' statement
1294         | FOR '(' ';' expression ';' ')' statement
1295         | FOR '(' expression ';' expression ';' ')' statement
1296         | FOR '(' ';' ';' expression ')' statement
1297         | FOR '(' expression ';' ';' expression ')' statement
1298         | FOR '(' ';' expression ';' expression ')' statement
1299         | FOR '(' expression ';' expression ';' expression ')' statement
1300         ;
1301
1302 jump_statement
1303         : GOTO identifier_or_typedef_name ';'
1304         | CONTINUE ';'
1305         | BREAK ';'
1306         | RETURN ';'
1307         | RETURN expression ';'
1308         ;
1309
1310 /* A.2.4 External definitions. */
1311
1312 translation_unit
1313         : external_declaration
1314         | translation_unit external_declaration
1315         ;
1316
1317 external_declaration
1318         : function_definition
1319         | declaration
1320         | macro
1321         ;
1322
1323 function_definition
1324         : declaration_specifiers declarator declaration_list compound_statement
1325         | declaration_specifiers declarator compound_statement
1326         ;
1327
1328 declaration_list
1329         : declaration
1330         | declaration_list declaration
1331         ;
1332
1333 /* Macros */
1334
1335 function_macro
1336         : FUNCTION_MACRO
1337           {
1338                 $$ = g_strdup (yytext + strlen ("#define "));
1339           }
1340         ;
1341
1342 object_macro
1343         : OBJECT_MACRO
1344           {
1345                 $$ = g_strdup (yytext + strlen ("#define "));
1346           }
1347         ;
1348
1349 function_macro_define
1350         : function_macro '(' identifier_list ')'
1351         ;
1352
1353 object_macro_define
1354         : object_macro constant_expression
1355           {
1356                 if ($2->const_int_set || $2->const_double_set || $2->const_string != NULL) {
1357                         $2->ident = $1;
1358                         gi_source_scanner_add_symbol (scanner, $2);
1359                         gi_source_symbol_unref ($2);
1360                 }
1361           }
1362         ;
1363
1364 macro
1365         : function_macro_define
1366         | object_macro_define
1367         | error
1368         ;
1369
1370 %%
1371 static void
1372 yyerror (GISourceScanner *scanner, const char *s)
1373 {
1374   /* ignore errors while doing a macro scan as not all object macros
1375    * have valid expressions */
1376   if (!scanner->macro_scan)
1377     {
1378       fprintf(stderr, "%s:%d: %s in '%s' at '%s'\n",
1379               scanner->current_filename, lineno, s, linebuf, yytext);
1380     }
1381 }
1382
1383 static int
1384 eat_hspace (FILE * f)
1385 {
1386   int c;
1387   do
1388     {
1389       c = fgetc (f);
1390     }
1391   while (c == ' ' || c == '\t');
1392   return c;
1393 }
1394
1395 static int
1396 eat_line (FILE * f, int c)
1397 {
1398   while (c != EOF && c != '\n')
1399     {
1400       c = fgetc (f);
1401     }
1402   if (c == '\n')
1403     {
1404       c = fgetc (f);
1405       if (c == ' ' || c == '\t')
1406         {
1407           c = eat_hspace (f);
1408         }
1409     }
1410   return c;
1411 }
1412
1413 static int
1414 read_identifier (FILE * f, int c, char **identifier)
1415 {
1416   GString *id = g_string_new ("");
1417   while (g_ascii_isalnum (c) || c == '_')
1418     {
1419       g_string_append_c (id, c);
1420       c = fgetc (f);
1421     }
1422   *identifier = g_string_free (id, FALSE);
1423   return c;
1424 }
1425
1426 void
1427 gi_source_scanner_parse_macros (GISourceScanner *scanner, GList *filenames)
1428 {
1429   GError *error = NULL;
1430   char *tmp_name = NULL;
1431   FILE *fmacros =
1432     fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error),
1433             "w+");
1434   g_unlink (tmp_name);
1435
1436   GList *l;
1437   for (l = filenames; l != NULL; l = l->next)
1438     {
1439       FILE *f = fopen (l->data, "r");
1440       int line = 1;
1441
1442       GString *define_line;
1443       char *str;
1444       gboolean error_line = FALSE;
1445       int c = eat_hspace (f);
1446       while (c != EOF)
1447         {
1448           if (c != '#')
1449             {
1450               /* ignore line */
1451               c = eat_line (f, c);
1452               line++;
1453               continue;
1454             }
1455
1456           /* print current location */
1457           str = g_strescape (l->data, "");
1458           fprintf (fmacros, "# %d \"%s\"\n", line, str);
1459           g_free (str);
1460
1461           c = eat_hspace (f);
1462           c = read_identifier (f, c, &str);
1463           if (strcmp (str, "define") != 0 || (c != ' ' && c != '\t'))
1464             {
1465               g_free (str);
1466               /* ignore line */
1467               c = eat_line (f, c);
1468               line++;
1469               continue;
1470             }
1471           g_free (str);
1472           c = eat_hspace (f);
1473           c = read_identifier (f, c, &str);
1474           if (strlen (str) == 0 || (c != ' ' && c != '\t' && c != '('))
1475             {
1476               g_free (str);
1477               /* ignore line */
1478               c = eat_line (f, c);
1479               line++;
1480               continue;
1481             }
1482           define_line = g_string_new ("#define ");
1483           g_string_append (define_line, str);
1484           g_free (str);
1485           if (c == '(')
1486             {
1487               while (c != ')')
1488                 {
1489                   g_string_append_c (define_line, c);
1490                   c = fgetc (f);
1491                   if (c == EOF || c == '\n')
1492                     {
1493                       error_line = TRUE;
1494                       break;
1495                     }
1496                 }
1497               if (error_line)
1498                 {
1499                   g_string_free (define_line, TRUE);
1500                   /* ignore line */
1501                   c = eat_line (f, c);
1502                   line++;
1503                   continue;
1504                 }
1505
1506               g_assert (c == ')');
1507               g_string_append_c (define_line, c);
1508               c = fgetc (f);
1509
1510               /* found function-like macro */
1511               fprintf (fmacros, "%s\n", define_line->str);
1512
1513               g_string_free (define_line, TRUE);
1514               /* ignore rest of line */
1515               c = eat_line (f, c);
1516               line++;
1517               continue;
1518             }
1519           if (c != ' ' && c != '\t')
1520             {
1521               g_string_free (define_line, TRUE);
1522               /* ignore line */
1523               c = eat_line (f, c);
1524               line++;
1525               continue;
1526             }
1527           while (c != EOF && c != '\n')
1528             {
1529               g_string_append_c (define_line, c);
1530               c = fgetc (f);
1531               if (c == '\\')
1532                 {
1533                   c = fgetc (f);
1534                   if (c == '\n')
1535                     {
1536                       /* fold lines when seeing backslash new-line sequence */
1537                       c = fgetc (f);
1538                     }
1539                   else
1540                     {
1541                       g_string_append_c (define_line, '\\');
1542                     }
1543                 }
1544             }
1545
1546           /* found object-like macro */
1547           fprintf (fmacros, "%s\n", define_line->str);
1548
1549           c = eat_line (f, c);
1550           line++;
1551         }
1552
1553       fclose (f);
1554     }
1555
1556   rewind (fmacros);
1557   gi_source_scanner_parse_file (scanner, fmacros);
1558 }
1559
1560 gboolean
1561 gi_source_scanner_parse_file (GISourceScanner *scanner, FILE *file)
1562 {
1563   g_return_val_if_fail (file != NULL, FALSE);
1564
1565   const_table = g_hash_table_new_full (g_str_hash, g_str_equal,
1566                                        g_free, (GDestroyNotify)gi_source_symbol_unref);
1567
1568   lineno = 1;
1569   yyin = file;
1570   yyparse (scanner);
1571
1572   g_hash_table_destroy (const_table);
1573   const_table = NULL;
1574
1575   yyin = NULL;
1576
1577   return TRUE;
1578 }
1579
1580 gboolean
1581 gi_source_scanner_lex_filename (GISourceScanner *scanner, const gchar *filename)
1582 {
1583   lineno = 1;
1584   yyin = fopen (filename, "r");
1585
1586   while (yylex (scanner) != YYEOF)
1587     ;
1588
1589   fclose (yyin);
1590
1591   return TRUE;
1592 }