blob: 6f158d91398beb4200f45af962d0706ec5df0c2b [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;
Carl Worthc5e98552010-05-14 10:12:21 -070036 string_list_t *parameters;
37 string_list_t *replacements;
Carl Worthfcbbb462010-05-13 09:36:23 -070038} 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,
Carl Worthc5e98552010-05-14 10:12:21 -070051 string_list_t *replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -070052
53void
54_define_function_macro (glcpp_parser_t *parser,
55 const char *macro,
Carl Worthc5e98552010-05-14 10:12:21 -070056 string_list_t *parameters,
57 string_list_t *replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -070058
Carl Worth2be8be02010-05-14 10:31:43 -070059string_list_t *
60_expand_object_macro (glcpp_parser_t *parser, const char *identifier);
61
62string_list_t *
63_expand_function_macro (glcpp_parser_t *parser,
64 const char *identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -070065 argument_list_t *arguments);
Carl Worthfcbbb462010-05-13 09:36:23 -070066
67void
Carl Worth2be8be02010-05-14 10:31:43 -070068_print_string_list (string_list_t *list);
Carl Worth33cc4002010-05-12 12:17:10 -070069
Carl Worth610053b2010-05-14 10:05:11 -070070string_list_t *
71_string_list_create (void *ctx);
Carl Worth33cc4002010-05-12 12:17:10 -070072
73void
Carl Worth610053b2010-05-14 10:05:11 -070074_string_list_append_item (string_list_t *list, const char *str);
Carl Worthfcbbb462010-05-13 09:36:23 -070075
76void
Carl Worth610053b2010-05-14 10:05:11 -070077_string_list_append_list (string_list_t *list, string_list_t *tail);
Carl Worthc6d5af32010-05-11 12:30:09 -070078
Carl Worth420d05a2010-05-17 10:15:23 -070079void
80_string_list_push (string_list_t *list, const char *str);
81
82void
83_string_list_pop (string_list_t *list);
84
Carl Worthdcc2ecd2010-05-13 12:56:42 -070085int
Carl Worth610053b2010-05-14 10:05:11 -070086_string_list_contains (string_list_t *list, const char *member, int *index);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070087
Carl Worthdcc2ecd2010-05-13 12:56:42 -070088int
Carl Worth610053b2010-05-14 10:05:11 -070089_string_list_length (string_list_t *list);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070090
Carl Worth8f6a8282010-05-14 10:44:19 -070091argument_list_t *
92_argument_list_create (void *ctx);
93
94void
95_argument_list_append (argument_list_t *list, string_list_t *argument);
96
97int
98_argument_list_length (argument_list_t *list);
99
100string_list_t *
101_argument_list_member_at (argument_list_t *list, int index);
102
Carl Worth3a37b872010-05-10 11:44:09 -0700103%}
104
Carl Worth33cc4002010-05-12 12:17:10 -0700105%union {
106 char *str;
Carl Worth8f6a8282010-05-14 10:44:19 -0700107 string_list_t *string_list;
108 argument_list_t *argument_list;
Carl Worth33cc4002010-05-12 12:17:10 -0700109}
110
Carl Worth0b27b5f2010-05-10 16:16:06 -0700111%parse-param {glcpp_parser_t *parser}
Carl Worth38aa8352010-05-10 11:52:29 -0700112%lex-param {void *scanner}
113
Carl Worth0a93cbb2010-05-13 10:29:07 -0700114%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO SPACE TOKEN UNDEF
Carl Worth38bd27b2010-05-14 12:05:37 -0700115%type <str> FUNC_MACRO IDENTIFIER identifier_perhaps_macro OBJ_MACRO replacement_word TOKEN word
Carl Worth8f6a8282010-05-14 10:44:19 -0700116%type <string_list> argument macro parameter_list replacement_list
117%type <argument_list> argument_list
Carl Worth3a37b872010-05-10 11:44:09 -0700118
119%%
120
Carl Worth33cc4002010-05-12 12:17:10 -0700121input:
122 /* empty */
Carl Worth8bcb6f12010-05-12 13:21:20 -0700123| input content
Carl Worth3a37b872010-05-10 11:44:09 -0700124;
125
Carl Worth04af1352010-05-14 10:17:38 -0700126 /* We do all printing at the content level */
Carl Worth33cc4002010-05-12 12:17:10 -0700127content:
Carl Worth9f62a7e2010-05-13 07:38:29 -0700128 IDENTIFIER {
129 printf ("%s", $1);
130 talloc_free ($1);
131 }
132| TOKEN {
133 printf ("%s", $1);
134 talloc_free ($1);
135 }
Carl Worthacf87bc2010-05-17 10:34:29 -0700136| FUNC_MACRO {
137 printf ("%s", $1);
138 talloc_free ($1);
139 }
Carl Worth2be8be02010-05-14 10:31:43 -0700140| macro {
141 _print_string_list ($1);
142 }
Carl Worth04af1352010-05-14 10:17:38 -0700143| directive_with_newline { printf ("\n"); }
Carl Worth0a93cbb2010-05-13 10:29:07 -0700144| NEWLINE { printf ("\n"); }
145| '(' { printf ("("); }
146| ')' { printf (")"); }
147| ',' { printf (","); }
Carl Worthcd27e642010-05-12 13:11:50 -0700148;
149
Carl Worthfcbbb462010-05-13 09:36:23 -0700150macro:
151 FUNC_MACRO '(' argument_list ')' {
Carl Worth2be8be02010-05-14 10:31:43 -0700152 $$ = _expand_function_macro (parser, $1, $3);
Carl Worthfcbbb462010-05-13 09:36:23 -0700153 }
154| OBJ_MACRO {
Carl Worth2be8be02010-05-14 10:31:43 -0700155 $$ = _expand_object_macro (parser, $1);
Carl Worthfcbbb462010-05-13 09:36:23 -0700156 talloc_free ($1);
157 }
158;
159
160argument_list:
Carl Worthac070e82010-05-14 11:33:00 -0700161 /* empty */ {
162 $$ = _argument_list_create (parser);
163 }
164| argument {
Carl Worth8f6a8282010-05-14 10:44:19 -0700165 $$ = _argument_list_create (parser);
166 _argument_list_append ($$, $1);
167 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700168| argument_list ',' argument {
Carl Worth8f6a8282010-05-14 10:44:19 -0700169 _argument_list_append ($1, $3);
Carl Worthfcbbb462010-05-13 09:36:23 -0700170 $$ = $1;
171 }
172;
173
174argument:
Carl Worthac070e82010-05-14 11:33:00 -0700175 word {
Carl Worth610053b2010-05-14 10:05:11 -0700176 $$ = _string_list_create (parser);
Carl Worthac070e82010-05-14 11:33:00 -0700177 _string_list_append_item ($$, $1);
Carl Worthfcbbb462010-05-13 09:36:23 -0700178 }
Carl Worth38bd27b2010-05-14 12:05:37 -0700179| macro {
180 $$ = $1;
181 }
Carl Worth0a93cbb2010-05-13 10:29:07 -0700182| argument word {
Carl Worth610053b2010-05-14 10:05:11 -0700183 _string_list_append_item ($1, $2);
Carl Worthfcbbb462010-05-13 09:36:23 -0700184 talloc_free ($2);
Carl Worth3596bb12010-05-14 16:53:52 -0700185 $$ = $1;
Carl Worthfcbbb462010-05-13 09:36:23 -0700186 }
Carl Worth3596bb12010-05-14 16:53:52 -0700187| argument '(' argument ')' {
188 _string_list_append_item ($1, "(");
189 _string_list_append_list ($1, $3);
190 _string_list_append_item ($1, ")");
191 $$ = $1;
192 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700193;
194
Carl Worthcd27e642010-05-12 13:11:50 -0700195directive_with_newline:
Carl Worth04af1352010-05-14 10:17:38 -0700196 directive NEWLINE
Carl Worth3a37b872010-05-10 11:44:09 -0700197;
198
Carl Worth33cc4002010-05-12 12:17:10 -0700199directive:
Carl Worth0a93cbb2010-05-13 10:29:07 -0700200 DEFINE IDENTIFIER {
Carl Worth610053b2010-05-14 10:05:11 -0700201 string_list_t *list = _string_list_create (parser);
Carl Worth0a93cbb2010-05-13 10:29:07 -0700202 _define_object_macro (parser, $2, list);
203 }
204| DEFINE IDENTIFIER SPACE replacement_list {
205 _define_object_macro (parser, $2, $4);
Carl Worthcd27e642010-05-12 13:11:50 -0700206 }
Carl Worth48b94da2010-05-13 10:46:29 -0700207| DEFINE IDENTIFIER '(' parameter_list ')' {
Carl Worth610053b2010-05-14 10:05:11 -0700208 string_list_t *list = _string_list_create (parser);
Carl Worth48b94da2010-05-13 10:46:29 -0700209 _define_function_macro (parser, $2, $4, list);
210 }
Carl Worth81f01432010-05-14 17:08:45 -0700211| DEFINE IDENTIFIER '(' parameter_list ')' replacement_list {
212 _define_function_macro (parser, $2, $4, $6);
Carl Worthfcbbb462010-05-13 09:36:23 -0700213 }
214| UNDEF FUNC_MACRO {
Carl Worth610053b2010-05-14 10:05:11 -0700215 string_list_t *replacement = hash_table_find (parser->defines, $2);
Carl Worthfcbbb462010-05-13 09:36:23 -0700216 if (replacement) {
217 /* XXX: Need hash table to support a real way
218 * to remove an element rather than prefixing
219 * a new node with data of NULL like this. */
220 hash_table_insert (parser->defines, NULL, $2);
221 talloc_free (replacement);
222 }
223 talloc_free ($2);
224 }
225| UNDEF OBJ_MACRO {
Carl Worth610053b2010-05-14 10:05:11 -0700226 string_list_t *replacement = hash_table_find (parser->defines, $2);
Carl Worthcd27e642010-05-12 13:11:50 -0700227 if (replacement) {
228 /* XXX: Need hash table to support a real way
229 * to remove an element rather than prefixing
230 * a new node with data of NULL like this. */
231 hash_table_insert (parser->defines, NULL, $2);
232 talloc_free (replacement);
233 }
234 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700235 }
236;
237
238replacement_list:
Carl Worth38bd27b2010-05-14 12:05:37 -0700239 replacement_word {
Carl Worth610053b2010-05-14 10:05:11 -0700240 $$ = _string_list_create (parser);
241 _string_list_append_item ($$, $1);
Carl Worth48b94da2010-05-13 10:46:29 -0700242 talloc_free ($1);
Carl Worth33cc4002010-05-12 12:17:10 -0700243 }
Carl Worth38bd27b2010-05-14 12:05:37 -0700244| replacement_list replacement_word {
Carl Worth610053b2010-05-14 10:05:11 -0700245 _string_list_append_item ($1, $2);
Carl Worth5070a202010-05-12 12:45:33 -0700246 talloc_free ($2);
Carl Worth33cc4002010-05-12 12:17:10 -0700247 $$ = $1;
248 }
249;
250
Carl Worth38bd27b2010-05-14 12:05:37 -0700251replacement_word:
252 word { $$ = $1; }
253| FUNC_MACRO { $$ = $1; }
254| OBJ_MACRO { $$ = $1; }
255| '(' { $$ = xtalloc_strdup (parser, "("); }
256| ')' { $$ = xtalloc_strdup (parser, ")"); }
257| ',' { $$ = xtalloc_strdup (parser, ","); }
Carl Worth38bd27b2010-05-14 12:05:37 -0700258;
259
Carl Worthfcbbb462010-05-13 09:36:23 -0700260parameter_list:
261 /* empty */ {
Carl Worth610053b2010-05-14 10:05:11 -0700262 $$ = _string_list_create (parser);
Carl Worthfcbbb462010-05-13 09:36:23 -0700263 }
Carl Worth7f9aa362010-05-13 12:58:49 -0700264| identifier_perhaps_macro {
Carl Worth610053b2010-05-14 10:05:11 -0700265 $$ = _string_list_create (parser);
266 _string_list_append_item ($$, $1);
Carl Worthfcbbb462010-05-13 09:36:23 -0700267 talloc_free ($1);
268 }
Carl Worth7f9aa362010-05-13 12:58:49 -0700269| parameter_list ',' identifier_perhaps_macro {
Carl Worth610053b2010-05-14 10:05:11 -0700270 _string_list_append_item ($1, $3);
Carl Worthfcbbb462010-05-13 09:36:23 -0700271 talloc_free ($3);
272 $$ = $1;
273 }
274;
275
Carl Worth7f9aa362010-05-13 12:58:49 -0700276identifier_perhaps_macro:
277 IDENTIFIER { $$ = $1; }
278| FUNC_MACRO { $$ = $1; }
279| OBJ_MACRO { $$ = $1; }
280;
281
Carl Worth0a93cbb2010-05-13 10:29:07 -0700282word:
Carl Worth9f62a7e2010-05-13 07:38:29 -0700283 IDENTIFIER { $$ = $1; }
Carl Worth9f62a7e2010-05-13 07:38:29 -0700284| TOKEN { $$ = $1; }
Carl Worth33cc4002010-05-12 12:17:10 -0700285;
286
287%%
288
Carl Worth610053b2010-05-14 10:05:11 -0700289string_list_t *
290_string_list_create (void *ctx)
Carl Worth33cc4002010-05-12 12:17:10 -0700291{
Carl Worth610053b2010-05-14 10:05:11 -0700292 string_list_t *list;
Carl Worth33cc4002010-05-12 12:17:10 -0700293
Carl Worth610053b2010-05-14 10:05:11 -0700294 list = xtalloc (ctx, string_list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700295 list->head = NULL;
296 list->tail = NULL;
297
298 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700299}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700300
Carl Worth33cc4002010-05-12 12:17:10 -0700301void
Carl Worth610053b2010-05-14 10:05:11 -0700302_string_list_append_list (string_list_t *list, string_list_t *tail)
Carl Worthfcbbb462010-05-13 09:36:23 -0700303{
304 if (list->head == NULL) {
305 list->head = tail->head;
306 } else {
307 list->tail->next = tail->head;
308 }
309
310 list->tail = tail->tail;
311}
312
313void
Carl Worth610053b2010-05-14 10:05:11 -0700314_string_list_append_item (string_list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700315{
Carl Worth610053b2010-05-14 10:05:11 -0700316 string_node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700317
Carl Worth610053b2010-05-14 10:05:11 -0700318 node = xtalloc (list, string_node_t);
Carl Worth5070a202010-05-12 12:45:33 -0700319 node->str = xtalloc_strdup (node, str);
Carl Worth33cc4002010-05-12 12:17:10 -0700320
321 node->next = NULL;
322
323 if (list->head == NULL) {
324 list->head = node;
325 } else {
326 list->tail->next = node;
327 }
328
329 list->tail = node;
330}
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700331
Carl Worth420d05a2010-05-17 10:15:23 -0700332void
333_string_list_push (string_list_t *list, const char *str)
334{
335 string_node_t *node;
336
337 node = xtalloc (list, string_node_t);
338 node->str = xtalloc_strdup (node, str);
339
340 node->next = list->head;
341
342 if (list->tail == NULL) {
343 list->tail = node;
344 }
345
346 list->head = node;
347}
348
349void
350_string_list_pop (string_list_t *list)
351{
352 string_node_t *node;
353
354 node = list->head;
355
356 if (node == NULL) {
357 fprintf (stderr, "Internal error: _string_list_pop called on an empty list.\n");
358 exit (1);
359 }
360
361 list->head = node->next;
362
363 if (list->tail == node) {
364 assert (node->next == NULL);
365 list->tail = NULL;
366 }
367
368 talloc_free (node);
369}
370
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700371int
Carl Worth610053b2010-05-14 10:05:11 -0700372_string_list_contains (string_list_t *list, const char *member, int *index)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700373{
Carl Worth610053b2010-05-14 10:05:11 -0700374 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700375 int i;
376
377 if (list == NULL)
378 return 0;
379
380 for (i = 0, node = list->head; node; i++, node = node->next) {
381 if (strcmp (node->str, member) == 0) {
Carl Worth420d05a2010-05-17 10:15:23 -0700382 if (index)
383 *index = i;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700384 return 1;
385 }
386 }
387
388 return 0;
389}
390
391int
Carl Worth610053b2010-05-14 10:05:11 -0700392_string_list_length (string_list_t *list)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700393{
394 int length = 0;
Carl Worth610053b2010-05-14 10:05:11 -0700395 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700396
397 if (list == NULL)
398 return 0;
399
400 for (node = list->head; node; node = node->next)
401 length++;
402
403 return length;
404}
405
Carl Worth2be8be02010-05-14 10:31:43 -0700406void
407_print_string_list (string_list_t *list)
408{
409 string_node_t *node;
410
411 if (list == NULL)
412 return;
413
Carl Worth81f01432010-05-14 17:08:45 -0700414 for (node = list->head; node; node = node->next) {
Carl Worth2be8be02010-05-14 10:31:43 -0700415 printf ("%s", node->str);
Carl Worth81f01432010-05-14 17:08:45 -0700416 if (node->next)
417 printf (" ");
418 }
Carl Worth2be8be02010-05-14 10:31:43 -0700419}
420
Carl Worth8f6a8282010-05-14 10:44:19 -0700421argument_list_t *
422_argument_list_create (void *ctx)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700423{
Carl Worth8f6a8282010-05-14 10:44:19 -0700424 argument_list_t *list;
425
426 list = xtalloc (ctx, argument_list_t);
427 list->head = NULL;
428 list->tail = NULL;
429
430 return list;
431}
432
433void
434_argument_list_append (argument_list_t *list, string_list_t *argument)
435{
436 argument_node_t *node;
437
438 if (argument == NULL || argument->head == NULL)
439 return;
440
441 node = xtalloc (list, argument_node_t);
442 node->argument = argument;
443
444 node->next = NULL;
445
446 if (list->head == NULL) {
447 list->head = node;
448 } else {
449 list->tail->next = node;
450 }
451
452 list->tail = node;
453}
454
455int
456_argument_list_length (argument_list_t *list)
457{
458 int length = 0;
459 argument_node_t *node;
460
461 if (list == NULL)
462 return 0;
463
464 for (node = list->head; node; node = node->next)
465 length++;
466
467 return length;
468}
469
470string_list_t *
471_argument_list_member_at (argument_list_t *list, int index)
472{
473 argument_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700474 int i;
475
476 if (list == NULL)
477 return NULL;
478
479 node = list->head;
480 for (i = 0; i < index; i++) {
481 node = node->next;
482 if (node == NULL)
483 break;
484 }
485
486 if (node)
Carl Worth8f6a8282010-05-14 10:44:19 -0700487 return node->argument;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700488
489 return NULL;
490}
Carl Worth33cc4002010-05-12 12:17:10 -0700491
Carl Worth3a37b872010-05-10 11:44:09 -0700492void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700493yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700494{
495 fprintf (stderr, "Parse error: %s\n", error);
496}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700497
Carl Worth33cc4002010-05-12 12:17:10 -0700498glcpp_parser_t *
499glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700500{
Carl Worth33cc4002010-05-12 12:17:10 -0700501 glcpp_parser_t *parser;
502
Carl Worth5070a202010-05-12 12:45:33 -0700503 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700504
Carl Worth5070a202010-05-12 12:45:33 -0700505 yylex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700506 parser->defines = hash_table_ctor (32, hash_table_string_hash,
507 hash_table_string_compare);
Carl Worth33cc4002010-05-12 12:17:10 -0700508
509 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700510}
511
512int
513glcpp_parser_parse (glcpp_parser_t *parser)
514{
515 return yyparse (parser);
516}
517
518void
Carl Worth33cc4002010-05-12 12:17:10 -0700519glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700520{
521 yylex_destroy (parser->scanner);
522 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700523 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700524}
Carl Worthc6d5af32010-05-11 12:30:09 -0700525
Carl Worthfcbbb462010-05-13 09:36:23 -0700526macro_type_t
527glcpp_parser_macro_type (glcpp_parser_t *parser, const char *identifier)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700528{
Carl Worthfcbbb462010-05-13 09:36:23 -0700529 macro_t *macro;
530
531 macro = hash_table_find (parser->defines, identifier);
532
533 if (macro == NULL)
534 return MACRO_TYPE_UNDEFINED;
535
536 if (macro->is_function)
537 return MACRO_TYPE_FUNCTION;
538 else
539 return MACRO_TYPE_OBJECT;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700540}
541
Carl Worth33cc4002010-05-12 12:17:10 -0700542void
Carl Worthfcbbb462010-05-13 09:36:23 -0700543_define_object_macro (glcpp_parser_t *parser,
544 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -0700545 string_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700546{
547 macro_t *macro;
548
549 macro = xtalloc (parser, macro_t);
550
551 macro->is_function = 0;
Carl Worthc5e98552010-05-14 10:12:21 -0700552 macro->parameters = NULL;
553 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700554
555 hash_table_insert (parser->defines, macro, identifier);
556}
557
558void
559_define_function_macro (glcpp_parser_t *parser,
560 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -0700561 string_list_t *parameters,
562 string_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700563{
564 macro_t *macro;
565
566 macro = xtalloc (parser, macro_t);
567
568 macro->is_function = 1;
Carl Worthc5e98552010-05-14 10:12:21 -0700569 macro->parameters = talloc_steal (macro, parameters);
570 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700571
572 hash_table_insert (parser->defines, macro, identifier);
573}
574
Carl Worth2be8be02010-05-14 10:31:43 -0700575static string_list_t *
576_expand_macro_recursive (glcpp_parser_t *parser,
577 const char *token,
Carl Worth420d05a2010-05-17 10:15:23 -0700578 string_list_t *active,
Carl Worth2be8be02010-05-14 10:31:43 -0700579 string_list_t *parameters,
Carl Worth8f6a8282010-05-14 10:44:19 -0700580 argument_list_t *arguments);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700581
Carl Worth2be8be02010-05-14 10:31:43 -0700582static string_list_t *
583_expand_string_list_recursive (glcpp_parser_t *parser,
584 string_list_t *list,
Carl Worth420d05a2010-05-17 10:15:23 -0700585 string_list_t *active,
Carl Worth2be8be02010-05-14 10:31:43 -0700586 string_list_t *parameters,
Carl Worth8f6a8282010-05-14 10:44:19 -0700587 argument_list_t *arguments)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700588{
Carl Worth2be8be02010-05-14 10:31:43 -0700589 string_list_t *result;
590 string_list_t *child;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700591 const char *token;
Carl Worth610053b2010-05-14 10:05:11 -0700592 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700593 int index;
594
Carl Worth2be8be02010-05-14 10:31:43 -0700595 result = _string_list_create (parser);
596
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700597 for (node = list->head ; node ; node = node->next) {
598 token = node->str;
599
Carl Worth420d05a2010-05-17 10:15:23 -0700600 /* Don't expand this macro if it's on the active
601 * stack, (meaning we're already in the process of
602 * expanding it). */
603 if (_string_list_contains (active, token, NULL)) {
Carl Worth2be8be02010-05-14 10:31:43 -0700604 _string_list_append_item (result, token);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700605 continue;
606 }
607
Carl Worth610053b2010-05-14 10:05:11 -0700608 if (_string_list_contains (parameters, token, &index)) {
Carl Worth8f6a8282010-05-14 10:44:19 -0700609 string_list_t *argument;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700610
Carl Worth8f6a8282010-05-14 10:44:19 -0700611 argument = _argument_list_member_at (arguments, index);
612 child = _expand_string_list_recursive (parser, argument,
Carl Worth420d05a2010-05-17 10:15:23 -0700613 active, NULL, NULL);
Carl Worth2be8be02010-05-14 10:31:43 -0700614 _string_list_append_list (result, child);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700615 } else {
Carl Worth2be8be02010-05-14 10:31:43 -0700616 child = _expand_macro_recursive (parser, token,
Carl Worth420d05a2010-05-17 10:15:23 -0700617 active, parameters,
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700618 arguments);
Carl Worth2be8be02010-05-14 10:31:43 -0700619 _string_list_append_list (result, child);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700620 }
621 }
Carl Worth2be8be02010-05-14 10:31:43 -0700622
623 return result;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700624}
625
626
Carl Worth2be8be02010-05-14 10:31:43 -0700627static string_list_t *
628_expand_macro_recursive (glcpp_parser_t *parser,
629 const char *token,
Carl Worth420d05a2010-05-17 10:15:23 -0700630 string_list_t *active,
Carl Worth2be8be02010-05-14 10:31:43 -0700631 string_list_t *parameters,
Carl Worth8f6a8282010-05-14 10:44:19 -0700632 argument_list_t *arguments)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700633{
634 macro_t *macro;
Carl Worthc5e98552010-05-14 10:12:21 -0700635 string_list_t *replacements;
Carl Worth420d05a2010-05-17 10:15:23 -0700636 string_list_t *result;
637
638 if (active == NULL)
639 active = _string_list_create (NULL);
640
641 _string_list_push (active, token);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700642
643 macro = hash_table_find (parser->defines, token);
644 if (macro == NULL) {
Carl Worth2be8be02010-05-14 10:31:43 -0700645 string_list_t *result;
646
647 result = _string_list_create (parser);
648 _string_list_append_item (result, token);
649 return result;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700650 }
651
Carl Worthc5e98552010-05-14 10:12:21 -0700652 replacements = macro->replacements;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700653
Carl Worth420d05a2010-05-17 10:15:23 -0700654 result = _expand_string_list_recursive (parser, replacements,
655 active, parameters, arguments);
656
657 _string_list_pop (active);
658 if (_string_list_length (active) == 0)
659 talloc_free (active);
660
661 return result;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700662}
663
Carl Worth2be8be02010-05-14 10:31:43 -0700664string_list_t *
665_expand_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700666{
Carl Worthfcbbb462010-05-13 09:36:23 -0700667 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700668
Carl Worthfcbbb462010-05-13 09:36:23 -0700669 macro = hash_table_find (parser->defines, identifier);
670 assert (! macro->is_function);
671
Carl Worth420d05a2010-05-17 10:15:23 -0700672 return _expand_macro_recursive (parser, identifier, NULL,
Carl Worth2be8be02010-05-14 10:31:43 -0700673 NULL, NULL);
Carl Worthfcbbb462010-05-13 09:36:23 -0700674}
675
Carl Worth2be8be02010-05-14 10:31:43 -0700676string_list_t *
677_expand_function_macro (glcpp_parser_t *parser,
678 const char *identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700679 argument_list_t *arguments)
Carl Worthfcbbb462010-05-13 09:36:23 -0700680{
Carl Worthfcbbb462010-05-13 09:36:23 -0700681 macro_t *macro;
682
683 macro = hash_table_find (parser->defines, identifier);
684 assert (macro->is_function);
685
Carl Worth8f6a8282010-05-14 10:44:19 -0700686 if (_argument_list_length (arguments) !=
Carl Worth2be8be02010-05-14 10:31:43 -0700687 _string_list_length (macro->parameters))
688 {
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700689 fprintf (stderr,
690 "Error: macro %s invoked with %d arguments (expected %d)\n",
691 identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700692 _argument_list_length (arguments),
Carl Worthc5e98552010-05-14 10:12:21 -0700693 _string_list_length (macro->parameters));
Carl Worth2be8be02010-05-14 10:31:43 -0700694 return NULL;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700695 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700696
Carl Worth420d05a2010-05-17 10:15:23 -0700697 return _expand_macro_recursive (parser, identifier, NULL,
Carl Worth2be8be02010-05-14 10:31:43 -0700698 macro->parameters, arguments);
Carl Worth33cc4002010-05-12 12:17:10 -0700699}