Fix defines involving both literals and other defined macros.
[mesa.git] / glcpp-parse.y
1 %{
2 /*
3 * Copyright © 2010 Intel Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <talloc.h>
28
29 #include "glcpp.h"
30
31 #define YYLEX_PARAM parser->scanner
32
33 struct glcpp_parser {
34 yyscan_t scanner;
35 struct hash_table *defines;
36 };
37
38 void
39 yyerror (void *scanner, const char *error);
40
41 void
42 _print_resolved_token (glcpp_parser_t *parser, const char *token);
43
44 list_t *
45 _list_create (void *ctx);
46
47 void
48 _list_append (list_t *list, const char *str);
49
50 %}
51
52 %union {
53 char *str;
54 list_t *list;
55 }
56
57 %parse-param {glcpp_parser_t *parser}
58 %lex-param {void *scanner}
59
60 %token DEFINE IDENTIFIER NEWLINE TOKEN
61 %type <str> token IDENTIFIER TOKEN
62 %type <list> replacement_list
63
64 %%
65
66 input:
67 /* empty */
68 | content
69 ;
70
71 content:
72 token {
73 _print_resolved_token (parser, $1);
74 free ($1);
75 }
76 | directive
77 | content token {
78 _print_resolved_token (parser, $2);
79 free ($2);
80 }
81 | content directive
82 ;
83
84 directive:
85 DEFINE IDENTIFIER replacement_list NEWLINE {
86 char *key = talloc_strdup ($3, $2);
87 free ($2);
88 hash_table_insert (parser->defines, $3, key);
89 printf ("\n");
90 }
91 ;
92
93 replacement_list:
94 /* empty */ {
95 $$ = _list_create (parser);
96 }
97
98 | replacement_list token {
99 _list_append ($1, $2);
100 free ($2);
101 $$ = $1;
102 }
103 ;
104
105 token:
106 TOKEN { $$ = $1; }
107 | IDENTIFIER { $$ = $1; }
108 ;
109
110 %%
111
112 list_t *
113 _list_create (void *ctx)
114 {
115 list_t *list;
116
117 list = talloc (ctx, list_t);
118 if (list == NULL) {
119 fprintf (stderr, "Out of memory.\n");
120 exit (1);
121 }
122
123 list->head = NULL;
124 list->tail = NULL;
125
126 return list;
127 }
128
129 void
130 _list_append (list_t *list, const char *str)
131 {
132 node_t *node;
133
134 node = talloc (list, node_t);
135 if (node == NULL) {
136 fprintf (stderr, "Out of memory.\n");
137 exit (1);
138 }
139
140 node->str = talloc_strdup (node, str);
141 if (node->str == NULL) {
142 fprintf (stderr, "Out of memory.\n");
143 exit (1);
144 }
145
146 node->next = NULL;
147
148 if (list->head == NULL) {
149 list->head = node;
150 } else {
151 list->tail->next = node;
152 }
153
154 list->tail = node;
155 }
156
157 void
158 yyerror (void *scanner, const char *error)
159 {
160 fprintf (stderr, "Parse error: %s\n", error);
161 }
162
163 glcpp_parser_t *
164 glcpp_parser_create (void)
165 {
166 glcpp_parser_t *parser;
167
168 parser = talloc (NULL, glcpp_parser_t);
169 if (parser == NULL) {
170 fprintf (stderr, "Out of memory.\n");
171 exit (1);
172 }
173
174 yylex_init (&parser->scanner);
175 parser->defines = hash_table_ctor (32, hash_table_string_hash,
176 hash_table_string_compare);
177
178 return parser;
179 }
180
181 int
182 glcpp_parser_parse (glcpp_parser_t *parser)
183 {
184 return yyparse (parser);
185 }
186
187 void
188 glcpp_parser_destroy (glcpp_parser_t *parser)
189 {
190 yylex_destroy (parser->scanner);
191 hash_table_dtor (parser->defines);
192 talloc_free (parser);
193 }
194
195 static void
196 _print_resolved_recursive (glcpp_parser_t *parser,
197 const char *token,
198 const char *orig,
199 int *first)
200 {
201 list_t *replacement;
202 node_t *node;
203
204 replacement = hash_table_find (parser->defines, token);
205 if (replacement == NULL) {
206 printf ("%s%s", *first ? "" : " ", token);
207 *first = 0;
208 } else {
209 for (node = replacement->head ; node ; node = node->next) {
210 token = node->str;
211 if (strcmp (token, orig) == 0) {
212 printf ("%s%s", *first ? "" : " ", token);
213 *first = 0;
214 } else {
215 _print_resolved_recursive (parser, token, orig, first);
216 }
217 }
218 }
219 }
220
221 void
222 _print_resolved_token (glcpp_parser_t *parser, const char *token)
223 {
224 int first = 1;
225
226 _print_resolved_recursive (parser, token, token, &first);
227 }