blob: c53370a89ad28373ed2ddfc9123b68c5fe193e25 [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 Worth3a37b872010-05-10 11:44:09 -070031void
Carl Wortha1e32bc2010-05-10 13:17:25 -070032yyerror (void *scanner, const char *error);
Carl Worth3a37b872010-05-10 11:44:09 -070033
Carl Worth33cc4002010-05-12 12:17:10 -070034void
Carl Worthfcbbb462010-05-13 09:36:23 -070035_define_object_macro (glcpp_parser_t *parser,
36 const char *macro,
Carl Worth47252442010-05-19 13:54:37 -070037 token_list_t *replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -070038
39void
40_define_function_macro (glcpp_parser_t *parser,
41 const char *macro,
Carl Worthc5e98552010-05-14 10:12:21 -070042 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -070043 token_list_t *replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -070044
Carl Wortha807fb72010-05-18 22:10:04 -070045void
Carl Worth2be8be02010-05-14 10:31:43 -070046_expand_object_macro (glcpp_parser_t *parser, const char *identifier);
47
Carl Wortha807fb72010-05-18 22:10:04 -070048void
Carl Worth2be8be02010-05-14 10:31:43 -070049_expand_function_macro (glcpp_parser_t *parser,
50 const char *identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -070051 argument_list_t *arguments);
Carl Worthfcbbb462010-05-13 09:36:23 -070052
Carl Worth610053b2010-05-14 10:05:11 -070053string_list_t *
54_string_list_create (void *ctx);
Carl Worth33cc4002010-05-12 12:17:10 -070055
56void
Carl Worth610053b2010-05-14 10:05:11 -070057_string_list_append_item (string_list_t *list, const char *str);
Carl Worthfcbbb462010-05-13 09:36:23 -070058
59void
Carl Worth610053b2010-05-14 10:05:11 -070060_string_list_append_list (string_list_t *list, string_list_t *tail);
Carl Worthc6d5af32010-05-11 12:30:09 -070061
Carl Worthdcc2ecd2010-05-13 12:56:42 -070062int
Carl Worth610053b2010-05-14 10:05:11 -070063_string_list_contains (string_list_t *list, const char *member, int *index);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070064
Carl Worthdcc2ecd2010-05-13 12:56:42 -070065int
Carl Worth610053b2010-05-14 10:05:11 -070066_string_list_length (string_list_t *list);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070067
Carl Worth8f6a8282010-05-14 10:44:19 -070068argument_list_t *
69_argument_list_create (void *ctx);
70
71void
Carl Worth47252442010-05-19 13:54:37 -070072_argument_list_append (argument_list_t *list, token_list_t *argument);
Carl Worth8f6a8282010-05-14 10:44:19 -070073
74int
75_argument_list_length (argument_list_t *list);
76
Carl Worth47252442010-05-19 13:54:37 -070077token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -070078_argument_list_member_at (argument_list_t *list, int index);
79
Carl Worth47252442010-05-19 13:54:37 -070080token_list_t *
81_token_list_create (void *ctx);
82
83void
84_token_list_append (token_list_t *list, int type, const char *value);
85
86void
87_token_list_append_list (token_list_t *list, token_list_t *tail);
88
Carl Worthaaa9acb2010-05-19 13:28:24 -070089static void
Carl Worthaaa9acb2010-05-19 13:28:24 -070090glcpp_parser_pop_expansion (glcpp_parser_t *parser);
91
Carl Worthb20d33c2010-05-20 22:27:07 -070092static void
93_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition);
94
95static void
96_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
97 int condition);
Carl Worth80dc60b2010-05-25 14:42:00 -070098
Carl Worthb20d33c2010-05-20 22:27:07 -070099static void
100_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser);
101
Carl Worth0293b2e2010-05-19 10:05:40 -0700102#define yylex glcpp_parser_lex
103
Carl Worth8f38aff2010-05-19 10:01:29 -0700104static int
Carl Worth0293b2e2010-05-19 10:05:40 -0700105glcpp_parser_lex (glcpp_parser_t *parser);
Carl Worth8f38aff2010-05-19 10:01:29 -0700106
Carl Worth3a37b872010-05-10 11:44:09 -0700107%}
108
Carl Worth33cc4002010-05-12 12:17:10 -0700109%union {
Carl Worth35419092010-05-24 11:27:23 -0700110 intmax_t imaxval;
Carl Worth005b3202010-05-20 14:19:57 -0700111 int ival;
Carl Worth33cc4002010-05-12 12:17:10 -0700112 char *str;
Carl Worth8f6a8282010-05-14 10:44:19 -0700113 argument_list_t *argument_list;
Carl Worth47252442010-05-19 13:54:37 -0700114 string_list_t *string_list;
Carl Worthb5693832010-05-20 08:01:44 -0700115 token_t token;
Carl Worth47252442010-05-19 13:54:37 -0700116 token_list_t *token_list;
Carl Worth33cc4002010-05-12 12:17:10 -0700117}
118
Carl Worth0b27b5f2010-05-10 16:16:06 -0700119%parse-param {glcpp_parser_t *parser}
Carl Worth0293b2e2010-05-19 10:05:40 -0700120%lex-param {glcpp_parser_t *parser}
Carl Worth38aa8352010-05-10 11:52:29 -0700121
Carl Worth3ff81672010-05-25 13:09:03 -0700122%token HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH IDENTIFIER NEWLINE OTHER HASH_UNDEF
123%token LEFT_SHIFT RIGHT_SHIFT LESS_OR_EQUAL GREATER_OR_EQUAL EQUAL NOT_EQUAL AND OR PASTE
Carl Worth3a37b872010-05-10 11:44:09 -0700124
Carl Worth3ff81672010-05-25 13:09:03 -0700125 /* Stale stuff just to allow code to compile. */
126%token IDENTIFIER_FINALIZED FUNC_MACRO OBJ_MACRO
Carl Worth796e1f02010-05-17 12:45:16 -0700127
Carl Worth3a37b872010-05-10 11:44:09 -0700128%%
129
Carl Worth33cc4002010-05-12 12:17:10 -0700130input:
Carl Worth3ff81672010-05-25 13:09:03 -0700131 /* empty */
132| input line
Carl Worth3a37b872010-05-10 11:44:09 -0700133;
134
Carl Worth3ff81672010-05-25 13:09:03 -0700135line:
136 control_line
137| text_line
138| HASH non_directive
Carl Worthcd27e642010-05-12 13:11:50 -0700139;
140
Carl Worth3ff81672010-05-25 13:09:03 -0700141control_line:
142 HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE
143| HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE
144| HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE
145| HASH_UNDEF IDENTIFIER NEWLINE
146| HASH NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700147;
148
Carl Worth3ff81672010-05-25 13:09:03 -0700149identifier_list:
150 IDENTIFIER
151| identifier_list ',' IDENTIFIER
Carl Worthfcbbb462010-05-13 09:36:23 -0700152;
153
Carl Worth3ff81672010-05-25 13:09:03 -0700154text_line:
155 NEWLINE
156| pp_tokens NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700157;
158
Carl Worth3ff81672010-05-25 13:09:03 -0700159non_directive:
160 pp_tokens NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700161;
162
Carl Worthaaa9acb2010-05-19 13:28:24 -0700163replacement_list:
Carl Worth3ff81672010-05-25 13:09:03 -0700164 /* empty */
165| pp_tokens
Carl Worthaaa9acb2010-05-19 13:28:24 -0700166;
167
Carl Worthaaa9acb2010-05-19 13:28:24 -0700168pp_tokens:
Carl Worth3ff81672010-05-25 13:09:03 -0700169 preprocessing_token
170| pp_tokens preprocessing_token
Carl Worthaaa9acb2010-05-19 13:28:24 -0700171;
172
Carl Worth3ff81672010-05-25 13:09:03 -0700173preprocessing_token:
174 IDENTIFIER
175| punctuator
176| OTHER
177;
178
179punctuator:
180 '['
181| ']'
182| '('
183| ')'
184| '{'
185| '}'
186| '.'
187| '&'
188| '*'
189| '+'
190| '-'
191| '~'
192| '!'
193| '/'
194| '%'
195| LEFT_SHIFT
196| RIGHT_SHIFT
197| '<'
198| '>'
199| LESS_OR_EQUAL
200| GREATER_OR_EQUAL
201| EQUAL
202| NOT_EQUAL
203| '^'
204| '|'
205| AND
206| OR
207| ';'
208| ','
209| PASTE
210;
211
212
Carl Worth33cc4002010-05-12 12:17:10 -0700213%%
214
Carl Worth610053b2010-05-14 10:05:11 -0700215string_list_t *
216_string_list_create (void *ctx)
Carl Worth33cc4002010-05-12 12:17:10 -0700217{
Carl Worth610053b2010-05-14 10:05:11 -0700218 string_list_t *list;
Carl Worth33cc4002010-05-12 12:17:10 -0700219
Carl Worth610053b2010-05-14 10:05:11 -0700220 list = xtalloc (ctx, string_list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700221 list->head = NULL;
222 list->tail = NULL;
223
224 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700225}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700226
Carl Worth33cc4002010-05-12 12:17:10 -0700227void
Carl Worth610053b2010-05-14 10:05:11 -0700228_string_list_append_list (string_list_t *list, string_list_t *tail)
Carl Worthfcbbb462010-05-13 09:36:23 -0700229{
230 if (list->head == NULL) {
231 list->head = tail->head;
232 } else {
233 list->tail->next = tail->head;
234 }
235
236 list->tail = tail->tail;
237}
238
239void
Carl Worth610053b2010-05-14 10:05:11 -0700240_string_list_append_item (string_list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700241{
Carl Worth610053b2010-05-14 10:05:11 -0700242 string_node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700243
Carl Worth610053b2010-05-14 10:05:11 -0700244 node = xtalloc (list, string_node_t);
Carl Worth5070a202010-05-12 12:45:33 -0700245 node->str = xtalloc_strdup (node, str);
Carl Worth80dc60b2010-05-25 14:42:00 -0700246
Carl Worth33cc4002010-05-12 12:17:10 -0700247 node->next = NULL;
248
249 if (list->head == NULL) {
250 list->head = node;
251 } else {
252 list->tail->next = node;
253 }
254
255 list->tail = node;
256}
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700257
258int
Carl Worth610053b2010-05-14 10:05:11 -0700259_string_list_contains (string_list_t *list, const char *member, int *index)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700260{
Carl Worth610053b2010-05-14 10:05:11 -0700261 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700262 int i;
263
264 if (list == NULL)
265 return 0;
266
267 for (i = 0, node = list->head; node; i++, node = node->next) {
268 if (strcmp (node->str, member) == 0) {
Carl Worth420d05a2010-05-17 10:15:23 -0700269 if (index)
270 *index = i;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700271 return 1;
272 }
273 }
274
275 return 0;
276}
277
278int
Carl Worth610053b2010-05-14 10:05:11 -0700279_string_list_length (string_list_t *list)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700280{
281 int length = 0;
Carl Worth610053b2010-05-14 10:05:11 -0700282 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700283
284 if (list == NULL)
285 return 0;
286
287 for (node = list->head; node; node = node->next)
288 length++;
289
290 return length;
291}
292
Carl Worth8f6a8282010-05-14 10:44:19 -0700293argument_list_t *
294_argument_list_create (void *ctx)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700295{
Carl Worth8f6a8282010-05-14 10:44:19 -0700296 argument_list_t *list;
297
298 list = xtalloc (ctx, argument_list_t);
299 list->head = NULL;
300 list->tail = NULL;
301
302 return list;
303}
304
305void
Carl Worth47252442010-05-19 13:54:37 -0700306_argument_list_append (argument_list_t *list, token_list_t *argument)
Carl Worth8f6a8282010-05-14 10:44:19 -0700307{
308 argument_node_t *node;
309
310 if (argument == NULL || argument->head == NULL)
311 return;
312
313 node = xtalloc (list, argument_node_t);
314 node->argument = argument;
315
316 node->next = NULL;
317
318 if (list->head == NULL) {
319 list->head = node;
320 } else {
321 list->tail->next = node;
322 }
323
324 list->tail = node;
325}
326
327int
328_argument_list_length (argument_list_t *list)
329{
330 int length = 0;
331 argument_node_t *node;
332
333 if (list == NULL)
334 return 0;
335
336 for (node = list->head; node; node = node->next)
337 length++;
338
339 return length;
340}
341
Carl Worth47252442010-05-19 13:54:37 -0700342token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -0700343_argument_list_member_at (argument_list_t *list, int index)
344{
345 argument_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700346 int i;
347
348 if (list == NULL)
349 return NULL;
350
351 node = list->head;
352 for (i = 0; i < index; i++) {
353 node = node->next;
354 if (node == NULL)
355 break;
356 }
357
358 if (node)
Carl Worth8f6a8282010-05-14 10:44:19 -0700359 return node->argument;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700360
361 return NULL;
362}
Carl Worth47252442010-05-19 13:54:37 -0700363
364token_list_t *
365_token_list_create (void *ctx)
366{
367 token_list_t *list;
368
369 list = xtalloc (ctx, token_list_t);
370 list->head = NULL;
371 list->tail = NULL;
372
373 return list;
374}
375
376void
377_token_list_append (token_list_t *list, int type, const char *value)
378{
379 token_node_t *node;
380
381 node = xtalloc (list, token_node_t);
382 node->type = type;
383 node->value = xtalloc_strdup (list, value);
384
385 node->next = NULL;
386
387 if (list->head == NULL) {
388 list->head = node;
389 } else {
390 list->tail->next = node;
391 }
392
393 list->tail = node;
394}
395
396void
397_token_list_append_list (token_list_t *list, token_list_t *tail)
398{
399 if (list->head == NULL) {
400 list->head = tail->head;
401 } else {
402 list->tail->next = tail->head;
403 }
404
405 list->tail = tail->tail;
406}
Carl Worth80dc60b2010-05-25 14:42:00 -0700407
Carl Worth3a37b872010-05-10 11:44:09 -0700408void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700409yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700410{
411 fprintf (stderr, "Parse error: %s\n", error);
412}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700413
Carl Worth33cc4002010-05-12 12:17:10 -0700414glcpp_parser_t *
415glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700416{
Carl Worth33cc4002010-05-12 12:17:10 -0700417 glcpp_parser_t *parser;
418
Carl Worth5070a202010-05-12 12:45:33 -0700419 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700420
Carl Worth8f38aff2010-05-19 10:01:29 -0700421 glcpp_lex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700422 parser->defines = hash_table_ctor (32, hash_table_string_hash,
423 hash_table_string_compare);
Carl Wortha807fb72010-05-18 22:10:04 -0700424 parser->expansions = NULL;
425
Carl Worth5a6b9a22010-05-20 14:29:43 -0700426 parser->just_printed_separator = 1;
Carl Worth876e5102010-05-20 14:38:06 -0700427 parser->need_newline = 0;
Carl Worth5a6b9a22010-05-20 14:29:43 -0700428
Carl Worthb20d33c2010-05-20 22:27:07 -0700429 parser->skip_stack = NULL;
430
Carl Worth33cc4002010-05-12 12:17:10 -0700431 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700432}
433
434int
435glcpp_parser_parse (glcpp_parser_t *parser)
436{
437 return yyparse (parser);
438}
439
440void
Carl Worth33cc4002010-05-12 12:17:10 -0700441glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700442{
Carl Worth876e5102010-05-20 14:38:06 -0700443 if (parser->need_newline)
444 printf ("\n");
Carl Worthb20d33c2010-05-20 22:27:07 -0700445 if (parser->skip_stack)
446 fprintf (stderr, "Error: Unterminated #if\n");
Carl Worth8f38aff2010-05-19 10:01:29 -0700447 glcpp_lex_destroy (parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700448 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700449 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700450}
Carl Worthc6d5af32010-05-11 12:30:09 -0700451
Carl Worthbe0e2e92010-05-19 07:29:22 -0700452static int
453glcpp_parser_is_expanding (glcpp_parser_t *parser, const char *member)
454{
455 expansion_node_t *node;
456
457 for (node = parser->expansions; node; node = node->next) {
458 if (node->macro &&
459 strcmp (node->macro->identifier, member) == 0)
460 {
461 return 1;
462 }
463 }
464
465 return 0;
466}
467
Carl Wortha807fb72010-05-18 22:10:04 -0700468token_class_t
469glcpp_parser_classify_token (glcpp_parser_t *parser,
470 const char *identifier,
471 int *parameter_index)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700472{
Carl Worthfcbbb462010-05-13 09:36:23 -0700473 macro_t *macro;
474
Carl Worthc10a51b2010-05-20 15:15:26 -0700475 /* Is this token a defined macro? */
Carl Worthfcbbb462010-05-13 09:36:23 -0700476 macro = hash_table_find (parser->defines, identifier);
477
478 if (macro == NULL)
Carl Wortha807fb72010-05-18 22:10:04 -0700479 return TOKEN_CLASS_IDENTIFIER;
Carl Worthfcbbb462010-05-13 09:36:23 -0700480
Carl Worthbe0e2e92010-05-19 07:29:22 -0700481 /* Don't consider this a macro if we are already actively
482 * expanding this macro. */
483 if (glcpp_parser_is_expanding (parser, identifier))
Carl Worthb5693832010-05-20 08:01:44 -0700484 return TOKEN_CLASS_IDENTIFIER_FINALIZED;
Carl Worthbe0e2e92010-05-19 07:29:22 -0700485
486 /* Definitely a macro. Just need to check if it's function-like. */
Carl Worthfcbbb462010-05-13 09:36:23 -0700487 if (macro->is_function)
Carl Wortha807fb72010-05-18 22:10:04 -0700488 return TOKEN_CLASS_FUNC_MACRO;
Carl Worthfcbbb462010-05-13 09:36:23 -0700489 else
Carl Wortha807fb72010-05-18 22:10:04 -0700490 return TOKEN_CLASS_OBJ_MACRO;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700491}
492
Carl Worth33cc4002010-05-12 12:17:10 -0700493void
Carl Worthfcbbb462010-05-13 09:36:23 -0700494_define_object_macro (glcpp_parser_t *parser,
495 const char *identifier,
Carl Worth47252442010-05-19 13:54:37 -0700496 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700497{
498 macro_t *macro;
499
500 macro = xtalloc (parser, macro_t);
501
502 macro->is_function = 0;
Carl Worthc5e98552010-05-14 10:12:21 -0700503 macro->parameters = NULL;
Carl Wortha807fb72010-05-18 22:10:04 -0700504 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700505 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700506
507 hash_table_insert (parser->defines, macro, identifier);
508}
509
510void
511_define_function_macro (glcpp_parser_t *parser,
512 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -0700513 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -0700514 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700515{
516 macro_t *macro;
517
518 macro = xtalloc (parser, macro_t);
519
520 macro->is_function = 1;
Carl Worthc5e98552010-05-14 10:12:21 -0700521 macro->parameters = talloc_steal (macro, parameters);
Carl Wortha807fb72010-05-18 22:10:04 -0700522 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700523 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700524
525 hash_table_insert (parser->defines, macro, identifier);
526}
527
Carl Wortha807fb72010-05-18 22:10:04 -0700528static void
Carl Worthc10a51b2010-05-20 15:15:26 -0700529_glcpp_parser_push_expansion (glcpp_parser_t *parser,
530 macro_t *macro,
531 token_node_t *replacements)
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;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700538 node->replacements = replacements;
Carl Wortha807fb72010-05-18 22:10:04 -0700539
540 node->next = parser->expansions;
541 parser->expansions = node;
Carl Wortha807fb72010-05-18 22:10:04 -0700542}
543
Carl Worthaaa9acb2010-05-19 13:28:24 -0700544static void
Carl Wortha807fb72010-05-18 22:10:04 -0700545glcpp_parser_pop_expansion (glcpp_parser_t *parser)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700546{
Carl Wortha807fb72010-05-18 22:10:04 -0700547 expansion_node_t *node;
Carl Worth420d05a2010-05-17 10:15:23 -0700548
Carl Wortha807fb72010-05-18 22:10:04 -0700549 node = parser->expansions;
Carl Worth420d05a2010-05-17 10:15:23 -0700550
Carl Wortha807fb72010-05-18 22:10:04 -0700551 if (node == NULL) {
552 fprintf (stderr, "Internal error: _expansion_list_pop called on an empty list.\n");
553 exit (1);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700554 }
555
Carl Wortha807fb72010-05-18 22:10:04 -0700556 parser->expansions = node->next;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700557
Carl Wortha807fb72010-05-18 22:10:04 -0700558 talloc_free (node);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700559}
560
Carl Wortha807fb72010-05-18 22:10:04 -0700561void
Carl Worth2be8be02010-05-14 10:31:43 -0700562_expand_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700563{
Carl Worthfcbbb462010-05-13 09:36:23 -0700564 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700565
Carl Worthfcbbb462010-05-13 09:36:23 -0700566 macro = hash_table_find (parser->defines, identifier);
567 assert (! macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700568 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700569
Carl Worthc10a51b2010-05-20 15:15:26 -0700570 _glcpp_parser_push_expansion (parser, macro, macro->replacements->head);
Carl Worthfcbbb462010-05-13 09:36:23 -0700571}
572
Carl Wortha807fb72010-05-18 22:10:04 -0700573void
Carl Worth2be8be02010-05-14 10:31:43 -0700574_expand_function_macro (glcpp_parser_t *parser,
575 const char *identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700576 argument_list_t *arguments)
Carl Worthfcbbb462010-05-13 09:36:23 -0700577{
Carl Worthfcbbb462010-05-13 09:36:23 -0700578 macro_t *macro;
Carl Worthc10a51b2010-05-20 15:15:26 -0700579 token_list_t *expanded;
580 token_node_t *i, *j;
581 int parameter_index;
Carl Worthfcbbb462010-05-13 09:36:23 -0700582
583 macro = hash_table_find (parser->defines, identifier);
584 assert (macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700585 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700586
Carl Worth8f6a8282010-05-14 10:44:19 -0700587 if (_argument_list_length (arguments) !=
Carl Worth2be8be02010-05-14 10:31:43 -0700588 _string_list_length (macro->parameters))
589 {
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700590 fprintf (stderr,
591 "Error: macro %s invoked with %d arguments (expected %d)\n",
592 identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700593 _argument_list_length (arguments),
Carl Worthc5e98552010-05-14 10:12:21 -0700594 _string_list_length (macro->parameters));
Carl Wortha807fb72010-05-18 22:10:04 -0700595 return;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700596 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700597
Carl Worthc10a51b2010-05-20 15:15:26 -0700598 expanded = _token_list_create (macro);
599
600 for (i = macro->replacements->head; i; i = i->next) {
601 if (_string_list_contains (macro->parameters, i->value,
602 &parameter_index))
603 {
604 token_list_t *argument;
605 argument = _argument_list_member_at (arguments,
606 parameter_index);
607 for (j = argument->head; j; j = j->next)
608 {
609 _token_list_append (expanded, j->type,
610 j->value);
611 }
612 } else {
613 _token_list_append (expanded, i->type, i->value);
614 }
615 }
616
617 _glcpp_parser_push_expansion (parser, macro, expanded->head);
Carl Worth33cc4002010-05-12 12:17:10 -0700618}
Carl Worth8f38aff2010-05-19 10:01:29 -0700619
620static int
Carl Worth0293b2e2010-05-19 10:05:40 -0700621glcpp_parser_lex (glcpp_parser_t *parser)
Carl Worth8f38aff2010-05-19 10:01:29 -0700622{
Carl Worthaaa9acb2010-05-19 13:28:24 -0700623 expansion_node_t *expansion;
Carl Worth47252442010-05-19 13:54:37 -0700624 token_node_t *replacements;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700625 int parameter_index;
Carl Worthd8327e52010-05-20 15:18:54 -0700626 const char *token;
627 token_class_t class;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700628
629 /* Who says C can't do efficient tail recursion? */
630 RECURSE:
631
632 expansion = parser->expansions;
633
634 if (expansion == NULL)
635 return glcpp_lex (parser->scanner);
636
637 replacements = expansion->replacements;
638
639 /* Pop expansion when replacements is exhausted. */
640 if (replacements == NULL) {
641 glcpp_parser_pop_expansion (parser);
642 goto RECURSE;
643 }
644
645 expansion->replacements = replacements->next;
646
Carl Worthd8327e52010-05-20 15:18:54 -0700647 token = replacements->value;
648
649 /* Implement token pasting. */
650 if (replacements->next && strcmp (replacements->next->value, "##") == 0) {
651 token_node_t *next_node;
652
653 next_node = replacements->next->next;
654
655 if (next_node == NULL) {
656 fprintf (stderr, "Error: '##' cannot appear at the end of a macro expansion.\n");
657 exit (1);
658 }
659
660 token = xtalloc_asprintf (parser, "%s%s",
661 token, next_node->value);
662 expansion->replacements = next_node->next;
663 }
664
665
666 if (strcmp (token, "(") == 0)
Carl Worthaaa9acb2010-05-19 13:28:24 -0700667 return '(';
Carl Worthd8327e52010-05-20 15:18:54 -0700668 else if (strcmp (token, ")") == 0)
Carl Worthaaa9acb2010-05-19 13:28:24 -0700669 return ')';
Carl Worthaaa9acb2010-05-19 13:28:24 -0700670
Carl Worthd8327e52010-05-20 15:18:54 -0700671 yylval.str = xtalloc_strdup (parser, token);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700672
Carl Worthb5693832010-05-20 08:01:44 -0700673 /* Carefully refuse to expand any finalized identifier. */
674 if (replacements->type == IDENTIFIER_FINALIZED)
675 return IDENTIFIER_FINALIZED;
676
Carl Worthaaa9acb2010-05-19 13:28:24 -0700677 switch (glcpp_parser_classify_token (parser, yylval.str,
678 &parameter_index))
679 {
Carl Worthaaa9acb2010-05-19 13:28:24 -0700680 case TOKEN_CLASS_IDENTIFIER:
681 return IDENTIFIER;
682 break;
Carl Worthb5693832010-05-20 08:01:44 -0700683 case TOKEN_CLASS_IDENTIFIER_FINALIZED:
684 return IDENTIFIER_FINALIZED;
685 break;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700686 case TOKEN_CLASS_FUNC_MACRO:
687 return FUNC_MACRO;
688 break;
689 default:
690 case TOKEN_CLASS_OBJ_MACRO:
691 return OBJ_MACRO;
692 break;
693 }
Carl Worth8f38aff2010-05-19 10:01:29 -0700694}
Carl Worthb20d33c2010-05-20 22:27:07 -0700695
696static void
697_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition)
698{
699 skip_type_t current = SKIP_NO_SKIP;
700 skip_node_t *node;
701
702 if (parser->skip_stack)
703 current = parser->skip_stack->type;
704
705 node = xtalloc (parser, skip_node_t);
706
707 if (current == SKIP_NO_SKIP) {
708 if (condition)
709 node->type = SKIP_NO_SKIP;
710 else
711 node->type = SKIP_TO_ELSE;
712 } else {
713 node->type = SKIP_TO_ENDIF;
714 }
715
716 node->next = parser->skip_stack;
717 parser->skip_stack = node;
718}
719
720static void
721_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
722 int condition)
723{
724 if (parser->skip_stack == NULL) {
725 fprintf (stderr, "Error: %s without #if\n", type);
726 exit (1);
727 }
728
729 if (parser->skip_stack->type == SKIP_TO_ELSE) {
730 if (condition)
731 parser->skip_stack->type = SKIP_NO_SKIP;
732 } else {
733 parser->skip_stack->type = SKIP_TO_ENDIF;
734 }
735}
Carl Worth80dc60b2010-05-25 14:42:00 -0700736
Carl Worthb20d33c2010-05-20 22:27:07 -0700737static void
738_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser)
739{
740 skip_node_t *node;
741
742 if (parser->skip_stack == NULL) {
743 fprintf (stderr, "Error: #endif without #if\n");
744 exit (1);
745 }
746
747 node = parser->skip_stack;
748 parser->skip_stack = node->next;
749 talloc_free (node);
750}