blob: 7d1c3ab927ff7572d317f3dcde27f534baf673ea [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 Worth48b94da2010-05-13 10:46:29 -0700112| SPACE { printf (" "); }
Carl Worthcd27e642010-05-12 13:11:50 -0700113;
114
Carl Worthfcbbb462010-05-13 09:36:23 -0700115macro:
116 FUNC_MACRO '(' argument_list ')' {
117 _print_expanded_function_macro (parser, $1, $3);
118 }
119| OBJ_MACRO {
120 _print_expanded_object_macro (parser, $1);
121 talloc_free ($1);
122 }
123;
124
125argument_list:
Carl Worthdb35d552010-05-14 08:47:32 -0700126 argument {
Carl Worthfcbbb462010-05-13 09:36:23 -0700127 $$ = _list_create (parser);
128 _list_append_list ($$, $1);
129 }
130| argument_list ',' argument {
131 _list_append_list ($1, $3);
132 $$ = $1;
133 }
134;
135
136argument:
137 /* empty */ {
138 $$ = _list_create (parser);
139 }
Carl Worth0a93cbb2010-05-13 10:29:07 -0700140| argument word {
Carl Worthfcbbb462010-05-13 09:36:23 -0700141 _list_append_item ($1, $2);
142 talloc_free ($2);
143 }
144| argument '(' argument ')'
145;
146
Carl Worthcd27e642010-05-12 13:11:50 -0700147directive_with_newline:
148 directive NEWLINE {
149 printf ("\n");
150 }
Carl Worth3a37b872010-05-10 11:44:09 -0700151;
152
Carl Worth33cc4002010-05-12 12:17:10 -0700153directive:
Carl Worth0a93cbb2010-05-13 10:29:07 -0700154 DEFINE IDENTIFIER {
155 list_t *list = _list_create (parser);
156 _define_object_macro (parser, $2, list);
157 }
158| DEFINE IDENTIFIER SPACE replacement_list {
159 _define_object_macro (parser, $2, $4);
Carl Worthcd27e642010-05-12 13:11:50 -0700160 }
Carl Worth48b94da2010-05-13 10:46:29 -0700161| DEFINE IDENTIFIER '(' parameter_list ')' {
162 list_t *list = _list_create (parser);
163 _define_function_macro (parser, $2, $4, list);
164 }
165| DEFINE IDENTIFIER '(' parameter_list ')' SPACE replacement_list {
166 _define_function_macro (parser, $2, $4, $7);
Carl Worthfcbbb462010-05-13 09:36:23 -0700167 }
168| UNDEF FUNC_MACRO {
169 list_t *replacement = hash_table_find (parser->defines, $2);
170 if (replacement) {
171 /* XXX: Need hash table to support a real way
172 * to remove an element rather than prefixing
173 * a new node with data of NULL like this. */
174 hash_table_insert (parser->defines, NULL, $2);
175 talloc_free (replacement);
176 }
177 talloc_free ($2);
178 }
179| UNDEF OBJ_MACRO {
Carl Worthcd27e642010-05-12 13:11:50 -0700180 list_t *replacement = hash_table_find (parser->defines, $2);
181 if (replacement) {
182 /* XXX: Need hash table to support a real way
183 * to remove an element rather than prefixing
184 * a new node with data of NULL like this. */
185 hash_table_insert (parser->defines, NULL, $2);
186 talloc_free (replacement);
187 }
188 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700189 }
190;
191
192replacement_list:
Carl Worth48b94da2010-05-13 10:46:29 -0700193 word_or_symbol {
Carl Worth33cc4002010-05-12 12:17:10 -0700194 $$ = _list_create (parser);
Carl Worth48b94da2010-05-13 10:46:29 -0700195 _list_append_item ($$, $1);
196 talloc_free ($1);
Carl Worth33cc4002010-05-12 12:17:10 -0700197 }
Carl Worth0a93cbb2010-05-13 10:29:07 -0700198| replacement_list word_or_symbol {
Carl Worthfcbbb462010-05-13 09:36:23 -0700199 _list_append_item ($1, $2);
Carl Worth5070a202010-05-12 12:45:33 -0700200 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700201 $$ = $1;
202 }
203;
204
Carl Worthfcbbb462010-05-13 09:36:23 -0700205parameter_list:
206 /* empty */ {
207 $$ = _list_create (parser);
208 }
209| IDENTIFIER {
210 $$ = _list_create (parser);
211 _list_append_item ($$, $1);
212 talloc_free ($1);
213 }
214| parameter_list ',' IDENTIFIER {
215 _list_append_item ($1, $3);
216 talloc_free ($3);
217 $$ = $1;
218 }
219;
220
Carl Worth0a93cbb2010-05-13 10:29:07 -0700221word_or_symbol:
222 word { $$ = $1; }
223| '(' { $$ = xtalloc_strdup (parser, "("); }
224| ')' { $$ = xtalloc_strdup (parser, ")"); }
225| ',' { $$ = xtalloc_strdup (parser, ","); }
Carl Worth48b94da2010-05-13 10:46:29 -0700226| SPACE { $$ = xtalloc_strdup (parser, " "); }
Carl Worth0a93cbb2010-05-13 10:29:07 -0700227;
228
229word:
Carl Worth9f62a7e2010-05-13 07:38:29 -0700230 IDENTIFIER { $$ = $1; }
Carl Worthfcbbb462010-05-13 09:36:23 -0700231| FUNC_MACRO { $$ = $1; }
232| OBJ_MACRO { $$ = $1; }
Carl Worth9f62a7e2010-05-13 07:38:29 -0700233| TOKEN { $$ = $1; }
Carl Worth33cc4002010-05-12 12:17:10 -0700234;
235
236%%
237
238list_t *
239_list_create (void *ctx)
240{
241 list_t *list;
242
Carl Worth5070a202010-05-12 12:45:33 -0700243 list = xtalloc (ctx, list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700244 list->head = NULL;
245 list->tail = NULL;
246
247 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700248}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700249
Carl Worth33cc4002010-05-12 12:17:10 -0700250void
Carl Worthfcbbb462010-05-13 09:36:23 -0700251_list_append_list (list_t *list, list_t *tail)
252{
253 if (list->head == NULL) {
254 list->head = tail->head;
255 } else {
256 list->tail->next = tail->head;
257 }
258
259 list->tail = tail->tail;
260}
261
262void
263_list_append_item (list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700264{
265 node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700266
Carl Worth5070a202010-05-12 12:45:33 -0700267 node = xtalloc (list, node_t);
268 node->str = xtalloc_strdup (node, str);
Carl Worth33cc4002010-05-12 12:17:10 -0700269
270 node->next = NULL;
271
272 if (list->head == NULL) {
273 list->head = node;
274 } else {
275 list->tail->next = node;
276 }
277
278 list->tail = node;
279}
280
Carl Worth3a37b872010-05-10 11:44:09 -0700281void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700282yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700283{
284 fprintf (stderr, "Parse error: %s\n", error);
285}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700286
Carl Worth33cc4002010-05-12 12:17:10 -0700287glcpp_parser_t *
288glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700289{
Carl Worth33cc4002010-05-12 12:17:10 -0700290 glcpp_parser_t *parser;
291
Carl Worth5070a202010-05-12 12:45:33 -0700292 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700293
Carl Worth5070a202010-05-12 12:45:33 -0700294 yylex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700295 parser->defines = hash_table_ctor (32, hash_table_string_hash,
296 hash_table_string_compare);
Carl Worth33cc4002010-05-12 12:17:10 -0700297
298 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700299}
300
301int
302glcpp_parser_parse (glcpp_parser_t *parser)
303{
304 return yyparse (parser);
305}
306
307void
Carl Worth33cc4002010-05-12 12:17:10 -0700308glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700309{
310 yylex_destroy (parser->scanner);
311 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700312 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700313}
Carl Worthc6d5af32010-05-11 12:30:09 -0700314
Carl Worthfcbbb462010-05-13 09:36:23 -0700315macro_type_t
316glcpp_parser_macro_type (glcpp_parser_t *parser, const char *identifier)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700317{
Carl Worthfcbbb462010-05-13 09:36:23 -0700318 macro_t *macro;
319
320 macro = hash_table_find (parser->defines, identifier);
321
322 if (macro == NULL)
323 return MACRO_TYPE_UNDEFINED;
324
325 if (macro->is_function)
326 return MACRO_TYPE_FUNCTION;
327 else
328 return MACRO_TYPE_OBJECT;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700329}
330
Carl Worth33cc4002010-05-12 12:17:10 -0700331static void
Carl Worth9f62a7e2010-05-13 07:38:29 -0700332_print_expanded_macro_recursive (glcpp_parser_t *parser,
333 const char *token,
Carl Worth48b94da2010-05-13 10:46:29 -0700334 const char *orig)
Carl Worthc6d5af32010-05-11 12:30:09 -0700335{
Carl Worthfcbbb462010-05-13 09:36:23 -0700336 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700337 node_t *node;
Carl Worthc6d5af32010-05-11 12:30:09 -0700338
Carl Worthfcbbb462010-05-13 09:36:23 -0700339 macro = hash_table_find (parser->defines, token);
340 if (macro == NULL) {
Carl Worth48b94da2010-05-13 10:46:29 -0700341 printf ("%s", token);
Carl Worth33cc4002010-05-12 12:17:10 -0700342 } else {
Carl Worthfcbbb462010-05-13 09:36:23 -0700343 list_t *replacement_list = macro->replacement_list;
344
345 for (node = replacement_list->head ; node ; node = node->next) {
Carl Worth33cc4002010-05-12 12:17:10 -0700346 token = node->str;
Carl Worth48b94da2010-05-13 10:46:29 -0700347 if (strcmp (token, orig) == 0)
348 printf ("%s", token);
349 else
Carl Worth9f62a7e2010-05-13 07:38:29 -0700350 _print_expanded_macro_recursive (parser,
Carl Worth48b94da2010-05-13 10:46:29 -0700351 token, orig);
Carl Worth33cc4002010-05-12 12:17:10 -0700352 }
Carl Worthc6d5af32010-05-11 12:30:09 -0700353 }
Carl Worthc6d5af32010-05-11 12:30:09 -0700354}
355
Carl Worth33cc4002010-05-12 12:17:10 -0700356void
Carl Worthfcbbb462010-05-13 09:36:23 -0700357_define_object_macro (glcpp_parser_t *parser,
358 const char *identifier,
359 list_t *replacement_list)
360{
361 macro_t *macro;
362
363 macro = xtalloc (parser, macro_t);
364
365 macro->is_function = 0;
366 macro->parameter_list = NULL;
367 macro->replacement_list = talloc_steal (macro, replacement_list);
368
369 hash_table_insert (parser->defines, macro, identifier);
370}
371
372void
373_define_function_macro (glcpp_parser_t *parser,
374 const char *identifier,
375 list_t *parameter_list,
376 list_t *replacement_list)
377{
378 macro_t *macro;
379
380 macro = xtalloc (parser, macro_t);
381
382 macro->is_function = 1;
383 macro->parameter_list = talloc_steal (macro, parameter_list);
384 macro->replacement_list = talloc_steal (macro, replacement_list);
385
386 hash_table_insert (parser->defines, macro, identifier);
387}
388
389void
390_print_expanded_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700391{
Carl Worthfcbbb462010-05-13 09:36:23 -0700392 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700393
Carl Worthfcbbb462010-05-13 09:36:23 -0700394 macro = hash_table_find (parser->defines, identifier);
395 assert (! macro->is_function);
396
Carl Worth48b94da2010-05-13 10:46:29 -0700397 _print_expanded_macro_recursive (parser, identifier, identifier);
Carl Worthfcbbb462010-05-13 09:36:23 -0700398}
399
400void
401_print_expanded_function_macro (glcpp_parser_t *parser,
402 const char *identifier,
403 list_t *arguments)
404{
Carl Worthfcbbb462010-05-13 09:36:23 -0700405 macro_t *macro;
406
407 macro = hash_table_find (parser->defines, identifier);
408 assert (macro->is_function);
409
410 /* XXX: Need to use argument list here in the expansion. */
411
Carl Worth48b94da2010-05-13 10:46:29 -0700412 _print_expanded_macro_recursive (parser, identifier, identifier);
Carl Worth33cc4002010-05-12 12:17:10 -0700413}