Support hexadecimal escapes in constants
[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 identifier_or_typedef_name '{' enumerator_list '}'
914           {
915                 scanner->private = FALSE;
916                 $$ = gi_source_enum_new ($2);
917                 $$->child_list = $4;
918                 $$->is_bitfield = is_bitfield;
919                 last_enum_value = -1;
920           }
921         | ENUM '{' enumerator_list '}'
922           {
923                 scanner->private = FALSE;
924                 $$ = gi_source_enum_new (NULL);
925                 $$->child_list = $3;
926                 $$->is_bitfield = is_bitfield;
927                 last_enum_value = -1;
928           }
929         | ENUM identifier_or_typedef_name '{' enumerator_list ',' '}'
930           {
931                 scanner->private = FALSE;
932                 $$ = gi_source_enum_new ($2);
933                 $$->child_list = $4;
934                 $$->is_bitfield = is_bitfield;
935                 last_enum_value = -1;
936           }
937         | ENUM '{' enumerator_list ',' '}'
938           {
939                 scanner->private = FALSE;
940                 $$ = gi_source_enum_new (NULL);
941                 $$->child_list = $3;
942                 $$->is_bitfield = is_bitfield;
943                 last_enum_value = -1;
944           }
945         | ENUM identifier_or_typedef_name
946           {
947                 scanner->private = FALSE;
948                 $$ = gi_source_enum_new ($2);
949           }
950         ;
951
952 enumerator_list
953         :
954           {
955                 /* reset flag before the first enum value */
956                 is_bitfield = FALSE;
957           }
958           enumerator
959           {
960             $2->private = scanner->private;
961             $$ = g_list_append (NULL, $2);
962           }
963         | enumerator_list ',' enumerator
964           {
965             $3->private = scanner->private;
966             $$ = g_list_append ($1, $3);
967           }
968         ;
969
970 enumerator
971         : identifier
972           {
973                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT, lineno);
974                 $$->ident = $1;
975                 $$->const_int_set = TRUE;
976                 $$->const_int = ++last_enum_value;
977                 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
978           }
979         | identifier '=' constant_expression
980           {
981                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_OBJECT, lineno);
982                 $$->ident = $1;
983                 $$->const_int_set = TRUE;
984                 $$->const_int = $3->const_int;
985                 last_enum_value = $$->const_int;
986                 g_hash_table_insert (const_table, g_strdup ($$->ident), gi_source_symbol_ref ($$));
987           }
988         ;
989
990 type_qualifier
991         : CONST
992           {
993                 $$ = TYPE_QUALIFIER_CONST;
994           }
995         | RESTRICT
996           {
997                 $$ = TYPE_QUALIFIER_RESTRICT;
998           }
999         | EXTENSION
1000           {
1001                 $$ = TYPE_QUALIFIER_EXTENSION;
1002           }
1003         | VOLATILE
1004           {
1005                 $$ = TYPE_QUALIFIER_VOLATILE;
1006           }
1007         ;
1008
1009 function_specifier
1010         : INLINE
1011           {
1012                 $$ = FUNCTION_INLINE;
1013           }
1014         ;
1015
1016 declarator
1017         : pointer direct_declarator
1018           {
1019                 $$ = $2;
1020                 gi_source_symbol_merge_type ($$, $1);
1021           }
1022         | direct_declarator
1023         ;
1024
1025 direct_declarator
1026         : identifier
1027           {
1028                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1029                 $$->ident = $1;
1030           }
1031         | '(' declarator ')'
1032           {
1033                 $$ = $2;
1034           }
1035         | direct_declarator '[' assignment_expression ']'
1036           {
1037                 $$ = $1;
1038                 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
1039           }
1040         | direct_declarator '[' ']'
1041           {
1042                 $$ = $1;
1043                 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1044           }
1045         | direct_declarator '(' parameter_list ')'
1046           {
1047                 GISourceType *func = gi_source_function_new ();
1048                 // ignore (void) parameter list
1049                 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1050                         func->child_list = $3;
1051                 }
1052                 $$ = $1;
1053                 gi_source_symbol_merge_type ($$, func);
1054           }
1055         | direct_declarator '(' identifier_list ')'
1056           {
1057                 GISourceType *func = gi_source_function_new ();
1058                 func->child_list = $3;
1059                 $$ = $1;
1060                 gi_source_symbol_merge_type ($$, func);
1061           }
1062         | direct_declarator '(' ')'
1063           {
1064                 GISourceType *func = gi_source_function_new ();
1065                 $$ = $1;
1066                 gi_source_symbol_merge_type ($$, func);
1067           }
1068         ;
1069
1070 pointer
1071         : '*' type_qualifier_list
1072           {
1073                 $$ = gi_source_pointer_new (NULL);
1074                 $$->type_qualifier = $2;
1075           }
1076         | '*'
1077           {
1078                 $$ = gi_source_pointer_new (NULL);
1079           }
1080         | '*' type_qualifier_list pointer
1081           {
1082                 $$ = gi_source_pointer_new ($3);
1083                 $$->type_qualifier = $2;
1084           }
1085         | '*' pointer
1086           {
1087                 $$ = gi_source_pointer_new ($2);
1088           }
1089         ;
1090
1091 type_qualifier_list
1092         : type_qualifier
1093         | type_qualifier_list type_qualifier
1094           {
1095                 $$ = $1 | $2;
1096           }
1097         ;
1098
1099 parameter_list
1100         : parameter_declaration
1101           {
1102                 $$ = g_list_append (NULL, $1);
1103           }
1104         | parameter_list ',' parameter_declaration
1105           {
1106                 $$ = g_list_append ($1, $3);
1107           }
1108         ;
1109
1110 parameter_declaration
1111         : declaration_specifiers declarator
1112           {
1113                 $$ = $2;
1114                 gi_source_symbol_merge_type ($$, $1);
1115           }
1116         | declaration_specifiers abstract_declarator
1117           {
1118                 $$ = $2;
1119                 gi_source_symbol_merge_type ($$, $1);
1120           }
1121         | declaration_specifiers
1122           {
1123                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1124                 $$->base_type = $1;
1125           }
1126         | ELLIPSIS
1127           {
1128                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_ELLIPSIS, lineno);
1129           }
1130         ;
1131
1132 identifier_list
1133         : identifier
1134           {
1135                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1136                 sym->ident = $1;
1137                 $$ = g_list_append (NULL, sym);
1138           }
1139         | identifier_list ',' identifier
1140           {
1141                 GISourceSymbol *sym = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1142                 sym->ident = $3;
1143                 $$ = g_list_append ($1, sym);
1144           }
1145         ;
1146
1147 type_name
1148         : specifier_qualifier_list
1149         | specifier_qualifier_list abstract_declarator
1150         ;
1151
1152 abstract_declarator
1153         : pointer
1154           {
1155                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1156                 gi_source_symbol_merge_type ($$, $1);
1157           }
1158         | direct_abstract_declarator
1159         | pointer direct_abstract_declarator
1160           {
1161                 $$ = $2;
1162                 gi_source_symbol_merge_type ($$, $1);
1163           }
1164         ;
1165
1166 direct_abstract_declarator
1167         : '(' abstract_declarator ')'
1168           {
1169                 $$ = $2;
1170           }
1171         | '[' ']'
1172           {
1173                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1174                 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1175           }
1176         | '[' assignment_expression ']'
1177           {
1178                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1179                 gi_source_symbol_merge_type ($$, gi_source_array_new ($2));
1180           }
1181         | direct_abstract_declarator '[' ']'
1182           {
1183                 $$ = $1;
1184                 gi_source_symbol_merge_type ($$, gi_source_array_new (NULL));
1185           }
1186         | direct_abstract_declarator '[' assignment_expression ']'
1187           {
1188                 $$ = $1;
1189                 gi_source_symbol_merge_type ($$, gi_source_array_new ($3));
1190           }
1191         | '(' ')'
1192           {
1193                 GISourceType *func = gi_source_function_new ();
1194                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1195                 gi_source_symbol_merge_type ($$, func);
1196           }
1197         | '(' parameter_list ')'
1198           {
1199                 GISourceType *func = gi_source_function_new ();
1200                 // ignore (void) parameter list
1201                 if ($2 != NULL && ($2->next != NULL || ((GISourceSymbol *) $2->data)->base_type->type != CTYPE_VOID)) {
1202                         func->child_list = $2;
1203                 }
1204                 $$ = gi_source_symbol_new (CSYMBOL_TYPE_INVALID, lineno);
1205                 gi_source_symbol_merge_type ($$, func);
1206           }
1207         | direct_abstract_declarator '(' ')'
1208           {
1209                 GISourceType *func = gi_source_function_new ();
1210                 $$ = $1;
1211                 gi_source_symbol_merge_type ($$, func);
1212           }
1213         | direct_abstract_declarator '(' parameter_list ')'
1214           {
1215                 GISourceType *func = gi_source_function_new ();
1216                 // ignore (void) parameter list
1217                 if ($3 != NULL && ($3->next != NULL || ((GISourceSymbol *) $3->data)->base_type->type != CTYPE_VOID)) {
1218                         func->child_list = $3;
1219                 }
1220                 $$ = $1;
1221                 gi_source_symbol_merge_type ($$, func);
1222           }
1223         ;
1224
1225 typedef_name
1226         : TYPEDEF_NAME
1227           {
1228                 $$ = g_strdup (yytext);
1229           }
1230         ;
1231
1232 initializer
1233         : assignment_expression
1234         | '{' initializer_list '}'
1235         | '{' initializer_list ',' '}'
1236         ;
1237
1238 initializer_list
1239         : initializer
1240         | initializer_list ',' initializer
1241         ;
1242
1243 /* A.2.3 Statements. */
1244
1245 statement
1246         : labeled_statement
1247         | compound_statement
1248         | expression_statement
1249         | selection_statement
1250         | iteration_statement
1251         | jump_statement
1252         ;
1253
1254 labeled_statement
1255         : identifier_or_typedef_name ':' statement
1256         | CASE constant_expression ':' statement
1257         | DEFAULT ':' statement
1258         ;
1259
1260 compound_statement
1261         : '{' '}'
1262         | '{' block_item_list '}'
1263         ;
1264
1265 block_item_list
1266         : block_item
1267         | block_item_list block_item
1268         ;
1269
1270 block_item
1271         : declaration
1272         | statement
1273         ;
1274
1275 expression_statement
1276         : ';'
1277         | expression ';'
1278         ;
1279
1280 selection_statement
1281         : IF '(' expression ')' statement
1282         | IF '(' expression ')' statement ELSE statement
1283         | SWITCH '(' expression ')' statement
1284         ;
1285
1286 iteration_statement
1287         : WHILE '(' expression ')' statement
1288         | DO statement WHILE '(' expression ')' ';'
1289         | FOR '(' ';' ';' ')' statement
1290         | FOR '(' expression ';' ';' ')' statement
1291         | FOR '(' ';' expression ';' ')' statement
1292         | FOR '(' expression ';' expression ';' ')' statement
1293         | FOR '(' ';' ';' expression ')' statement
1294         | FOR '(' expression ';' ';' expression ')' statement
1295         | FOR '(' ';' expression ';' expression ')' statement
1296         | FOR '(' expression ';' expression ';' expression ')' statement
1297         ;
1298
1299 jump_statement
1300         : GOTO identifier_or_typedef_name ';'
1301         | CONTINUE ';'
1302         | BREAK ';'
1303         | RETURN ';'
1304         | RETURN expression ';'
1305         ;
1306
1307 /* A.2.4 External definitions. */
1308
1309 translation_unit
1310         : external_declaration
1311         | translation_unit external_declaration
1312         ;
1313
1314 external_declaration
1315         : function_definition
1316         | declaration
1317         | macro
1318         ;
1319
1320 function_definition
1321         : declaration_specifiers declarator declaration_list compound_statement
1322         | declaration_specifiers declarator compound_statement
1323         ;
1324
1325 declaration_list
1326         : declaration
1327         | declaration_list declaration
1328         ;
1329
1330 /* Macros */
1331
1332 function_macro
1333         : FUNCTION_MACRO
1334           {
1335                 $$ = g_strdup (yytext + strlen ("#define "));
1336           }
1337         ;
1338
1339 object_macro
1340         : OBJECT_MACRO
1341           {
1342                 $$ = g_strdup (yytext + strlen ("#define "));
1343           }
1344         ;
1345
1346 function_macro_define
1347         : function_macro '(' identifier_list ')'
1348         ;
1349
1350 object_macro_define
1351         : object_macro constant_expression
1352           {
1353                 if ($2->const_int_set || $2->const_double_set || $2->const_string != NULL) {
1354                         $2->ident = $1;
1355                         gi_source_scanner_add_symbol (scanner, $2);
1356                         gi_source_symbol_unref ($2);
1357                 }
1358           }
1359         ;
1360
1361 macro
1362         : function_macro_define
1363         | object_macro_define
1364         | error
1365         ;
1366
1367 %%
1368 static void
1369 yyerror (GISourceScanner *scanner, const char *s)
1370 {
1371   /* ignore errors while doing a macro scan as not all object macros
1372    * have valid expressions */
1373   if (!scanner->macro_scan)
1374     {
1375       fprintf(stderr, "%s:%d: %s in '%s' at '%s'\n",
1376               scanner->current_filename, lineno, s, linebuf, yytext);
1377     }
1378 }
1379
1380 static int
1381 eat_hspace (FILE * f)
1382 {
1383   int c;
1384   do
1385     {
1386       c = fgetc (f);
1387     }
1388   while (c == ' ' || c == '\t');
1389   return c;
1390 }
1391
1392 static int
1393 eat_line (FILE * f, int c)
1394 {
1395   while (c != EOF && c != '\n')
1396     {
1397       c = fgetc (f);
1398     }
1399   if (c == '\n')
1400     {
1401       c = fgetc (f);
1402       if (c == ' ' || c == '\t')
1403         {
1404           c = eat_hspace (f);
1405         }
1406     }
1407   return c;
1408 }
1409
1410 static int
1411 read_identifier (FILE * f, int c, char **identifier)
1412 {
1413   GString *id = g_string_new ("");
1414   while (g_ascii_isalnum (c) || c == '_')
1415     {
1416       g_string_append_c (id, c);
1417       c = fgetc (f);
1418     }
1419   *identifier = g_string_free (id, FALSE);
1420   return c;
1421 }
1422
1423 void
1424 gi_source_scanner_parse_macros (GISourceScanner *scanner, GList *filenames)
1425 {
1426   GError *error = NULL;
1427   char *tmp_name = NULL;
1428   FILE *fmacros =
1429     fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error),
1430             "w+");
1431   g_unlink (tmp_name);
1432
1433   GList *l;
1434   for (l = filenames; l != NULL; l = l->next)
1435     {
1436       FILE *f = fopen (l->data, "r");
1437       int line = 1;
1438
1439       GString *define_line;
1440       char *str;
1441       gboolean error_line = FALSE;
1442       int c = eat_hspace (f);
1443       while (c != EOF)
1444         {
1445           if (c != '#')
1446             {
1447               /* ignore line */
1448               c = eat_line (f, c);
1449               line++;
1450               continue;
1451             }
1452
1453           /* print current location */
1454           str = g_strescape (l->data, "");
1455           fprintf (fmacros, "# %d \"%s\"\n", line, str);
1456           g_free (str);
1457
1458           c = eat_hspace (f);
1459           c = read_identifier (f, c, &str);
1460           if (strcmp (str, "define") != 0 || (c != ' ' && c != '\t'))
1461             {
1462               g_free (str);
1463               /* ignore line */
1464               c = eat_line (f, c);
1465               line++;
1466               continue;
1467             }
1468           g_free (str);
1469           c = eat_hspace (f);
1470           c = read_identifier (f, c, &str);
1471           if (strlen (str) == 0 || (c != ' ' && c != '\t' && c != '('))
1472             {
1473               g_free (str);
1474               /* ignore line */
1475               c = eat_line (f, c);
1476               line++;
1477               continue;
1478             }
1479           define_line = g_string_new ("#define ");
1480           g_string_append (define_line, str);
1481           g_free (str);
1482           if (c == '(')
1483             {
1484               while (c != ')')
1485                 {
1486                   g_string_append_c (define_line, c);
1487                   c = fgetc (f);
1488                   if (c == EOF || c == '\n')
1489                     {
1490                       error_line = TRUE;
1491                       break;
1492                     }
1493                 }
1494               if (error_line)
1495                 {
1496                   g_string_free (define_line, TRUE);
1497                   /* ignore line */
1498                   c = eat_line (f, c);
1499                   line++;
1500                   continue;
1501                 }
1502
1503               g_assert (c == ')');
1504               g_string_append_c (define_line, c);
1505               c = fgetc (f);
1506
1507               /* found function-like macro */
1508               fprintf (fmacros, "%s\n", define_line->str);
1509
1510               g_string_free (define_line, TRUE);
1511               /* ignore rest of line */
1512               c = eat_line (f, c);
1513               line++;
1514               continue;
1515             }
1516           if (c != ' ' && c != '\t')
1517             {
1518               g_string_free (define_line, TRUE);
1519               /* ignore line */
1520               c = eat_line (f, c);
1521               line++;
1522               continue;
1523             }
1524           while (c != EOF && c != '\n')
1525             {
1526               g_string_append_c (define_line, c);
1527               c = fgetc (f);
1528               if (c == '\\')
1529                 {
1530                   c = fgetc (f);
1531                   if (c == '\n')
1532                     {
1533                       /* fold lines when seeing backslash new-line sequence */
1534                       c = fgetc (f);
1535                     }
1536                   else
1537                     {
1538                       g_string_append_c (define_line, '\\');
1539                     }
1540                 }
1541             }
1542
1543           /* found object-like macro */
1544           fprintf (fmacros, "%s\n", define_line->str);
1545
1546           c = eat_line (f, c);
1547           line++;
1548         }
1549
1550       fclose (f);
1551     }
1552
1553   rewind (fmacros);
1554   gi_source_scanner_parse_file (scanner, fmacros);
1555 }
1556
1557 gboolean
1558 gi_source_scanner_parse_file (GISourceScanner *scanner, FILE *file)
1559 {
1560   g_return_val_if_fail (file != NULL, FALSE);
1561
1562   const_table = g_hash_table_new_full (g_str_hash, g_str_equal,
1563                                        g_free, (GDestroyNotify)gi_source_symbol_unref);
1564
1565   lineno = 1;
1566   yyin = file;
1567   yyparse (scanner);
1568
1569   g_hash_table_destroy (const_table);
1570   const_table = NULL;
1571
1572   yyin = NULL;
1573
1574   return TRUE;
1575 }
1576
1577 gboolean
1578 gi_source_scanner_lex_filename (GISourceScanner *scanner, const gchar *filename)
1579 {
1580   lineno = 1;
1581   yyin = fopen (filename, "r");
1582
1583   while (yylex (scanner) != YYEOF)
1584     ;
1585
1586   fclose (yyin);
1587
1588   return TRUE;
1589 }