blob: 4b4a754f82b599078f607b9d4156815c3040896d [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 Worthdcc2ecd2010-05-13 12:56:42 -070076int
77_list_contains (list_t *list, const char *member, int *index);
78
79const char *
80_list_member_at (list_t *list, int index);
81
82int
83_list_length (list_t *list);
84
Carl Worth3a37b872010-05-10 11:44:09 -070085%}
86
Carl Worth33cc4002010-05-12 12:17:10 -070087%union {
88 char *str;
89 list_t *list;
90}
91
Carl Worth0b27b5f2010-05-10 16:16:06 -070092%parse-param {glcpp_parser_t *parser}
Carl Worth38aa8352010-05-10 11:52:29 -070093%lex-param {void *scanner}
94
Carl Worth0a93cbb2010-05-13 10:29:07 -070095%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO SPACE TOKEN UNDEF
96%type <str> FUNC_MACRO IDENTIFIER OBJ_MACRO TOKEN word word_or_symbol
Carl Worthfcbbb462010-05-13 09:36:23 -070097%type <list> argument argument_list parameter_list replacement_list
Carl Worth3a37b872010-05-10 11:44:09 -070098
99%%
100
Carl Worth33cc4002010-05-12 12:17:10 -0700101input:
102 /* empty */
Carl Worth8bcb6f12010-05-12 13:21:20 -0700103| input content
Carl Worth3a37b872010-05-10 11:44:09 -0700104;
105
Carl Worth33cc4002010-05-12 12:17:10 -0700106content:
Carl Worth9f62a7e2010-05-13 07:38:29 -0700107 IDENTIFIER {
108 printf ("%s", $1);
109 talloc_free ($1);
110 }
111| TOKEN {
112 printf ("%s", $1);
113 talloc_free ($1);
114 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700115| macro
Carl Worthcd27e642010-05-12 13:11:50 -0700116| directive_with_newline
Carl Worth0a93cbb2010-05-13 10:29:07 -0700117| NEWLINE { printf ("\n"); }
118| '(' { printf ("("); }
119| ')' { printf (")"); }
120| ',' { printf (","); }
Carl Worth48b94da2010-05-13 10:46:29 -0700121| SPACE { printf (" "); }
Carl Worthcd27e642010-05-12 13:11:50 -0700122;
123
Carl Worthfcbbb462010-05-13 09:36:23 -0700124macro:
125 FUNC_MACRO '(' argument_list ')' {
126 _print_expanded_function_macro (parser, $1, $3);
127 }
128| OBJ_MACRO {
129 _print_expanded_object_macro (parser, $1);
130 talloc_free ($1);
131 }
132;
133
134argument_list:
Carl Worthdb35d552010-05-14 08:47:32 -0700135 argument {
Carl Worthfcbbb462010-05-13 09:36:23 -0700136 $$ = _list_create (parser);
137 _list_append_list ($$, $1);
138 }
139| argument_list ',' argument {
140 _list_append_list ($1, $3);
141 $$ = $1;
142 }
143;
144
145argument:
146 /* empty */ {
147 $$ = _list_create (parser);
148 }
Carl Worth0a93cbb2010-05-13 10:29:07 -0700149| argument word {
Carl Worthfcbbb462010-05-13 09:36:23 -0700150 _list_append_item ($1, $2);
151 talloc_free ($2);
152 }
153| argument '(' argument ')'
154;
155
Carl Worthcd27e642010-05-12 13:11:50 -0700156directive_with_newline:
157 directive NEWLINE {
158 printf ("\n");
159 }
Carl Worth3a37b872010-05-10 11:44:09 -0700160;
161
Carl Worth33cc4002010-05-12 12:17:10 -0700162directive:
Carl Worth0a93cbb2010-05-13 10:29:07 -0700163 DEFINE IDENTIFIER {
164 list_t *list = _list_create (parser);
165 _define_object_macro (parser, $2, list);
166 }
167| DEFINE IDENTIFIER SPACE replacement_list {
168 _define_object_macro (parser, $2, $4);
Carl Worthcd27e642010-05-12 13:11:50 -0700169 }
Carl Worth48b94da2010-05-13 10:46:29 -0700170| DEFINE IDENTIFIER '(' parameter_list ')' {
171 list_t *list = _list_create (parser);
172 _define_function_macro (parser, $2, $4, list);
173 }
174| DEFINE IDENTIFIER '(' parameter_list ')' SPACE replacement_list {
175 _define_function_macro (parser, $2, $4, $7);
Carl Worthfcbbb462010-05-13 09:36:23 -0700176 }
177| UNDEF FUNC_MACRO {
178 list_t *replacement = hash_table_find (parser->defines, $2);
179 if (replacement) {
180 /* XXX: Need hash table to support a real way
181 * to remove an element rather than prefixing
182 * a new node with data of NULL like this. */
183 hash_table_insert (parser->defines, NULL, $2);
184 talloc_free (replacement);
185 }
186 talloc_free ($2);
187 }
188| UNDEF OBJ_MACRO {
Carl Worthcd27e642010-05-12 13:11:50 -0700189 list_t *replacement = hash_table_find (parser->defines, $2);
190 if (replacement) {
191 /* XXX: Need hash table to support a real way
192 * to remove an element rather than prefixing
193 * a new node with data of NULL like this. */
194 hash_table_insert (parser->defines, NULL, $2);
195 talloc_free (replacement);
196 }
197 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700198 }
199;
200
201replacement_list:
Carl Worth48b94da2010-05-13 10:46:29 -0700202 word_or_symbol {
Carl Worth33cc4002010-05-12 12:17:10 -0700203 $$ = _list_create (parser);
Carl Worth48b94da2010-05-13 10:46:29 -0700204 _list_append_item ($$, $1);
205 talloc_free ($1);
Carl Worth33cc4002010-05-12 12:17:10 -0700206 }
Carl Worth0a93cbb2010-05-13 10:29:07 -0700207| replacement_list word_or_symbol {
Carl Worthfcbbb462010-05-13 09:36:23 -0700208 _list_append_item ($1, $2);
Carl Worth5070a202010-05-12 12:45:33 -0700209 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700210 $$ = $1;
211 }
212;
213
Carl Worthfcbbb462010-05-13 09:36:23 -0700214parameter_list:
215 /* empty */ {
216 $$ = _list_create (parser);
217 }
218| IDENTIFIER {
219 $$ = _list_create (parser);
220 _list_append_item ($$, $1);
221 talloc_free ($1);
222 }
223| parameter_list ',' IDENTIFIER {
224 _list_append_item ($1, $3);
225 talloc_free ($3);
226 $$ = $1;
227 }
228;
229
Carl Worth0a93cbb2010-05-13 10:29:07 -0700230word_or_symbol:
231 word { $$ = $1; }
232| '(' { $$ = xtalloc_strdup (parser, "("); }
233| ')' { $$ = xtalloc_strdup (parser, ")"); }
234| ',' { $$ = xtalloc_strdup (parser, ","); }
Carl Worth48b94da2010-05-13 10:46:29 -0700235| SPACE { $$ = xtalloc_strdup (parser, " "); }
Carl Worth0a93cbb2010-05-13 10:29:07 -0700236;
237
238word:
Carl Worth9f62a7e2010-05-13 07:38:29 -0700239 IDENTIFIER { $$ = $1; }
Carl Worthfcbbb462010-05-13 09:36:23 -0700240| FUNC_MACRO { $$ = $1; }
241| OBJ_MACRO { $$ = $1; }
Carl Worth9f62a7e2010-05-13 07:38:29 -0700242| TOKEN { $$ = $1; }
Carl Worth33cc4002010-05-12 12:17:10 -0700243;
244
245%%
246
247list_t *
248_list_create (void *ctx)
249{
250 list_t *list;
251
Carl Worth5070a202010-05-12 12:45:33 -0700252 list = xtalloc (ctx, list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700253 list->head = NULL;
254 list->tail = NULL;
255
256 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700257}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700258
Carl Worth33cc4002010-05-12 12:17:10 -0700259void
Carl Worthfcbbb462010-05-13 09:36:23 -0700260_list_append_list (list_t *list, list_t *tail)
261{
262 if (list->head == NULL) {
263 list->head = tail->head;
264 } else {
265 list->tail->next = tail->head;
266 }
267
268 list->tail = tail->tail;
269}
270
271void
272_list_append_item (list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700273{
274 node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700275
Carl Worth5070a202010-05-12 12:45:33 -0700276 node = xtalloc (list, node_t);
277 node->str = xtalloc_strdup (node, str);
Carl Worth33cc4002010-05-12 12:17:10 -0700278
279 node->next = NULL;
280
281 if (list->head == NULL) {
282 list->head = node;
283 } else {
284 list->tail->next = node;
285 }
286
287 list->tail = node;
288}
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700289
290int
291_list_contains (list_t *list, const char *member, int *index)
292{
293 node_t *node;
294 int i;
295
296 if (list == NULL)
297 return 0;
298
299 for (i = 0, node = list->head; node; i++, node = node->next) {
300 if (strcmp (node->str, member) == 0) {
301 *index = i;
302 return 1;
303 }
304 }
305
306 return 0;
307}
308
309int
310_list_length (list_t *list)
311{
312 int length = 0;
313 node_t *node;
314
315 if (list == NULL)
316 return 0;
317
318 for (node = list->head; node; node = node->next)
319 length++;
320
321 return length;
322}
323
324const char *
325_list_member_at (list_t *list, int index)
326{
327 node_t *node;
328 int i;
329
330 if (list == NULL)
331 return NULL;
332
333 node = list->head;
334 for (i = 0; i < index; i++) {
335 node = node->next;
336 if (node == NULL)
337 break;
338 }
339
340 if (node)
341 return node->str;
342
343 return NULL;
344}
Carl Worth33cc4002010-05-12 12:17:10 -0700345
Carl Worth3a37b872010-05-10 11:44:09 -0700346void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700347yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700348{
349 fprintf (stderr, "Parse error: %s\n", error);
350}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700351
Carl Worth33cc4002010-05-12 12:17:10 -0700352glcpp_parser_t *
353glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700354{
Carl Worth33cc4002010-05-12 12:17:10 -0700355 glcpp_parser_t *parser;
356
Carl Worth5070a202010-05-12 12:45:33 -0700357 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700358
Carl Worth5070a202010-05-12 12:45:33 -0700359 yylex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700360 parser->defines = hash_table_ctor (32, hash_table_string_hash,
361 hash_table_string_compare);
Carl Worth33cc4002010-05-12 12:17:10 -0700362
363 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700364}
365
366int
367glcpp_parser_parse (glcpp_parser_t *parser)
368{
369 return yyparse (parser);
370}
371
372void
Carl Worth33cc4002010-05-12 12:17:10 -0700373glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700374{
375 yylex_destroy (parser->scanner);
376 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700377 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700378}
Carl Worthc6d5af32010-05-11 12:30:09 -0700379
Carl Worthfcbbb462010-05-13 09:36:23 -0700380macro_type_t
381glcpp_parser_macro_type (glcpp_parser_t *parser, const char *identifier)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700382{
Carl Worthfcbbb462010-05-13 09:36:23 -0700383 macro_t *macro;
384
385 macro = hash_table_find (parser->defines, identifier);
386
387 if (macro == NULL)
388 return MACRO_TYPE_UNDEFINED;
389
390 if (macro->is_function)
391 return MACRO_TYPE_FUNCTION;
392 else
393 return MACRO_TYPE_OBJECT;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700394}
395
Carl Worth33cc4002010-05-12 12:17:10 -0700396void
Carl Worthfcbbb462010-05-13 09:36:23 -0700397_define_object_macro (glcpp_parser_t *parser,
398 const char *identifier,
399 list_t *replacement_list)
400{
401 macro_t *macro;
402
403 macro = xtalloc (parser, macro_t);
404
405 macro->is_function = 0;
406 macro->parameter_list = NULL;
407 macro->replacement_list = talloc_steal (macro, replacement_list);
408
409 hash_table_insert (parser->defines, macro, identifier);
410}
411
412void
413_define_function_macro (glcpp_parser_t *parser,
414 const char *identifier,
415 list_t *parameter_list,
416 list_t *replacement_list)
417{
418 macro_t *macro;
419
420 macro = xtalloc (parser, macro_t);
421
422 macro->is_function = 1;
423 macro->parameter_list = talloc_steal (macro, parameter_list);
424 macro->replacement_list = talloc_steal (macro, replacement_list);
425
426 hash_table_insert (parser->defines, macro, identifier);
427}
428
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700429static void
430_print_expanded_macro_recursive (glcpp_parser_t *parser,
431 const char *token,
432 const char *orig,
433 list_t *parameters,
434 list_t *arguments);
435
436static void
437_print_expanded_list_recursive (glcpp_parser_t *parser,
438 list_t *list,
439 const char *orig,
440 list_t *parameters,
441 list_t *arguments)
442{
443 const char *token;
444 node_t *node;
445 int index;
446
447 for (node = list->head ; node ; node = node->next) {
448 token = node->str;
449
450 if (strcmp (token, orig) == 0) {
451 printf ("%s", token);
452 continue;
453 }
454
455 if (_list_contains (parameters, token, &index)) {
456 const char *argument;
457
458 argument = _list_member_at (arguments, index);
459 _print_expanded_macro_recursive (parser, argument,
460 orig, parameters,
461 arguments);
462 } else {
463 _print_expanded_macro_recursive (parser, token,
464 orig, parameters,
465 arguments);
466 }
467 }
468}
469
470
471static void
472_print_expanded_macro_recursive (glcpp_parser_t *parser,
473 const char *token,
474 const char *orig,
475 list_t *parameters,
476 list_t *arguments)
477{
478 macro_t *macro;
479 list_t *replacement_list;
480
481 macro = hash_table_find (parser->defines, token);
482 if (macro == NULL) {
483 printf ("%s", token);
484 return;
485 }
486
487 replacement_list = macro->replacement_list;
488
489 _print_expanded_list_recursive (parser, replacement_list,
490 orig, parameters, arguments);
491}
492
Carl Worthfcbbb462010-05-13 09:36:23 -0700493void
494_print_expanded_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700495{
Carl Worthfcbbb462010-05-13 09:36:23 -0700496 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700497
Carl Worthfcbbb462010-05-13 09:36:23 -0700498 macro = hash_table_find (parser->defines, identifier);
499 assert (! macro->is_function);
500
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700501 _print_expanded_macro_recursive (parser, identifier, identifier,
502 NULL, NULL);
Carl Worthfcbbb462010-05-13 09:36:23 -0700503}
504
505void
506_print_expanded_function_macro (glcpp_parser_t *parser,
507 const char *identifier,
508 list_t *arguments)
509{
Carl Worthfcbbb462010-05-13 09:36:23 -0700510 macro_t *macro;
511
512 macro = hash_table_find (parser->defines, identifier);
513 assert (macro->is_function);
514
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700515 if (_list_length (arguments) != _list_length (macro->parameter_list)) {
516 fprintf (stderr,
517 "Error: macro %s invoked with %d arguments (expected %d)\n",
518 identifier,
519 _list_length (arguments),
520 _list_length (macro->parameter_list));
521 return;
522 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700523
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700524 _print_expanded_macro_recursive (parser, identifier, identifier,
525 macro->parameter_list, arguments);
Carl Worth33cc4002010-05-12 12:17:10 -0700526}