blob: 66725db69edf50e71f0baed5507970a91ced2d17 [file] [log] [blame]
Carl Worth3a37b872010-05-10 11:44:09 -07001%{
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>
Carl Worthfcbbb462010-05-13 09:36:23 -070027#include <assert.h>
Carl Worth33cc4002010-05-12 12:17:10 -070028#include <talloc.h>
Carl Worth3a37b872010-05-10 11:44:09 -070029
Carl Wortha1e32bc2010-05-10 13:17:25 -070030#include "glcpp.h"
31
Carl Worth0b27b5f2010-05-10 16:16:06 -070032#define YYLEX_PARAM parser->scanner
Carl Worth3a37b872010-05-10 11:44:09 -070033
Carl Worthfcbbb462010-05-13 09:36:23 -070034typedef struct {
35 int is_function;
36 list_t *parameter_list;
37 list_t *replacement_list;
38} macro_t;
39
Carl Worth33cc4002010-05-12 12:17:10 -070040struct glcpp_parser {
41 yyscan_t scanner;
42 struct hash_table *defines;
43};
44
Carl Worth3a37b872010-05-10 11:44:09 -070045void
Carl Wortha1e32bc2010-05-10 13:17:25 -070046yyerror (void *scanner, const char *error);
Carl Worth3a37b872010-05-10 11:44:09 -070047
Carl Worth33cc4002010-05-12 12:17:10 -070048void
Carl Worthfcbbb462010-05-13 09:36:23 -070049_define_object_macro (glcpp_parser_t *parser,
50 const char *macro,
51 list_t *replacement_list);
52
53void
54_define_function_macro (glcpp_parser_t *parser,
55 const char *macro,
56 list_t *parameter_list,
57 list_t *replacement_list);
58
59void
60_print_expanded_object_macro (glcpp_parser_t *parser, const char *macro);
61
62void
63_print_expanded_function_macro (glcpp_parser_t *parser,
64 const char *macro,
65 list_t *arguments);
Carl Worth33cc4002010-05-12 12:17:10 -070066
67list_t *
68_list_create (void *ctx);
69
70void
Carl Worthfcbbb462010-05-13 09:36:23 -070071_list_append_item (list_t *list, const char *str);
72
73void
74_list_append_list (list_t *list, list_t *tail);
Carl Worthc6d5af32010-05-11 12:30:09 -070075
Carl Worth3a37b872010-05-10 11:44:09 -070076%}
77
Carl Worth33cc4002010-05-12 12:17:10 -070078%union {
79 char *str;
80 list_t *list;
81}
82
Carl Worth0b27b5f2010-05-10 16:16:06 -070083%parse-param {glcpp_parser_t *parser}
Carl Worth38aa8352010-05-10 11:52:29 -070084%lex-param {void *scanner}
85
Carl Worthfcbbb462010-05-13 09:36:23 -070086%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO TOKEN UNDEF
87%type <str> FUNC_MACRO IDENTIFIER OBJ_MACRO TOKEN string
88%type <list> argument argument_list parameter_list replacement_list
Carl Worth3a37b872010-05-10 11:44:09 -070089
90%%
91
Carl Worth33cc4002010-05-12 12:17:10 -070092input:
93 /* empty */
Carl Worth8bcb6f12010-05-12 13:21:20 -070094| input content
Carl Worth3a37b872010-05-10 11:44:09 -070095;
96
Carl Worth33cc4002010-05-12 12:17:10 -070097content:
Carl Worth9f62a7e2010-05-13 07:38:29 -070098 IDENTIFIER {
99 printf ("%s", $1);
100 talloc_free ($1);
101 }
102| TOKEN {
103 printf ("%s", $1);
104 talloc_free ($1);
105 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700106| macro
Carl Worthcd27e642010-05-12 13:11:50 -0700107| directive_with_newline
Carl Worth012295f2010-05-12 13:19:23 -0700108| NEWLINE {
109 printf ("\n");
110 }
Carl Worthcd27e642010-05-12 13:11:50 -0700111;
112
Carl Worthfcbbb462010-05-13 09:36:23 -0700113macro:
114 FUNC_MACRO '(' argument_list ')' {
115 _print_expanded_function_macro (parser, $1, $3);
116 }
117| OBJ_MACRO {
118 _print_expanded_object_macro (parser, $1);
119 talloc_free ($1);
120 }
121;
122
123argument_list:
Carl Worthdb35d552010-05-14 08:47:32 -0700124 argument {
Carl Worthfcbbb462010-05-13 09:36:23 -0700125 $$ = _list_create (parser);
126 _list_append_list ($$, $1);
127 }
128| argument_list ',' argument {
129 _list_append_list ($1, $3);
130 $$ = $1;
131 }
132;
133
134argument:
135 /* empty */ {
136 $$ = _list_create (parser);
137 }
138| argument string {
139 _list_append_item ($1, $2);
140 talloc_free ($2);
141 }
142| argument '(' argument ')'
143;
144
Carl Worthcd27e642010-05-12 13:11:50 -0700145directive_with_newline:
146 directive NEWLINE {
147 printf ("\n");
148 }
Carl Worth3a37b872010-05-10 11:44:09 -0700149;
150
Carl Worth33cc4002010-05-12 12:17:10 -0700151directive:
Carl Worthcd27e642010-05-12 13:11:50 -0700152 DEFINE IDENTIFIER replacement_list {
Carl Worthfcbbb462010-05-13 09:36:23 -0700153 _define_object_macro (parser, $2, $3);
Carl Worthcd27e642010-05-12 13:11:50 -0700154 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700155| DEFINE IDENTIFIER '(' parameter_list ')' replacement_list {
156 _define_function_macro (parser, $2, $4, $6);
157 }
158| UNDEF FUNC_MACRO {
159 list_t *replacement = hash_table_find (parser->defines, $2);
160 if (replacement) {
161 /* XXX: Need hash table to support a real way
162 * to remove an element rather than prefixing
163 * a new node with data of NULL like this. */
164 hash_table_insert (parser->defines, NULL, $2);
165 talloc_free (replacement);
166 }
167 talloc_free ($2);
168 }
169| UNDEF OBJ_MACRO {
Carl Worthcd27e642010-05-12 13:11:50 -0700170 list_t *replacement = hash_table_find (parser->defines, $2);
171 if (replacement) {
172 /* XXX: Need hash table to support a real way
173 * to remove an element rather than prefixing
174 * a new node with data of NULL like this. */
175 hash_table_insert (parser->defines, NULL, $2);
176 talloc_free (replacement);
177 }
178 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700179 }
180;
181
182replacement_list:
183 /* empty */ {
184 $$ = _list_create (parser);
185 }
Carl Worth9f62a7e2010-05-13 07:38:29 -0700186| replacement_list string {
Carl Worthfcbbb462010-05-13 09:36:23 -0700187 _list_append_item ($1, $2);
Carl Worth5070a202010-05-12 12:45:33 -0700188 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700189 $$ = $1;
190 }
191;
192
Carl Worthfcbbb462010-05-13 09:36:23 -0700193parameter_list:
194 /* empty */ {
195 $$ = _list_create (parser);
196 }
197| IDENTIFIER {
198 $$ = _list_create (parser);
199 _list_append_item ($$, $1);
200 talloc_free ($1);
201 }
202| parameter_list ',' IDENTIFIER {
203 _list_append_item ($1, $3);
204 talloc_free ($3);
205 $$ = $1;
206 }
207;
208
Carl Worth9f62a7e2010-05-13 07:38:29 -0700209string:
210 IDENTIFIER { $$ = $1; }
Carl Worthfcbbb462010-05-13 09:36:23 -0700211| FUNC_MACRO { $$ = $1; }
212| OBJ_MACRO { $$ = $1; }
Carl Worth9f62a7e2010-05-13 07:38:29 -0700213| TOKEN { $$ = $1; }
Carl Worth33cc4002010-05-12 12:17:10 -0700214;
215
216%%
217
218list_t *
219_list_create (void *ctx)
220{
221 list_t *list;
222
Carl Worth5070a202010-05-12 12:45:33 -0700223 list = xtalloc (ctx, list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700224 list->head = NULL;
225 list->tail = NULL;
226
227 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700228}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700229
Carl Worth33cc4002010-05-12 12:17:10 -0700230void
Carl Worthfcbbb462010-05-13 09:36:23 -0700231_list_append_list (list_t *list, list_t *tail)
232{
233 if (list->head == NULL) {
234 list->head = tail->head;
235 } else {
236 list->tail->next = tail->head;
237 }
238
239 list->tail = tail->tail;
240}
241
242void
243_list_append_item (list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700244{
245 node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700246
Carl Worth5070a202010-05-12 12:45:33 -0700247 node = xtalloc (list, node_t);
248 node->str = xtalloc_strdup (node, str);
Carl Worth33cc4002010-05-12 12:17:10 -0700249
250 node->next = NULL;
251
252 if (list->head == NULL) {
253 list->head = node;
254 } else {
255 list->tail->next = node;
256 }
257
258 list->tail = node;
259}
260
Carl Worth3a37b872010-05-10 11:44:09 -0700261void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700262yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700263{
264 fprintf (stderr, "Parse error: %s\n", error);
265}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700266
Carl Worth33cc4002010-05-12 12:17:10 -0700267glcpp_parser_t *
268glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700269{
Carl Worth33cc4002010-05-12 12:17:10 -0700270 glcpp_parser_t *parser;
271
Carl Worth5070a202010-05-12 12:45:33 -0700272 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700273
Carl Worth5070a202010-05-12 12:45:33 -0700274 yylex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700275 parser->defines = hash_table_ctor (32, hash_table_string_hash,
276 hash_table_string_compare);
Carl Worth33cc4002010-05-12 12:17:10 -0700277
278 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700279}
280
281int
282glcpp_parser_parse (glcpp_parser_t *parser)
283{
284 return yyparse (parser);
285}
286
287void
Carl Worth33cc4002010-05-12 12:17:10 -0700288glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700289{
290 yylex_destroy (parser->scanner);
291 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700292 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700293}
Carl Worthc6d5af32010-05-11 12:30:09 -0700294
Carl Worthfcbbb462010-05-13 09:36:23 -0700295macro_type_t
296glcpp_parser_macro_type (glcpp_parser_t *parser, const char *identifier)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700297{
Carl Worthfcbbb462010-05-13 09:36:23 -0700298 macro_t *macro;
299
300 macro = hash_table_find (parser->defines, identifier);
301
302 if (macro == NULL)
303 return MACRO_TYPE_UNDEFINED;
304
305 if (macro->is_function)
306 return MACRO_TYPE_FUNCTION;
307 else
308 return MACRO_TYPE_OBJECT;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700309}
310
Carl Worth33cc4002010-05-12 12:17:10 -0700311static void
Carl Worth9f62a7e2010-05-13 07:38:29 -0700312_print_expanded_macro_recursive (glcpp_parser_t *parser,
313 const char *token,
314 const char *orig,
315 int *first)
Carl Worthc6d5af32010-05-11 12:30:09 -0700316{
Carl Worthfcbbb462010-05-13 09:36:23 -0700317 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700318 node_t *node;
Carl Worthc6d5af32010-05-11 12:30:09 -0700319
Carl Worthfcbbb462010-05-13 09:36:23 -0700320 macro = hash_table_find (parser->defines, token);
321 if (macro == NULL) {
Carl Worth33cc4002010-05-12 12:17:10 -0700322 printf ("%s%s", *first ? "" : " ", token);
323 *first = 0;
324 } else {
Carl Worthfcbbb462010-05-13 09:36:23 -0700325 list_t *replacement_list = macro->replacement_list;
326
327 for (node = replacement_list->head ; node ; node = node->next) {
Carl Worth33cc4002010-05-12 12:17:10 -0700328 token = node->str;
329 if (strcmp (token, orig) == 0) {
330 printf ("%s%s", *first ? "" : " ", token);
331 *first = 0;
332 } else {
Carl Worth9f62a7e2010-05-13 07:38:29 -0700333 _print_expanded_macro_recursive (parser,
334 token, orig,
335 first);
Carl Worth33cc4002010-05-12 12:17:10 -0700336 }
337 }
Carl Worthc6d5af32010-05-11 12:30:09 -0700338 }
Carl Worthc6d5af32010-05-11 12:30:09 -0700339}
340
Carl Worth33cc4002010-05-12 12:17:10 -0700341void
Carl Worthfcbbb462010-05-13 09:36:23 -0700342_define_object_macro (glcpp_parser_t *parser,
343 const char *identifier,
344 list_t *replacement_list)
345{
346 macro_t *macro;
347
348 macro = xtalloc (parser, macro_t);
349
350 macro->is_function = 0;
351 macro->parameter_list = NULL;
352 macro->replacement_list = talloc_steal (macro, replacement_list);
353
354 hash_table_insert (parser->defines, macro, identifier);
355}
356
357void
358_define_function_macro (glcpp_parser_t *parser,
359 const char *identifier,
360 list_t *parameter_list,
361 list_t *replacement_list)
362{
363 macro_t *macro;
364
365 macro = xtalloc (parser, macro_t);
366
367 macro->is_function = 1;
368 macro->parameter_list = talloc_steal (macro, parameter_list);
369 macro->replacement_list = talloc_steal (macro, replacement_list);
370
371 hash_table_insert (parser->defines, macro, identifier);
372}
373
374void
375_print_expanded_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700376{
377 int first = 1;
Carl Worthfcbbb462010-05-13 09:36:23 -0700378 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700379
Carl Worthfcbbb462010-05-13 09:36:23 -0700380 macro = hash_table_find (parser->defines, identifier);
381 assert (! macro->is_function);
382
383 _print_expanded_macro_recursive (parser, identifier, identifier, &first);
384}
385
386void
387_print_expanded_function_macro (glcpp_parser_t *parser,
388 const char *identifier,
389 list_t *arguments)
390{
391 int first = 1;
392 macro_t *macro;
393
394 macro = hash_table_find (parser->defines, identifier);
395 assert (macro->is_function);
396
397 /* XXX: Need to use argument list here in the expansion. */
398
399 _print_expanded_macro_recursive (parser, identifier, identifier, &first);
Carl Worth33cc4002010-05-12 12:17:10 -0700400}