blob: 2e40db525b8ec02ae167c8cb46c8692d083c214e [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:
124 /* empty */ {
125 $$ = _list_create (parser);
126 }
127| argument {
128 $$ = _list_create (parser);
129 _list_append_list ($$, $1);
130 }
131| argument_list ',' argument {
132 _list_append_list ($1, $3);
133 $$ = $1;
134 }
135;
136
137argument:
138 /* empty */ {
139 $$ = _list_create (parser);
140 }
141| argument string {
142 _list_append_item ($1, $2);
143 talloc_free ($2);
144 }
145| argument '(' argument ')'
146;
147
Carl Worthcd27e642010-05-12 13:11:50 -0700148directive_with_newline:
149 directive NEWLINE {
150 printf ("\n");
151 }
Carl Worth3a37b872010-05-10 11:44:09 -0700152;
153
Carl Worth33cc4002010-05-12 12:17:10 -0700154directive:
Carl Worthcd27e642010-05-12 13:11:50 -0700155 DEFINE IDENTIFIER replacement_list {
Carl Worthfcbbb462010-05-13 09:36:23 -0700156 _define_object_macro (parser, $2, $3);
Carl Worthcd27e642010-05-12 13:11:50 -0700157 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700158| DEFINE IDENTIFIER '(' parameter_list ')' replacement_list {
159 _define_function_macro (parser, $2, $4, $6);
160 }
161| UNDEF FUNC_MACRO {
162 list_t *replacement = hash_table_find (parser->defines, $2);
163 if (replacement) {
164 /* XXX: Need hash table to support a real way
165 * to remove an element rather than prefixing
166 * a new node with data of NULL like this. */
167 hash_table_insert (parser->defines, NULL, $2);
168 talloc_free (replacement);
169 }
170 talloc_free ($2);
171 }
172| UNDEF OBJ_MACRO {
Carl Worthcd27e642010-05-12 13:11:50 -0700173 list_t *replacement = hash_table_find (parser->defines, $2);
174 if (replacement) {
175 /* XXX: Need hash table to support a real way
176 * to remove an element rather than prefixing
177 * a new node with data of NULL like this. */
178 hash_table_insert (parser->defines, NULL, $2);
179 talloc_free (replacement);
180 }
181 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700182 }
183;
184
185replacement_list:
186 /* empty */ {
187 $$ = _list_create (parser);
188 }
Carl Worth9f62a7e2010-05-13 07:38:29 -0700189| replacement_list string {
Carl Worthfcbbb462010-05-13 09:36:23 -0700190 _list_append_item ($1, $2);
Carl Worth5070a202010-05-12 12:45:33 -0700191 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700192 $$ = $1;
193 }
194;
195
Carl Worthfcbbb462010-05-13 09:36:23 -0700196parameter_list:
197 /* empty */ {
198 $$ = _list_create (parser);
199 }
200| IDENTIFIER {
201 $$ = _list_create (parser);
202 _list_append_item ($$, $1);
203 talloc_free ($1);
204 }
205| parameter_list ',' IDENTIFIER {
206 _list_append_item ($1, $3);
207 talloc_free ($3);
208 $$ = $1;
209 }
210;
211
Carl Worth9f62a7e2010-05-13 07:38:29 -0700212string:
213 IDENTIFIER { $$ = $1; }
Carl Worthfcbbb462010-05-13 09:36:23 -0700214| FUNC_MACRO { $$ = $1; }
215| OBJ_MACRO { $$ = $1; }
Carl Worth9f62a7e2010-05-13 07:38:29 -0700216| TOKEN { $$ = $1; }
Carl Worth33cc4002010-05-12 12:17:10 -0700217;
218
219%%
220
221list_t *
222_list_create (void *ctx)
223{
224 list_t *list;
225
Carl Worth5070a202010-05-12 12:45:33 -0700226 list = xtalloc (ctx, list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700227 list->head = NULL;
228 list->tail = NULL;
229
230 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700231}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700232
Carl Worth33cc4002010-05-12 12:17:10 -0700233void
Carl Worthfcbbb462010-05-13 09:36:23 -0700234_list_append_list (list_t *list, list_t *tail)
235{
236 if (list->head == NULL) {
237 list->head = tail->head;
238 } else {
239 list->tail->next = tail->head;
240 }
241
242 list->tail = tail->tail;
243}
244
245void
246_list_append_item (list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700247{
248 node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700249
Carl Worth5070a202010-05-12 12:45:33 -0700250 node = xtalloc (list, node_t);
251 node->str = xtalloc_strdup (node, str);
Carl Worth33cc4002010-05-12 12:17:10 -0700252
253 node->next = NULL;
254
255 if (list->head == NULL) {
256 list->head = node;
257 } else {
258 list->tail->next = node;
259 }
260
261 list->tail = node;
262}
263
Carl Worth3a37b872010-05-10 11:44:09 -0700264void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700265yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700266{
267 fprintf (stderr, "Parse error: %s\n", error);
268}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700269
Carl Worth33cc4002010-05-12 12:17:10 -0700270glcpp_parser_t *
271glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700272{
Carl Worth33cc4002010-05-12 12:17:10 -0700273 glcpp_parser_t *parser;
274
Carl Worth5070a202010-05-12 12:45:33 -0700275 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700276
Carl Worth5070a202010-05-12 12:45:33 -0700277 yylex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700278 parser->defines = hash_table_ctor (32, hash_table_string_hash,
279 hash_table_string_compare);
Carl Worth33cc4002010-05-12 12:17:10 -0700280
281 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700282}
283
284int
285glcpp_parser_parse (glcpp_parser_t *parser)
286{
287 return yyparse (parser);
288}
289
290void
Carl Worth33cc4002010-05-12 12:17:10 -0700291glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700292{
293 yylex_destroy (parser->scanner);
294 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700295 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700296}
Carl Worthc6d5af32010-05-11 12:30:09 -0700297
Carl Worthfcbbb462010-05-13 09:36:23 -0700298macro_type_t
299glcpp_parser_macro_type (glcpp_parser_t *parser, const char *identifier)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700300{
Carl Worthfcbbb462010-05-13 09:36:23 -0700301 macro_t *macro;
302
303 macro = hash_table_find (parser->defines, identifier);
304
305 if (macro == NULL)
306 return MACRO_TYPE_UNDEFINED;
307
308 if (macro->is_function)
309 return MACRO_TYPE_FUNCTION;
310 else
311 return MACRO_TYPE_OBJECT;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700312}
313
Carl Worth33cc4002010-05-12 12:17:10 -0700314static void
Carl Worth9f62a7e2010-05-13 07:38:29 -0700315_print_expanded_macro_recursive (glcpp_parser_t *parser,
316 const char *token,
317 const char *orig,
318 int *first)
Carl Worthc6d5af32010-05-11 12:30:09 -0700319{
Carl Worthfcbbb462010-05-13 09:36:23 -0700320 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700321 node_t *node;
Carl Worthc6d5af32010-05-11 12:30:09 -0700322
Carl Worthfcbbb462010-05-13 09:36:23 -0700323 macro = hash_table_find (parser->defines, token);
324 if (macro == NULL) {
Carl Worth33cc4002010-05-12 12:17:10 -0700325 printf ("%s%s", *first ? "" : " ", token);
326 *first = 0;
327 } else {
Carl Worthfcbbb462010-05-13 09:36:23 -0700328 list_t *replacement_list = macro->replacement_list;
329
330 for (node = replacement_list->head ; node ; node = node->next) {
Carl Worth33cc4002010-05-12 12:17:10 -0700331 token = node->str;
332 if (strcmp (token, orig) == 0) {
333 printf ("%s%s", *first ? "" : " ", token);
334 *first = 0;
335 } else {
Carl Worth9f62a7e2010-05-13 07:38:29 -0700336 _print_expanded_macro_recursive (parser,
337 token, orig,
338 first);
Carl Worth33cc4002010-05-12 12:17:10 -0700339 }
340 }
Carl Worthc6d5af32010-05-11 12:30:09 -0700341 }
Carl Worthc6d5af32010-05-11 12:30:09 -0700342}
343
Carl Worth33cc4002010-05-12 12:17:10 -0700344void
Carl Worthfcbbb462010-05-13 09:36:23 -0700345_define_object_macro (glcpp_parser_t *parser,
346 const char *identifier,
347 list_t *replacement_list)
348{
349 macro_t *macro;
350
351 macro = xtalloc (parser, macro_t);
352
353 macro->is_function = 0;
354 macro->parameter_list = NULL;
355 macro->replacement_list = talloc_steal (macro, replacement_list);
356
357 hash_table_insert (parser->defines, macro, identifier);
358}
359
360void
361_define_function_macro (glcpp_parser_t *parser,
362 const char *identifier,
363 list_t *parameter_list,
364 list_t *replacement_list)
365{
366 macro_t *macro;
367
368 macro = xtalloc (parser, macro_t);
369
370 macro->is_function = 1;
371 macro->parameter_list = talloc_steal (macro, parameter_list);
372 macro->replacement_list = talloc_steal (macro, replacement_list);
373
374 hash_table_insert (parser->defines, macro, identifier);
375}
376
377void
378_print_expanded_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700379{
380 int first = 1;
Carl Worthfcbbb462010-05-13 09:36:23 -0700381 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700382
Carl Worthfcbbb462010-05-13 09:36:23 -0700383 macro = hash_table_find (parser->defines, identifier);
384 assert (! macro->is_function);
385
386 _print_expanded_macro_recursive (parser, identifier, identifier, &first);
387}
388
389void
390_print_expanded_function_macro (glcpp_parser_t *parser,
391 const char *identifier,
392 list_t *arguments)
393{
394 int first = 1;
395 macro_t *macro;
396
397 macro = hash_table_find (parser->defines, identifier);
398 assert (macro->is_function);
399
400 /* XXX: Need to use argument list here in the expansion. */
401
402 _print_expanded_macro_recursive (parser, identifier, identifier, &first);
Carl Worth33cc4002010-05-12 12:17:10 -0700403}