blob: 647532f209dc8eecd099072a02520ff36a055bbe [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 Worth3a37b872010-05-10 11:44:09 -070028
Carl Wortha1e32bc2010-05-10 13:17:25 -070029#include "glcpp.h"
30
Carl Worth0b27b5f2010-05-10 16:16:06 -070031#define YYLEX_PARAM parser->scanner
Carl Worth3a37b872010-05-10 11:44:09 -070032
33void
Carl Wortha1e32bc2010-05-10 13:17:25 -070034yyerror (void *scanner, const char *error);
Carl Worth3a37b872010-05-10 11:44:09 -070035
Carl Worth33cc4002010-05-12 12:17:10 -070036void
Carl Worthfcbbb462010-05-13 09:36:23 -070037_define_object_macro (glcpp_parser_t *parser,
38 const char *macro,
Carl Wortha807fb72010-05-18 22:10:04 -070039 const char *replacement);
Carl Worthfcbbb462010-05-13 09:36:23 -070040
41void
42_define_function_macro (glcpp_parser_t *parser,
43 const char *macro,
Carl Worthc5e98552010-05-14 10:12:21 -070044 string_list_t *parameters,
Carl Wortha807fb72010-05-18 22:10:04 -070045 const char *replacement);
Carl Worthfcbbb462010-05-13 09:36:23 -070046
Carl Wortha807fb72010-05-18 22:10:04 -070047void
Carl Worth2be8be02010-05-14 10:31:43 -070048_expand_object_macro (glcpp_parser_t *parser, const char *identifier);
49
Carl Wortha807fb72010-05-18 22:10:04 -070050void
Carl Worth2be8be02010-05-14 10:31:43 -070051_expand_function_macro (glcpp_parser_t *parser,
52 const char *identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -070053 argument_list_t *arguments);
Carl Worthfcbbb462010-05-13 09:36:23 -070054
55void
Carl Worth2be8be02010-05-14 10:31:43 -070056_print_string_list (string_list_t *list);
Carl Worth33cc4002010-05-12 12:17:10 -070057
Carl Worth610053b2010-05-14 10:05:11 -070058string_list_t *
59_string_list_create (void *ctx);
Carl Worth33cc4002010-05-12 12:17:10 -070060
61void
Carl Worth610053b2010-05-14 10:05:11 -070062_string_list_append_item (string_list_t *list, const char *str);
Carl Worthfcbbb462010-05-13 09:36:23 -070063
64void
Carl Worth610053b2010-05-14 10:05:11 -070065_string_list_append_list (string_list_t *list, string_list_t *tail);
Carl Worthc6d5af32010-05-11 12:30:09 -070066
Carl Worthdcc2ecd2010-05-13 12:56:42 -070067int
Carl Worth610053b2010-05-14 10:05:11 -070068_string_list_contains (string_list_t *list, const char *member, int *index);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070069
Carl Worthdcc2ecd2010-05-13 12:56:42 -070070int
Carl Worth610053b2010-05-14 10:05:11 -070071_string_list_length (string_list_t *list);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070072
Carl Worth8f6a8282010-05-14 10:44:19 -070073argument_list_t *
74_argument_list_create (void *ctx);
75
76void
77_argument_list_append (argument_list_t *list, string_list_t *argument);
78
79int
80_argument_list_length (argument_list_t *list);
81
82string_list_t *
83_argument_list_member_at (argument_list_t *list, int index);
84
Carl Worth3a37b872010-05-10 11:44:09 -070085%}
86
Carl Worth33cc4002010-05-12 12:17:10 -070087%union {
88 char *str;
Carl Worth8f6a8282010-05-14 10:44:19 -070089 string_list_t *string_list;
90 argument_list_t *argument_list;
Carl Worth33cc4002010-05-12 12:17:10 -070091}
92
Carl Worth0b27b5f2010-05-10 16:16:06 -070093%parse-param {glcpp_parser_t *parser}
Carl Worth38aa8352010-05-10 11:52:29 -070094%lex-param {void *scanner}
95
Carl Wortha807fb72010-05-18 22:10:04 -070096%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO REPLACEMENT TOKEN UNDEF
Carl Worth59ca9892010-05-19 07:49:47 -070097%type <str> argument_word FUNC_MACRO IDENTIFIER OBJ_MACRO REPLACEMENT TOKEN
Carl Wortha807fb72010-05-18 22:10:04 -070098%type <string_list> argument macro parameter_list
Carl Worth8f6a8282010-05-14 10:44:19 -070099%type <argument_list> argument_list
Carl Worth3a37b872010-05-10 11:44:09 -0700100
Carl Worth796e1f02010-05-17 12:45:16 -0700101/* Hard to remove shift/reduce conflicts documented as follows:
102 *
103 * 1. '(' after FUNC_MACRO name which is correctly resolved to shift
104 * to form macro invocation rather than reducing directly to
105 * content.
Carl Worth69f390d2010-05-19 07:42:42 -0700106 *
107 * 2. Similarly, '(' after FUNC_MACRO which is correctly resolved to
108 * shift to form macro invocation rather than reducing directly to
109 * argument.
Carl Worth796e1f02010-05-17 12:45:16 -0700110 */
Carl Worth69f390d2010-05-19 07:42:42 -0700111%expect 2
Carl Worth796e1f02010-05-17 12:45:16 -0700112
Carl Worth3a37b872010-05-10 11:44:09 -0700113%%
114
Carl Worth33cc4002010-05-12 12:17:10 -0700115input:
116 /* empty */
Carl Worth8bcb6f12010-05-12 13:21:20 -0700117| input content
Carl Worth3a37b872010-05-10 11:44:09 -0700118;
119
Carl Worth04af1352010-05-14 10:17:38 -0700120 /* We do all printing at the content level */
Carl Worth33cc4002010-05-12 12:17:10 -0700121content:
Carl Worth9f62a7e2010-05-13 07:38:29 -0700122 IDENTIFIER {
123 printf ("%s", $1);
124 talloc_free ($1);
125 }
126| TOKEN {
127 printf ("%s", $1);
128 talloc_free ($1);
129 }
Carl Worthacf87bc2010-05-17 10:34:29 -0700130| FUNC_MACRO {
131 printf ("%s", $1);
132 talloc_free ($1);
133 }
Carl Wortha807fb72010-05-18 22:10:04 -0700134| directive {
135 printf ("\n");
Carl Worth2be8be02010-05-14 10:31:43 -0700136 }
Carl Worth0a93cbb2010-05-13 10:29:07 -0700137| '(' { printf ("("); }
138| ')' { printf (")"); }
139| ',' { printf (","); }
Carl Wortha807fb72010-05-18 22:10:04 -0700140| macro
Carl Worthcd27e642010-05-12 13:11:50 -0700141;
142
Carl Worthfcbbb462010-05-13 09:36:23 -0700143macro:
144 FUNC_MACRO '(' argument_list ')' {
Carl Wortha807fb72010-05-18 22:10:04 -0700145 _expand_function_macro (parser, $1, $3);
Carl Worthfcbbb462010-05-13 09:36:23 -0700146 }
147| OBJ_MACRO {
Carl Wortha807fb72010-05-18 22:10:04 -0700148 _expand_object_macro (parser, $1);
Carl Worthfcbbb462010-05-13 09:36:23 -0700149 talloc_free ($1);
150 }
151;
152
153argument_list:
Carl Worthac070e82010-05-14 11:33:00 -0700154 /* empty */ {
155 $$ = _argument_list_create (parser);
156 }
157| argument {
Carl Worth8f6a8282010-05-14 10:44:19 -0700158 $$ = _argument_list_create (parser);
159 _argument_list_append ($$, $1);
160 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700161| argument_list ',' argument {
Carl Worth8f6a8282010-05-14 10:44:19 -0700162 _argument_list_append ($1, $3);
Carl Worthfcbbb462010-05-13 09:36:23 -0700163 $$ = $1;
164 }
165;
166
167argument:
Carl Worth59ca9892010-05-19 07:49:47 -0700168 argument_word {
Carl Worth610053b2010-05-14 10:05:11 -0700169 $$ = _string_list_create (parser);
Carl Worthac070e82010-05-14 11:33:00 -0700170 _string_list_append_item ($$, $1);
Carl Worthfcbbb462010-05-13 09:36:23 -0700171 }
Carl Worth59ca9892010-05-19 07:49:47 -0700172| argument argument_word {
Carl Worth610053b2010-05-14 10:05:11 -0700173 _string_list_append_item ($1, $2);
Carl Worthfcbbb462010-05-13 09:36:23 -0700174 talloc_free ($2);
Carl Worth3596bb12010-05-14 16:53:52 -0700175 $$ = $1;
Carl Worthfcbbb462010-05-13 09:36:23 -0700176 }
Carl Worth3596bb12010-05-14 16:53:52 -0700177| argument '(' argument ')' {
178 _string_list_append_item ($1, "(");
179 _string_list_append_list ($1, $3);
180 _string_list_append_item ($1, ")");
181 $$ = $1;
182 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700183;
184
Carl Worth59ca9892010-05-19 07:49:47 -0700185argument_word:
186 IDENTIFIER { $$ = $1; }
187| TOKEN { $$ = $1; }
188| FUNC_MACRO { $$ = $1; }
Carl Worth5d211422010-05-19 07:57:03 -0700189| macro { $$ = xtalloc_strdup (parser, ""); }
Carl Worth59ca9892010-05-19 07:49:47 -0700190;
191
192
Carl Worth33cc4002010-05-12 12:17:10 -0700193directive:
Carl Wortha807fb72010-05-18 22:10:04 -0700194 DEFINE IDENTIFIER REPLACEMENT {
195 _define_object_macro (parser, $2, $3);
Carl Worth0a93cbb2010-05-13 10:29:07 -0700196 }
Carl Wortha807fb72010-05-18 22:10:04 -0700197| DEFINE IDENTIFIER '(' parameter_list ')' REPLACEMENT {
Carl Worth81f01432010-05-14 17:08:45 -0700198 _define_function_macro (parser, $2, $4, $6);
Carl Worthfcbbb462010-05-13 09:36:23 -0700199 }
Carl Wortha807fb72010-05-18 22:10:04 -0700200| UNDEF IDENTIFIER {
201 string_list_t *macro = hash_table_find (parser->defines, $2);
202 if (macro) {
Carl Worthfcbbb462010-05-13 09:36:23 -0700203 /* XXX: Need hash table to support a real way
204 * to remove an element rather than prefixing
205 * a new node with data of NULL like this. */
206 hash_table_insert (parser->defines, NULL, $2);
Carl Wortha807fb72010-05-18 22:10:04 -0700207 talloc_free (macro);
Carl Worthfcbbb462010-05-13 09:36:23 -0700208 }
209 talloc_free ($2);
210 }
Carl Worth38bd27b2010-05-14 12:05:37 -0700211;
212
Carl Worthfcbbb462010-05-13 09:36:23 -0700213parameter_list:
214 /* empty */ {
Carl Worth610053b2010-05-14 10:05:11 -0700215 $$ = _string_list_create (parser);
Carl Worthfcbbb462010-05-13 09:36:23 -0700216 }
Carl Wortha807fb72010-05-18 22:10:04 -0700217| IDENTIFIER {
Carl Worth610053b2010-05-14 10:05:11 -0700218 $$ = _string_list_create (parser);
219 _string_list_append_item ($$, $1);
Carl Worthfcbbb462010-05-13 09:36:23 -0700220 talloc_free ($1);
221 }
Carl Wortha807fb72010-05-18 22:10:04 -0700222| parameter_list ',' IDENTIFIER {
Carl Worth610053b2010-05-14 10:05:11 -0700223 _string_list_append_item ($1, $3);
Carl Worthfcbbb462010-05-13 09:36:23 -0700224 talloc_free ($3);
225 $$ = $1;
226 }
227;
228
Carl Worth33cc4002010-05-12 12:17:10 -0700229%%
230
Carl Worth610053b2010-05-14 10:05:11 -0700231string_list_t *
232_string_list_create (void *ctx)
Carl Worth33cc4002010-05-12 12:17:10 -0700233{
Carl Worth610053b2010-05-14 10:05:11 -0700234 string_list_t *list;
Carl Worth33cc4002010-05-12 12:17:10 -0700235
Carl Worth610053b2010-05-14 10:05:11 -0700236 list = xtalloc (ctx, string_list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700237 list->head = NULL;
238 list->tail = NULL;
239
240 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700241}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700242
Carl Worth33cc4002010-05-12 12:17:10 -0700243void
Carl Worth610053b2010-05-14 10:05:11 -0700244_string_list_append_list (string_list_t *list, string_list_t *tail)
Carl Worthfcbbb462010-05-13 09:36:23 -0700245{
246 if (list->head == NULL) {
247 list->head = tail->head;
248 } else {
249 list->tail->next = tail->head;
250 }
251
252 list->tail = tail->tail;
253}
254
255void
Carl Worth610053b2010-05-14 10:05:11 -0700256_string_list_append_item (string_list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700257{
Carl Worth610053b2010-05-14 10:05:11 -0700258 string_node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700259
Carl Worth610053b2010-05-14 10:05:11 -0700260 node = xtalloc (list, string_node_t);
Carl Worth5070a202010-05-12 12:45:33 -0700261 node->str = xtalloc_strdup (node, str);
Carl Worth33cc4002010-05-12 12:17:10 -0700262
263 node->next = NULL;
264
265 if (list->head == NULL) {
266 list->head = node;
267 } else {
268 list->tail->next = node;
269 }
270
271 list->tail = node;
272}
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700273
274int
Carl Worth610053b2010-05-14 10:05:11 -0700275_string_list_contains (string_list_t *list, const char *member, int *index)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700276{
Carl Worth610053b2010-05-14 10:05:11 -0700277 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700278 int i;
279
280 if (list == NULL)
281 return 0;
282
283 for (i = 0, node = list->head; node; i++, node = node->next) {
284 if (strcmp (node->str, member) == 0) {
Carl Worth420d05a2010-05-17 10:15:23 -0700285 if (index)
286 *index = i;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700287 return 1;
288 }
289 }
290
291 return 0;
292}
293
294int
Carl Worth610053b2010-05-14 10:05:11 -0700295_string_list_length (string_list_t *list)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700296{
297 int length = 0;
Carl Worth610053b2010-05-14 10:05:11 -0700298 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700299
300 if (list == NULL)
301 return 0;
302
303 for (node = list->head; node; node = node->next)
304 length++;
305
306 return length;
307}
308
Carl Worth2be8be02010-05-14 10:31:43 -0700309void
310_print_string_list (string_list_t *list)
311{
312 string_node_t *node;
313
314 if (list == NULL)
315 return;
316
Carl Worth81f01432010-05-14 17:08:45 -0700317 for (node = list->head; node; node = node->next) {
Carl Worth2be8be02010-05-14 10:31:43 -0700318 printf ("%s", node->str);
Carl Worth81f01432010-05-14 17:08:45 -0700319 if (node->next)
320 printf (" ");
321 }
Carl Worth2be8be02010-05-14 10:31:43 -0700322}
323
Carl Worth8f6a8282010-05-14 10:44:19 -0700324argument_list_t *
325_argument_list_create (void *ctx)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700326{
Carl Worth8f6a8282010-05-14 10:44:19 -0700327 argument_list_t *list;
328
329 list = xtalloc (ctx, argument_list_t);
330 list->head = NULL;
331 list->tail = NULL;
332
333 return list;
334}
335
336void
337_argument_list_append (argument_list_t *list, string_list_t *argument)
338{
339 argument_node_t *node;
340
341 if (argument == NULL || argument->head == NULL)
342 return;
343
344 node = xtalloc (list, argument_node_t);
345 node->argument = argument;
346
347 node->next = NULL;
348
349 if (list->head == NULL) {
350 list->head = node;
351 } else {
352 list->tail->next = node;
353 }
354
355 list->tail = node;
356}
357
358int
359_argument_list_length (argument_list_t *list)
360{
361 int length = 0;
362 argument_node_t *node;
363
364 if (list == NULL)
365 return 0;
366
367 for (node = list->head; node; node = node->next)
368 length++;
369
370 return length;
371}
372
373string_list_t *
374_argument_list_member_at (argument_list_t *list, int index)
375{
376 argument_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700377 int i;
378
379 if (list == NULL)
380 return NULL;
381
382 node = list->head;
383 for (i = 0; i < index; i++) {
384 node = node->next;
385 if (node == NULL)
386 break;
387 }
388
389 if (node)
Carl Worth8f6a8282010-05-14 10:44:19 -0700390 return node->argument;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700391
392 return NULL;
393}
Carl Worth33cc4002010-05-12 12:17:10 -0700394
Carl Worth3a37b872010-05-10 11:44:09 -0700395void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700396yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700397{
398 fprintf (stderr, "Parse error: %s\n", error);
399}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700400
Carl Worth33cc4002010-05-12 12:17:10 -0700401glcpp_parser_t *
402glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700403{
Carl Worth33cc4002010-05-12 12:17:10 -0700404 glcpp_parser_t *parser;
405
Carl Worth5070a202010-05-12 12:45:33 -0700406 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700407
Carl Worth5070a202010-05-12 12:45:33 -0700408 yylex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700409 parser->defines = hash_table_ctor (32, hash_table_string_hash,
410 hash_table_string_compare);
Carl Wortha807fb72010-05-18 22:10:04 -0700411 parser->expansions = NULL;
412
413 parser->lex_stack = xtalloc (parser, glcpp_lex_stack_t);
414 parser->lex_stack->parser = parser;
415 parser->lex_stack->head = NULL;
Carl Worth33cc4002010-05-12 12:17:10 -0700416
417 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700418}
419
420int
421glcpp_parser_parse (glcpp_parser_t *parser)
422{
423 return yyparse (parser);
424}
425
426void
Carl Worth33cc4002010-05-12 12:17:10 -0700427glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700428{
429 yylex_destroy (parser->scanner);
430 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700431 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700432}
Carl Worthc6d5af32010-05-11 12:30:09 -0700433
Carl Worthbe0e2e92010-05-19 07:29:22 -0700434static int
435glcpp_parser_is_expanding (glcpp_parser_t *parser, const char *member)
436{
437 expansion_node_t *node;
438
439 for (node = parser->expansions; node; node = node->next) {
440 if (node->macro &&
441 strcmp (node->macro->identifier, member) == 0)
442 {
443 return 1;
444 }
445 }
446
447 return 0;
448}
449
Carl Wortha807fb72010-05-18 22:10:04 -0700450token_class_t
451glcpp_parser_classify_token (glcpp_parser_t *parser,
452 const char *identifier,
453 int *parameter_index)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700454{
Carl Worthfcbbb462010-05-13 09:36:23 -0700455 macro_t *macro;
456
Carl Wortha807fb72010-05-18 22:10:04 -0700457 /* First we check if we are currently expanding a
458 * function-like macro, and if so, whether the parameter list
459 * contains a parameter matching this token name. */
460 if (parser->expansions &&
461 parser->expansions->macro &&
462 parser->expansions->macro->parameters)
463 {
464 string_list_t *list;
465
466 list = parser->expansions->macro->parameters;
467
468 if (_string_list_contains (list, identifier, parameter_index))
469 return TOKEN_CLASS_ARGUMENT;
470 }
471
472 /* If not a function-like macro parameter, we next check if
473 * this token is a macro itself. */
474
Carl Worthfcbbb462010-05-13 09:36:23 -0700475 macro = hash_table_find (parser->defines, identifier);
476
477 if (macro == NULL)
Carl Wortha807fb72010-05-18 22:10:04 -0700478 return TOKEN_CLASS_IDENTIFIER;
Carl Worthfcbbb462010-05-13 09:36:23 -0700479
Carl Worthbe0e2e92010-05-19 07:29:22 -0700480 /* Don't consider this a macro if we are already actively
481 * expanding this macro. */
482 if (glcpp_parser_is_expanding (parser, identifier))
483 return TOKEN_CLASS_IDENTIFIER;
484
485 /* Definitely a macro. Just need to check if it's function-like. */
Carl Worthfcbbb462010-05-13 09:36:23 -0700486 if (macro->is_function)
Carl Wortha807fb72010-05-18 22:10:04 -0700487 return TOKEN_CLASS_FUNC_MACRO;
Carl Worthfcbbb462010-05-13 09:36:23 -0700488 else
Carl Wortha807fb72010-05-18 22:10:04 -0700489 return TOKEN_CLASS_OBJ_MACRO;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700490}
491
Carl Worth33cc4002010-05-12 12:17:10 -0700492void
Carl Worthfcbbb462010-05-13 09:36:23 -0700493_define_object_macro (glcpp_parser_t *parser,
494 const char *identifier,
Carl Wortha807fb72010-05-18 22:10:04 -0700495 const char *replacement)
Carl Worthfcbbb462010-05-13 09:36:23 -0700496{
497 macro_t *macro;
498
499 macro = xtalloc (parser, macro_t);
500
501 macro->is_function = 0;
Carl Worthc5e98552010-05-14 10:12:21 -0700502 macro->parameters = NULL;
Carl Wortha807fb72010-05-18 22:10:04 -0700503 macro->identifier = talloc_strdup (macro, identifier);
504 macro->replacement = talloc_steal (macro, replacement);
Carl Worthfcbbb462010-05-13 09:36:23 -0700505
506 hash_table_insert (parser->defines, macro, identifier);
507}
508
509void
510_define_function_macro (glcpp_parser_t *parser,
511 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -0700512 string_list_t *parameters,
Carl Wortha807fb72010-05-18 22:10:04 -0700513 const char *replacement)
Carl Worthfcbbb462010-05-13 09:36:23 -0700514{
515 macro_t *macro;
516
517 macro = xtalloc (parser, macro_t);
518
519 macro->is_function = 1;
Carl Worthc5e98552010-05-14 10:12:21 -0700520 macro->parameters = talloc_steal (macro, parameters);
Carl Wortha807fb72010-05-18 22:10:04 -0700521 macro->identifier = talloc_strdup (macro, identifier);
522 macro->replacement = talloc_steal (macro, replacement);
Carl Worthfcbbb462010-05-13 09:36:23 -0700523
524 hash_table_insert (parser->defines, macro, identifier);
525}
526
Carl Wortha807fb72010-05-18 22:10:04 -0700527static void
528_glcpp_parser_push_expansion_internal (glcpp_parser_t *parser,
529 macro_t *macro,
530 argument_list_t *arguments,
531 const char * replacement)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700532{
Carl Wortha807fb72010-05-18 22:10:04 -0700533 expansion_node_t *node;
534
535 node = xtalloc (parser, expansion_node_t);
536
537 node->macro = macro;
538 node->arguments = arguments;
539
540 node->next = parser->expansions;
541 parser->expansions = node;
542
543 glcpp_lex_stack_push (parser->lex_stack, replacement);
544}
545
546void
547glcpp_parser_push_expansion_macro (glcpp_parser_t *parser,
548 macro_t *macro,
549 argument_list_t *arguments)
550{
551 _glcpp_parser_push_expansion_internal (parser, macro, arguments,
552 macro->replacement);
553}
554
555void
556glcpp_parser_push_expansion_argument (glcpp_parser_t *parser,
557 int argument_index)
558{
559 argument_list_t *arguments;
560 string_list_t *argument;
Carl Worth610053b2010-05-14 10:05:11 -0700561 string_node_t *node;
Carl Wortha807fb72010-05-18 22:10:04 -0700562 char *argument_str, *s;
563 int length;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700564
Carl Wortha807fb72010-05-18 22:10:04 -0700565 arguments = parser->expansions->arguments;
Carl Worth2be8be02010-05-14 10:31:43 -0700566
Carl Wortha807fb72010-05-18 22:10:04 -0700567 argument = _argument_list_member_at (arguments, argument_index);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700568
Carl Wortha807fb72010-05-18 22:10:04 -0700569 length = 0;
570 for (node = argument->head; node; node = node->next)
571 length += strlen (node->str) + 1;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700572
Carl Wortha807fb72010-05-18 22:10:04 -0700573 argument_str = xtalloc_size (parser, length);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700574
Carl Wortha807fb72010-05-18 22:10:04 -0700575 *argument_str = '\0';
576 s = argument_str;
577 for (node = argument->head; node; node = node->next) {
578 strcpy (s, node->str);
579 s += strlen (node->str);
580 if (node->next) {
581 *s = ' ';
582 s++;
583 *s = '\0';
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700584 }
585 }
Carl Worth2be8be02010-05-14 10:31:43 -0700586
Carl Wortha807fb72010-05-18 22:10:04 -0700587 _glcpp_parser_push_expansion_internal (parser, NULL, NULL,
588 argument_str);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700589}
590
Carl Wortha807fb72010-05-18 22:10:04 -0700591/* The lexer calls this when it exhausts a string. */
592void
593glcpp_parser_pop_expansion (glcpp_parser_t *parser)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700594{
Carl Wortha807fb72010-05-18 22:10:04 -0700595 expansion_node_t *node;
Carl Worth420d05a2010-05-17 10:15:23 -0700596
Carl Wortha807fb72010-05-18 22:10:04 -0700597 node = parser->expansions;
Carl Worth420d05a2010-05-17 10:15:23 -0700598
Carl Wortha807fb72010-05-18 22:10:04 -0700599 if (node == NULL) {
600 fprintf (stderr, "Internal error: _expansion_list_pop called on an empty list.\n");
601 exit (1);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700602 }
603
Carl Wortha807fb72010-05-18 22:10:04 -0700604 parser->expansions = node->next;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700605
Carl Wortha807fb72010-05-18 22:10:04 -0700606 talloc_free (node);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700607}
608
Carl Wortha807fb72010-05-18 22:10:04 -0700609void
Carl Worth2be8be02010-05-14 10:31:43 -0700610_expand_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700611{
Carl Worthfcbbb462010-05-13 09:36:23 -0700612 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700613
Carl Worthfcbbb462010-05-13 09:36:23 -0700614 macro = hash_table_find (parser->defines, identifier);
615 assert (! macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700616 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700617
Carl Worthbe0e2e92010-05-19 07:29:22 -0700618 glcpp_parser_push_expansion_macro (parser, macro, NULL);
Carl Worthfcbbb462010-05-13 09:36:23 -0700619}
620
Carl Wortha807fb72010-05-18 22:10:04 -0700621void
Carl Worth2be8be02010-05-14 10:31:43 -0700622_expand_function_macro (glcpp_parser_t *parser,
623 const char *identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700624 argument_list_t *arguments)
Carl Worthfcbbb462010-05-13 09:36:23 -0700625{
Carl Worthfcbbb462010-05-13 09:36:23 -0700626 macro_t *macro;
627
628 macro = hash_table_find (parser->defines, identifier);
629 assert (macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700630 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700631
Carl Worth8f6a8282010-05-14 10:44:19 -0700632 if (_argument_list_length (arguments) !=
Carl Worth2be8be02010-05-14 10:31:43 -0700633 _string_list_length (macro->parameters))
634 {
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700635 fprintf (stderr,
636 "Error: macro %s invoked with %d arguments (expected %d)\n",
637 identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700638 _argument_list_length (arguments),
Carl Worthc5e98552010-05-14 10:12:21 -0700639 _string_list_length (macro->parameters));
Carl Wortha807fb72010-05-18 22:10:04 -0700640 return;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700641 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700642
Carl Worthbe0e2e92010-05-19 07:29:22 -0700643 glcpp_parser_push_expansion_macro (parser, macro, arguments);
Carl Worth33cc4002010-05-12 12:17:10 -0700644}