blob: dc352de55b65a218bb8b1aa1b9f250eb01afb7ac [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 Worth0a93cbb2010-05-13 10:29:07 -070086%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO SPACE TOKEN UNDEF
87%type <str> FUNC_MACRO IDENTIFIER OBJ_MACRO TOKEN word word_or_symbol
Carl Worthfcbbb462010-05-13 09:36:23 -070088%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 Worth0a93cbb2010-05-13 10:29:07 -0700108| NEWLINE { printf ("\n"); }
109| '(' { printf ("("); }
110| ')' { printf (")"); }
111| ',' { printf (","); }
Carl Worthcd27e642010-05-12 13:11:50 -0700112;
113
Carl Worthfcbbb462010-05-13 09:36:23 -0700114macro:
115 FUNC_MACRO '(' argument_list ')' {
116 _print_expanded_function_macro (parser, $1, $3);
117 }
118| OBJ_MACRO {
119 _print_expanded_object_macro (parser, $1);
120 talloc_free ($1);
121 }
122;
123
124argument_list:
Carl Worthdb35d552010-05-14 08:47:32 -0700125 argument {
Carl Worthfcbbb462010-05-13 09:36:23 -0700126 $$ = _list_create (parser);
127 _list_append_list ($$, $1);
128 }
129| argument_list ',' argument {
130 _list_append_list ($1, $3);
131 $$ = $1;
132 }
133;
134
135argument:
136 /* empty */ {
137 $$ = _list_create (parser);
138 }
Carl Worth0a93cbb2010-05-13 10:29:07 -0700139| argument word {
Carl Worthfcbbb462010-05-13 09:36:23 -0700140 _list_append_item ($1, $2);
141 talloc_free ($2);
142 }
143| argument '(' argument ')'
144;
145
Carl Worthcd27e642010-05-12 13:11:50 -0700146directive_with_newline:
147 directive NEWLINE {
148 printf ("\n");
149 }
Carl Worth3a37b872010-05-10 11:44:09 -0700150;
151
Carl Worth33cc4002010-05-12 12:17:10 -0700152directive:
Carl Worth0a93cbb2010-05-13 10:29:07 -0700153 DEFINE IDENTIFIER {
154 list_t *list = _list_create (parser);
155 _define_object_macro (parser, $2, list);
156 }
157| DEFINE IDENTIFIER SPACE replacement_list {
158 _define_object_macro (parser, $2, $4);
Carl Worthcd27e642010-05-12 13:11:50 -0700159 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700160| DEFINE IDENTIFIER '(' parameter_list ')' replacement_list {
161 _define_function_macro (parser, $2, $4, $6);
162 }
163| UNDEF FUNC_MACRO {
164 list_t *replacement = hash_table_find (parser->defines, $2);
165 if (replacement) {
166 /* XXX: Need hash table to support a real way
167 * to remove an element rather than prefixing
168 * a new node with data of NULL like this. */
169 hash_table_insert (parser->defines, NULL, $2);
170 talloc_free (replacement);
171 }
172 talloc_free ($2);
173 }
174| UNDEF OBJ_MACRO {
Carl Worthcd27e642010-05-12 13:11:50 -0700175 list_t *replacement = hash_table_find (parser->defines, $2);
176 if (replacement) {
177 /* XXX: Need hash table to support a real way
178 * to remove an element rather than prefixing
179 * a new node with data of NULL like this. */
180 hash_table_insert (parser->defines, NULL, $2);
181 talloc_free (replacement);
182 }
183 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700184 }
185;
186
187replacement_list:
188 /* empty */ {
189 $$ = _list_create (parser);
190 }
Carl Worth0a93cbb2010-05-13 10:29:07 -0700191| replacement_list word_or_symbol {
Carl Worthfcbbb462010-05-13 09:36:23 -0700192 _list_append_item ($1, $2);
Carl Worth5070a202010-05-12 12:45:33 -0700193 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700194 $$ = $1;
195 }
196;
197
Carl Worthfcbbb462010-05-13 09:36:23 -0700198parameter_list:
199 /* empty */ {
200 $$ = _list_create (parser);
201 }
202| IDENTIFIER {
203 $$ = _list_create (parser);
204 _list_append_item ($$, $1);
205 talloc_free ($1);
206 }
207| parameter_list ',' IDENTIFIER {
208 _list_append_item ($1, $3);
209 talloc_free ($3);
210 $$ = $1;
211 }
212;
213
Carl Worth0a93cbb2010-05-13 10:29:07 -0700214word_or_symbol:
215 word { $$ = $1; }
216| '(' { $$ = xtalloc_strdup (parser, "("); }
217| ')' { $$ = xtalloc_strdup (parser, ")"); }
218| ',' { $$ = xtalloc_strdup (parser, ","); }
219;
220
221word:
Carl Worth9f62a7e2010-05-13 07:38:29 -0700222 IDENTIFIER { $$ = $1; }
Carl Worthfcbbb462010-05-13 09:36:23 -0700223| FUNC_MACRO { $$ = $1; }
224| OBJ_MACRO { $$ = $1; }
Carl Worth9f62a7e2010-05-13 07:38:29 -0700225| TOKEN { $$ = $1; }
Carl Worth33cc4002010-05-12 12:17:10 -0700226;
227
228%%
229
230list_t *
231_list_create (void *ctx)
232{
233 list_t *list;
234
Carl Worth5070a202010-05-12 12:45:33 -0700235 list = xtalloc (ctx, list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700236 list->head = NULL;
237 list->tail = NULL;
238
239 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700240}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700241
Carl Worth33cc4002010-05-12 12:17:10 -0700242void
Carl Worthfcbbb462010-05-13 09:36:23 -0700243_list_append_list (list_t *list, list_t *tail)
244{
245 if (list->head == NULL) {
246 list->head = tail->head;
247 } else {
248 list->tail->next = tail->head;
249 }
250
251 list->tail = tail->tail;
252}
253
254void
255_list_append_item (list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700256{
257 node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700258
Carl Worth5070a202010-05-12 12:45:33 -0700259 node = xtalloc (list, node_t);
260 node->str = xtalloc_strdup (node, str);
Carl Worth33cc4002010-05-12 12:17:10 -0700261
262 node->next = NULL;
263
264 if (list->head == NULL) {
265 list->head = node;
266 } else {
267 list->tail->next = node;
268 }
269
270 list->tail = node;
271}
272
Carl Worth3a37b872010-05-10 11:44:09 -0700273void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700274yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700275{
276 fprintf (stderr, "Parse error: %s\n", error);
277}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700278
Carl Worth33cc4002010-05-12 12:17:10 -0700279glcpp_parser_t *
280glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700281{
Carl Worth33cc4002010-05-12 12:17:10 -0700282 glcpp_parser_t *parser;
283
Carl Worth5070a202010-05-12 12:45:33 -0700284 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700285
Carl Worth5070a202010-05-12 12:45:33 -0700286 yylex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700287 parser->defines = hash_table_ctor (32, hash_table_string_hash,
288 hash_table_string_compare);
Carl Worth33cc4002010-05-12 12:17:10 -0700289
290 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700291}
292
293int
294glcpp_parser_parse (glcpp_parser_t *parser)
295{
296 return yyparse (parser);
297}
298
299void
Carl Worth33cc4002010-05-12 12:17:10 -0700300glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700301{
302 yylex_destroy (parser->scanner);
303 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700304 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700305}
Carl Worthc6d5af32010-05-11 12:30:09 -0700306
Carl Worthfcbbb462010-05-13 09:36:23 -0700307macro_type_t
308glcpp_parser_macro_type (glcpp_parser_t *parser, const char *identifier)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700309{
Carl Worthfcbbb462010-05-13 09:36:23 -0700310 macro_t *macro;
311
312 macro = hash_table_find (parser->defines, identifier);
313
314 if (macro == NULL)
315 return MACRO_TYPE_UNDEFINED;
316
317 if (macro->is_function)
318 return MACRO_TYPE_FUNCTION;
319 else
320 return MACRO_TYPE_OBJECT;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700321}
322
Carl Worth33cc4002010-05-12 12:17:10 -0700323static void
Carl Worth9f62a7e2010-05-13 07:38:29 -0700324_print_expanded_macro_recursive (glcpp_parser_t *parser,
325 const char *token,
326 const char *orig,
327 int *first)
Carl Worthc6d5af32010-05-11 12:30:09 -0700328{
Carl Worthfcbbb462010-05-13 09:36:23 -0700329 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700330 node_t *node;
Carl Worthc6d5af32010-05-11 12:30:09 -0700331
Carl Worthfcbbb462010-05-13 09:36:23 -0700332 macro = hash_table_find (parser->defines, token);
333 if (macro == NULL) {
Carl Worth33cc4002010-05-12 12:17:10 -0700334 printf ("%s%s", *first ? "" : " ", token);
335 *first = 0;
336 } else {
Carl Worthfcbbb462010-05-13 09:36:23 -0700337 list_t *replacement_list = macro->replacement_list;
338
339 for (node = replacement_list->head ; node ; node = node->next) {
Carl Worth33cc4002010-05-12 12:17:10 -0700340 token = node->str;
341 if (strcmp (token, orig) == 0) {
342 printf ("%s%s", *first ? "" : " ", token);
343 *first = 0;
344 } else {
Carl Worth9f62a7e2010-05-13 07:38:29 -0700345 _print_expanded_macro_recursive (parser,
346 token, orig,
347 first);
Carl Worth33cc4002010-05-12 12:17:10 -0700348 }
349 }
Carl Worthc6d5af32010-05-11 12:30:09 -0700350 }
Carl Worthc6d5af32010-05-11 12:30:09 -0700351}
352
Carl Worth33cc4002010-05-12 12:17:10 -0700353void
Carl Worthfcbbb462010-05-13 09:36:23 -0700354_define_object_macro (glcpp_parser_t *parser,
355 const char *identifier,
356 list_t *replacement_list)
357{
358 macro_t *macro;
359
360 macro = xtalloc (parser, macro_t);
361
362 macro->is_function = 0;
363 macro->parameter_list = NULL;
364 macro->replacement_list = talloc_steal (macro, replacement_list);
365
366 hash_table_insert (parser->defines, macro, identifier);
367}
368
369void
370_define_function_macro (glcpp_parser_t *parser,
371 const char *identifier,
372 list_t *parameter_list,
373 list_t *replacement_list)
374{
375 macro_t *macro;
376
377 macro = xtalloc (parser, macro_t);
378
379 macro->is_function = 1;
380 macro->parameter_list = talloc_steal (macro, parameter_list);
381 macro->replacement_list = talloc_steal (macro, replacement_list);
382
383 hash_table_insert (parser->defines, macro, identifier);
384}
385
386void
387_print_expanded_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700388{
389 int first = 1;
Carl Worthfcbbb462010-05-13 09:36:23 -0700390 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700391
Carl Worthfcbbb462010-05-13 09:36:23 -0700392 macro = hash_table_find (parser->defines, identifier);
393 assert (! macro->is_function);
394
395 _print_expanded_macro_recursive (parser, identifier, identifier, &first);
396}
397
398void
399_print_expanded_function_macro (glcpp_parser_t *parser,
400 const char *identifier,
401 list_t *arguments)
402{
403 int first = 1;
404 macro_t *macro;
405
406 macro = hash_table_find (parser->defines, identifier);
407 assert (macro->is_function);
408
409 /* XXX: Need to use argument list here in the expansion. */
410
411 _print_expanded_macro_recursive (parser, identifier, identifier, &first);
Carl Worth33cc4002010-05-12 12:17:10 -0700412}