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