blob: 131102fab95d9d7e18e5e16689155d20406d4870 [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 Worthae6517f2010-05-25 15:24:59 -070062void
63_string_list_push (string_list_t *list, const char *str);
64
65void
66_string_list_pop (string_list_t *list);
67
Carl Worthdcc2ecd2010-05-13 12:56:42 -070068int
Carl Worth610053b2010-05-14 10:05:11 -070069_string_list_contains (string_list_t *list, const char *member, int *index);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070070
Carl Worthdcc2ecd2010-05-13 12:56:42 -070071int
Carl Worth610053b2010-05-14 10:05:11 -070072_string_list_length (string_list_t *list);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070073
Carl Worth8f6a8282010-05-14 10:44:19 -070074argument_list_t *
75_argument_list_create (void *ctx);
76
77void
Carl Worth47252442010-05-19 13:54:37 -070078_argument_list_append (argument_list_t *list, token_list_t *argument);
Carl Worth8f6a8282010-05-14 10:44:19 -070079
80int
81_argument_list_length (argument_list_t *list);
82
Carl Worth47252442010-05-19 13:54:37 -070083token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -070084_argument_list_member_at (argument_list_t *list, int index);
85
Carl Worth808401f2010-05-25 14:52:43 -070086/* Note: This function talloc_steal()s the str pointer. */
87token_t *
88_token_create_str (void *ctx, int type, char *str);
89
90token_t *
91_token_create_ival (void *ctx, int type, int ival);
92
Carl Worth47252442010-05-19 13:54:37 -070093token_list_t *
94_token_list_create (void *ctx);
95
Carl Worth808401f2010-05-25 14:52:43 -070096/* Note: This function add a talloc_reference() to token.
97 *
98 * You may want to talloc_unlink any current reference if you no
99 * longer need it. */
Carl Worth47252442010-05-19 13:54:37 -0700100void
Carl Worth808401f2010-05-25 14:52:43 -0700101_token_list_append (token_list_t *list, token_t *token);
Carl Worth47252442010-05-19 13:54:37 -0700102
103void
104_token_list_append_list (token_list_t *list, token_list_t *tail);
105
Carl Worth808401f2010-05-25 14:52:43 -0700106void
Carl Worthae6517f2010-05-25 15:24:59 -0700107_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
108 token_list_t *list);
Carl Worth808401f2010-05-25 14:52:43 -0700109
Carl Worthaaa9acb2010-05-19 13:28:24 -0700110static void
Carl Worthaaa9acb2010-05-19 13:28:24 -0700111glcpp_parser_pop_expansion (glcpp_parser_t *parser);
112
Carl Worthb20d33c2010-05-20 22:27:07 -0700113static void
114_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition);
115
116static void
117_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
118 int condition);
Carl Worth80dc60b2010-05-25 14:42:00 -0700119
Carl Worthb20d33c2010-05-20 22:27:07 -0700120static void
121_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser);
122
Carl Worth0293b2e2010-05-19 10:05:40 -0700123#define yylex glcpp_parser_lex
124
Carl Worth8f38aff2010-05-19 10:01:29 -0700125static int
Carl Worth0293b2e2010-05-19 10:05:40 -0700126glcpp_parser_lex (glcpp_parser_t *parser);
Carl Worth8f38aff2010-05-19 10:01:29 -0700127
Carl Worth3a37b872010-05-10 11:44:09 -0700128%}
129
Carl Worth0b27b5f2010-05-10 16:16:06 -0700130%parse-param {glcpp_parser_t *parser}
Carl Worth0293b2e2010-05-19 10:05:40 -0700131%lex-param {glcpp_parser_t *parser}
Carl Worth38aa8352010-05-10 11:52:29 -0700132
Carl Worthb1854fd2010-05-25 16:28:26 -0700133%token HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_UNDEF IDENTIFIER NEWLINE OTHER SPACE
Carl Worth3ff81672010-05-25 13:09:03 -0700134%token LEFT_SHIFT RIGHT_SHIFT LESS_OR_EQUAL GREATER_OR_EQUAL EQUAL NOT_EQUAL AND OR PASTE
Carl Worthe9397862010-05-25 17:08:07 -0700135%type <ival> punctuator SPACE
136%type <str> IDENTIFIER OTHER
Carl Worthb1854fd2010-05-25 16:28:26 -0700137%type <string_list> identifier_list
Carl Worth808401f2010-05-25 14:52:43 -0700138%type <token> preprocessing_token
139%type <token_list> pp_tokens replacement_list text_line
Carl Worth3a37b872010-05-10 11:44:09 -0700140
Carl Worth3ff81672010-05-25 13:09:03 -0700141 /* Stale stuff just to allow code to compile. */
142%token IDENTIFIER_FINALIZED FUNC_MACRO OBJ_MACRO
Carl Worth796e1f02010-05-17 12:45:16 -0700143
Carl Worth3a37b872010-05-10 11:44:09 -0700144%%
145
Carl Worth33cc4002010-05-12 12:17:10 -0700146input:
Carl Worth3ff81672010-05-25 13:09:03 -0700147 /* empty */
Carl Worthae6517f2010-05-25 15:24:59 -0700148| input line {
149 printf ("\n");
150 }
Carl Worth3a37b872010-05-10 11:44:09 -0700151;
152
Carl Worth3ff81672010-05-25 13:09:03 -0700153line:
154 control_line
Carl Worth808401f2010-05-25 14:52:43 -0700155| text_line {
Carl Worthae6517f2010-05-25 15:24:59 -0700156 _glcpp_parser_print_expanded_token_list (parser, $1);
Carl Worth808401f2010-05-25 14:52:43 -0700157 talloc_free ($1);
158 }
Carl Worth3ff81672010-05-25 13:09:03 -0700159| HASH non_directive
Carl Worthcd27e642010-05-12 13:11:50 -0700160;
161
Carl Worth3ff81672010-05-25 13:09:03 -0700162control_line:
Carl Worthf34a0002010-05-25 16:59:02 -0700163 HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
Carl Worthae6517f2010-05-25 15:24:59 -0700164 _define_object_macro (parser, $2, $3);
165 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700166| HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
167 _define_function_macro (parser, $2, NULL, $5);
168 }
169| HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
170 _define_function_macro (parser, $2, $4, $6);
171 }
Carl Worthe6fb7822010-05-25 15:28:58 -0700172| HASH_UNDEF IDENTIFIER NEWLINE {
173 string_list_t *macro = hash_table_find (parser->defines, $2);
174 if (macro) {
175 /* XXX: Need hash table to support a real way
176 * to remove an element rather than prefixing
177 * a new node with data of NULL like this. */
178 hash_table_insert (parser->defines, NULL, $2);
179 talloc_free (macro);
180 }
181 talloc_free ($2);
182 }
Carl Worth3ff81672010-05-25 13:09:03 -0700183| HASH NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700184;
185
Carl Worth3ff81672010-05-25 13:09:03 -0700186identifier_list:
Carl Worthb1854fd2010-05-25 16:28:26 -0700187 IDENTIFIER {
188 $$ = _string_list_create (parser);
189 _string_list_append_item ($$, $1);
190 talloc_steal ($$, $1);
191 }
192| identifier_list ',' IDENTIFIER {
193 $$ = $1;
194 _string_list_append_item ($$, $3);
195 talloc_steal ($$, $3);
196 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700197;
198
Carl Worth3ff81672010-05-25 13:09:03 -0700199text_line:
Carl Worth808401f2010-05-25 14:52:43 -0700200 NEWLINE { $$ = NULL; }
Carl Worth3ff81672010-05-25 13:09:03 -0700201| pp_tokens NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700202;
203
Carl Worth3ff81672010-05-25 13:09:03 -0700204non_directive:
205 pp_tokens NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700206;
207
Carl Worthaaa9acb2010-05-19 13:28:24 -0700208replacement_list:
Carl Worth808401f2010-05-25 14:52:43 -0700209 /* empty */ { $$ = NULL; }
Carl Worth3ff81672010-05-25 13:09:03 -0700210| pp_tokens
Carl Worthaaa9acb2010-05-19 13:28:24 -0700211;
212
Carl Worthaaa9acb2010-05-19 13:28:24 -0700213pp_tokens:
Carl Worth808401f2010-05-25 14:52:43 -0700214 preprocessing_token {
Carl Worthf34a0002010-05-25 16:59:02 -0700215 parser->space_tokens = 1;
Carl Worth808401f2010-05-25 14:52:43 -0700216 $$ = _token_list_create (parser);
217 _token_list_append ($$, $1);
218 talloc_unlink (parser, $1);
219 }
220| pp_tokens preprocessing_token {
221 $$ = $1;
222 _token_list_append ($$, $2);
223 talloc_unlink (parser, $2);
224 }
Carl Worthaaa9acb2010-05-19 13:28:24 -0700225;
226
Carl Worth3ff81672010-05-25 13:09:03 -0700227preprocessing_token:
Carl Worth808401f2010-05-25 14:52:43 -0700228 IDENTIFIER {
229 $$ = _token_create_str (parser, IDENTIFIER, $1);
230 }
231| punctuator {
232 $$ = _token_create_ival (parser, $1, $1);
233 }
234| OTHER {
235 $$ = _token_create_str (parser, OTHER, $1);
236 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700237| SPACE {
Carl Worthe9397862010-05-25 17:08:07 -0700238 $$ = _token_create_ival (parser, SPACE, SPACE);
Carl Worthb1854fd2010-05-25 16:28:26 -0700239 }
Carl Worth3ff81672010-05-25 13:09:03 -0700240;
241
242punctuator:
Carl Worth808401f2010-05-25 14:52:43 -0700243 '[' { $$ = '['; }
244| ']' { $$ = ']'; }
245| '(' { $$ = '('; }
246| ')' { $$ = ')'; }
247| '{' { $$ = '{'; }
248| '}' { $$ = '}'; }
249| '.' { $$ = '.'; }
250| '&' { $$ = '&'; }
251| '*' { $$ = '*'; }
252| '+' { $$ = '+'; }
253| '-' { $$ = '-'; }
254| '~' { $$ = '~'; }
255| '!' { $$ = '!'; }
256| '/' { $$ = '/'; }
257| '%' { $$ = '%'; }
258| LEFT_SHIFT { $$ = LEFT_SHIFT; }
259| RIGHT_SHIFT { $$ = RIGHT_SHIFT; }
260| '<' { $$ = '<'; }
261| '>' { $$ = '>'; }
262| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; }
263| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; }
264| EQUAL { $$ = EQUAL; }
265| NOT_EQUAL { $$ = NOT_EQUAL; }
266| '^' { $$ = '^'; }
267| '|' { $$ = '|'; }
268| AND { $$ = AND; }
269| OR { $$ = OR; }
270| ';' { $$ = ';'; }
271| ',' { $$ = ','; }
272| PASTE { $$ = PASTE; }
Carl Worth3ff81672010-05-25 13:09:03 -0700273;
274
Carl Worth33cc4002010-05-12 12:17:10 -0700275%%
276
Carl Worth610053b2010-05-14 10:05:11 -0700277string_list_t *
278_string_list_create (void *ctx)
Carl Worth33cc4002010-05-12 12:17:10 -0700279{
Carl Worth610053b2010-05-14 10:05:11 -0700280 string_list_t *list;
Carl Worth33cc4002010-05-12 12:17:10 -0700281
Carl Worth610053b2010-05-14 10:05:11 -0700282 list = xtalloc (ctx, string_list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700283 list->head = NULL;
284 list->tail = NULL;
285
286 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700287}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700288
Carl Worth33cc4002010-05-12 12:17:10 -0700289void
Carl Worth610053b2010-05-14 10:05:11 -0700290_string_list_append_list (string_list_t *list, string_list_t *tail)
Carl Worthfcbbb462010-05-13 09:36:23 -0700291{
292 if (list->head == NULL) {
293 list->head = tail->head;
294 } else {
295 list->tail->next = tail->head;
296 }
297
298 list->tail = tail->tail;
299}
300
301void
Carl Worth610053b2010-05-14 10:05:11 -0700302_string_list_append_item (string_list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700303{
Carl Worth610053b2010-05-14 10:05:11 -0700304 string_node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700305
Carl Worth610053b2010-05-14 10:05:11 -0700306 node = xtalloc (list, string_node_t);
Carl Worth5070a202010-05-12 12:45:33 -0700307 node->str = xtalloc_strdup (node, str);
Carl Worth80dc60b2010-05-25 14:42:00 -0700308
Carl Worth33cc4002010-05-12 12:17:10 -0700309 node->next = NULL;
310
311 if (list->head == NULL) {
312 list->head = node;
313 } else {
314 list->tail->next = node;
315 }
316
317 list->tail = node;
318}
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700319
Carl Worthae6517f2010-05-25 15:24:59 -0700320void
321_string_list_push (string_list_t *list, const char *str)
322{
323 string_node_t *node;
324
325 node = xtalloc (list, string_node_t);
326 node->str = xtalloc_strdup (node, str);
327 node->next = list->head;
328
329 if (list->tail == NULL) {
330 list->tail = node;
331 }
332 list->head = node;
333}
334
335void
336_string_list_pop (string_list_t *list)
337{
338 string_node_t *node;
339
340 node = list->head;
341
342 if (node == NULL) {
343 fprintf (stderr, "Internal error: _string_list_pop called on an empty list.\n");
344 exit (1);
345 }
346
347 list->head = node->next;
348 if (list->tail == node) {
349 assert (node->next == NULL);
350 list->tail = NULL;
351 }
352
353 talloc_free (node);
354}
355
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700356int
Carl Worth610053b2010-05-14 10:05:11 -0700357_string_list_contains (string_list_t *list, const char *member, int *index)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700358{
Carl Worth610053b2010-05-14 10:05:11 -0700359 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700360 int i;
361
362 if (list == NULL)
363 return 0;
364
365 for (i = 0, node = list->head; node; i++, node = node->next) {
366 if (strcmp (node->str, member) == 0) {
Carl Worth420d05a2010-05-17 10:15:23 -0700367 if (index)
368 *index = i;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700369 return 1;
370 }
371 }
372
373 return 0;
374}
375
376int
Carl Worth610053b2010-05-14 10:05:11 -0700377_string_list_length (string_list_t *list)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700378{
379 int length = 0;
Carl Worth610053b2010-05-14 10:05:11 -0700380 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700381
382 if (list == NULL)
383 return 0;
384
385 for (node = list->head; node; node = node->next)
386 length++;
387
388 return length;
389}
390
Carl Worth8f6a8282010-05-14 10:44:19 -0700391argument_list_t *
392_argument_list_create (void *ctx)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700393{
Carl Worth8f6a8282010-05-14 10:44:19 -0700394 argument_list_t *list;
395
396 list = xtalloc (ctx, argument_list_t);
397 list->head = NULL;
398 list->tail = NULL;
399
400 return list;
401}
402
403void
Carl Worth47252442010-05-19 13:54:37 -0700404_argument_list_append (argument_list_t *list, token_list_t *argument)
Carl Worth8f6a8282010-05-14 10:44:19 -0700405{
406 argument_node_t *node;
407
Carl Worth8f6a8282010-05-14 10:44:19 -0700408 node = xtalloc (list, argument_node_t);
409 node->argument = argument;
410
411 node->next = NULL;
412
413 if (list->head == NULL) {
414 list->head = node;
415 } else {
416 list->tail->next = node;
417 }
418
419 list->tail = node;
420}
421
422int
423_argument_list_length (argument_list_t *list)
424{
425 int length = 0;
426 argument_node_t *node;
427
428 if (list == NULL)
429 return 0;
430
431 for (node = list->head; node; node = node->next)
432 length++;
433
434 return length;
435}
436
Carl Worth47252442010-05-19 13:54:37 -0700437token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -0700438_argument_list_member_at (argument_list_t *list, int index)
439{
440 argument_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700441 int i;
442
443 if (list == NULL)
444 return NULL;
445
446 node = list->head;
447 for (i = 0; i < index; i++) {
448 node = node->next;
449 if (node == NULL)
450 break;
451 }
452
453 if (node)
Carl Worth8f6a8282010-05-14 10:44:19 -0700454 return node->argument;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700455
456 return NULL;
457}
Carl Worth47252442010-05-19 13:54:37 -0700458
Carl Worth808401f2010-05-25 14:52:43 -0700459/* Note: This function talloc_steal()s the str pointer. */
460token_t *
461_token_create_str (void *ctx, int type, char *str)
462{
463 token_t *token;
464
465 token = xtalloc (ctx, token_t);
466 token->type = type;
467 token->value.str = talloc_steal (token, str);
468
469 return token;
470}
471
472token_t *
473_token_create_ival (void *ctx, int type, int ival)
474{
475 token_t *token;
476
477 token = xtalloc (ctx, token_t);
478 token->type = type;
479 token->value.ival = ival;
480
481 return token;
482}
483
484void
485_token_print (token_t *token)
486{
487 if (token->type < 256) {
488 printf ("%c", token->type);
489 return;
490 }
491
492 switch (token->type) {
493 case IDENTIFIER:
494 case OTHER:
495 printf ("%s", token->value.str);
496 break;
Carl Worthe9397862010-05-25 17:08:07 -0700497 case SPACE:
498 printf (" ");
499 break;
Carl Worth808401f2010-05-25 14:52:43 -0700500 case LEFT_SHIFT:
501 printf ("<<");
502 break;
503 case RIGHT_SHIFT:
504 printf (">>");
505 break;
506 case LESS_OR_EQUAL:
507 printf ("<=");
508 break;
509 case GREATER_OR_EQUAL:
510 printf (">=");
511 break;
512 case EQUAL:
513 printf ("==");
514 break;
515 case NOT_EQUAL:
516 printf ("!=");
517 break;
518 case AND:
519 printf ("&&");
520 break;
521 case OR:
522 printf ("||");
523 break;
524 case PASTE:
525 printf ("##");
526 break;
527 default:
528 fprintf (stderr, "Error: Don't know how to print token type %d\n", token->type);
529 break;
530 }
531}
532
Carl Worth47252442010-05-19 13:54:37 -0700533token_list_t *
534_token_list_create (void *ctx)
535{
536 token_list_t *list;
537
538 list = xtalloc (ctx, token_list_t);
539 list->head = NULL;
540 list->tail = NULL;
541
542 return list;
543}
544
545void
Carl Worth808401f2010-05-25 14:52:43 -0700546_token_list_append (token_list_t *list, token_t *token)
Carl Worth47252442010-05-19 13:54:37 -0700547{
548 token_node_t *node;
549
550 node = xtalloc (list, token_node_t);
Carl Worth808401f2010-05-25 14:52:43 -0700551 node->token = xtalloc_reference (list, token);
Carl Worth47252442010-05-19 13:54:37 -0700552
553 node->next = NULL;
554
555 if (list->head == NULL) {
556 list->head = node;
557 } else {
558 list->tail->next = node;
559 }
560
561 list->tail = node;
562}
563
564void
565_token_list_append_list (token_list_t *list, token_list_t *tail)
566{
567 if (list->head == NULL) {
568 list->head = tail->head;
569 } else {
570 list->tail->next = tail->head;
571 }
572
573 list->tail = tail->tail;
574}
Carl Worth80dc60b2010-05-25 14:42:00 -0700575
Carl Worth3a37b872010-05-10 11:44:09 -0700576void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700577yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700578{
579 fprintf (stderr, "Parse error: %s\n", error);
580}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700581
Carl Worth33cc4002010-05-12 12:17:10 -0700582glcpp_parser_t *
583glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700584{
Carl Worth33cc4002010-05-12 12:17:10 -0700585 glcpp_parser_t *parser;
586
Carl Worth5070a202010-05-12 12:45:33 -0700587 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700588
Carl Worth8f38aff2010-05-19 10:01:29 -0700589 glcpp_lex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700590 parser->defines = hash_table_ctor (32, hash_table_string_hash,
591 hash_table_string_compare);
Carl Worthae6517f2010-05-25 15:24:59 -0700592 parser->active = _string_list_create (parser);
Carl Worthf34a0002010-05-25 16:59:02 -0700593 parser->space_tokens = 1;
Carl Wortha807fb72010-05-18 22:10:04 -0700594 parser->expansions = NULL;
595
Carl Worth5a6b9a22010-05-20 14:29:43 -0700596 parser->just_printed_separator = 1;
Carl Worth876e5102010-05-20 14:38:06 -0700597 parser->need_newline = 0;
Carl Worth5a6b9a22010-05-20 14:29:43 -0700598
Carl Worthb20d33c2010-05-20 22:27:07 -0700599 parser->skip_stack = NULL;
600
Carl Worth33cc4002010-05-12 12:17:10 -0700601 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700602}
603
604int
605glcpp_parser_parse (glcpp_parser_t *parser)
606{
607 return yyparse (parser);
608}
609
610void
Carl Worth33cc4002010-05-12 12:17:10 -0700611glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700612{
Carl Worth876e5102010-05-20 14:38:06 -0700613 if (parser->need_newline)
614 printf ("\n");
Carl Worthb20d33c2010-05-20 22:27:07 -0700615 if (parser->skip_stack)
616 fprintf (stderr, "Error: Unterminated #if\n");
Carl Worth8f38aff2010-05-19 10:01:29 -0700617 glcpp_lex_destroy (parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700618 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700619 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700620}
Carl Worthc6d5af32010-05-11 12:30:09 -0700621
Carl Worthbe0e2e92010-05-19 07:29:22 -0700622static int
623glcpp_parser_is_expanding (glcpp_parser_t *parser, const char *member)
624{
625 expansion_node_t *node;
626
627 for (node = parser->expansions; node; node = node->next) {
628 if (node->macro &&
629 strcmp (node->macro->identifier, member) == 0)
630 {
631 return 1;
632 }
633 }
634
635 return 0;
636}
637
Carl Wortha807fb72010-05-18 22:10:04 -0700638token_class_t
639glcpp_parser_classify_token (glcpp_parser_t *parser,
640 const char *identifier,
641 int *parameter_index)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700642{
Carl Worthfcbbb462010-05-13 09:36:23 -0700643 macro_t *macro;
644
Carl Worthc10a51b2010-05-20 15:15:26 -0700645 /* Is this token a defined macro? */
Carl Worthfcbbb462010-05-13 09:36:23 -0700646 macro = hash_table_find (parser->defines, identifier);
647
648 if (macro == NULL)
Carl Wortha807fb72010-05-18 22:10:04 -0700649 return TOKEN_CLASS_IDENTIFIER;
Carl Worthfcbbb462010-05-13 09:36:23 -0700650
Carl Worthbe0e2e92010-05-19 07:29:22 -0700651 /* Don't consider this a macro if we are already actively
652 * expanding this macro. */
653 if (glcpp_parser_is_expanding (parser, identifier))
Carl Worthb5693832010-05-20 08:01:44 -0700654 return TOKEN_CLASS_IDENTIFIER_FINALIZED;
Carl Worthbe0e2e92010-05-19 07:29:22 -0700655
656 /* Definitely a macro. Just need to check if it's function-like. */
Carl Worthfcbbb462010-05-13 09:36:23 -0700657 if (macro->is_function)
Carl Wortha807fb72010-05-18 22:10:04 -0700658 return TOKEN_CLASS_FUNC_MACRO;
Carl Worthfcbbb462010-05-13 09:36:23 -0700659 else
Carl Wortha807fb72010-05-18 22:10:04 -0700660 return TOKEN_CLASS_OBJ_MACRO;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700661}
662
Carl Worthb1854fd2010-05-25 16:28:26 -0700663/* Print a non-macro token, or the expansion of an object-like macro.
664 *
665 * Returns 0 if this token is completely printed.
666 *
667 * Returns 1 in the case that 'token' is a function-like macro that
668 * needs further expansion.
669 */
670static int
Carl Worthae6517f2010-05-25 15:24:59 -0700671_glcpp_parser_print_expanded_token (glcpp_parser_t *parser,
672 token_t *token)
673{
674 const char *identifier;
675 macro_t *macro;
676
677 /* We only expand identifiers */
678 if (token->type != IDENTIFIER) {
679 _token_print (token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700680 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700681 }
682
683 /* Look up this identifier in the hash table. */
684 identifier = token->value.str;
685 macro = hash_table_find (parser->defines, identifier);
686
687 /* Not a macro, so just print directly. */
688 if (macro == NULL) {
689 printf ("%s", identifier);
Carl Worthb1854fd2010-05-25 16:28:26 -0700690 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700691 }
692
Carl Worthb1854fd2010-05-25 16:28:26 -0700693 /* For function-like macros return 1 for further processing. */
Carl Worthae6517f2010-05-25 15:24:59 -0700694 if (macro->is_function) {
Carl Worthb1854fd2010-05-25 16:28:26 -0700695 return 1;
Carl Worthae6517f2010-05-25 15:24:59 -0700696 }
697
698 /* Finally, don't expand this macro if we're already actively
699 * expanding it, (to avoid infinite recursion). */
700 if (_string_list_contains (parser->active, identifier, NULL)) {
701 printf ("%s", identifier);
Carl Worthb1854fd2010-05-25 16:28:26 -0700702 return 0;
703 }
704
705 _string_list_push (parser->active, identifier);
706 _glcpp_parser_print_expanded_token_list (parser,
707 macro->replacements);
708 _string_list_pop (parser->active);
709
710 return 0;
711}
712
713typedef enum function_status
714{
715 FUNCTION_STATUS_SUCCESS,
716 FUNCTION_NOT_A_FUNCTION,
717 FUNCTION_UNBALANCED_PARENTHESES
718} function_status_t;
719
720/* Find a set of function-like macro arguments by looking for a
721 * balanced set of parentheses. Upon return *node will be the last
722 * consumed node, such that further processing can continue with
723 * node->next.
724 *
725 * Return values:
726 *
727 * FUNCTION_STATUS_SUCCESS:
728 *
729 * Successfully parsed a set of function arguments.
730 *
731 * FUNCTION_NOT_A_FUNCTION:
732 *
733 * Macro name not followed by a '('. This is not an error, but
734 * simply that the macro name should be treated as a non-macro.
735 *
736 * FUNCTION_UNBLANCED_PARENTHESES
737 *
738 * Macro name is not followed by a balanced set of parentheses.
739 */
740static function_status_t
Carl Worth9ce18cf2010-05-25 17:32:21 -0700741_arguments_parse (argument_list_t *arguments, token_node_t **node_ret)
Carl Worthb1854fd2010-05-25 16:28:26 -0700742{
Carl Worth9ce18cf2010-05-25 17:32:21 -0700743 token_list_t *argument;
Carl Worthb1854fd2010-05-25 16:28:26 -0700744 token_node_t *node = *node_ret, *last;
745 int paren_count;
Carl Worthb1854fd2010-05-25 16:28:26 -0700746
747 last = node;
748 node = node->next;
749
750 /* Ignore whitespace before first parenthesis. */
751 while (node && node->token->type == SPACE)
752 node = node->next;
753
754 if (node == NULL || node->token->type != '(')
755 return FUNCTION_NOT_A_FUNCTION;
756
Carl Worth652fa272010-05-25 17:45:22 -0700757 last = node;
758 node = node->next;
759
Carl Worth9ce18cf2010-05-25 17:32:21 -0700760 argument = NULL;
761
Carl Worth652fa272010-05-25 17:45:22 -0700762 for (paren_count = 1; node; last = node, node = node->next) {
Carl Worthb1854fd2010-05-25 16:28:26 -0700763 if (node->token->type == '(')
764 {
765 paren_count++;
766 }
767 else if (node->token->type == ')')
768 {
769 paren_count--;
Carl Worthc7581c22010-05-25 17:41:07 -0700770 if (paren_count == 0) {
771 last = node;
772 node = node->next;
773 break;
774 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700775 }
Carl Worth652fa272010-05-25 17:45:22 -0700776
777 if (node->token->type == ',' &&
Carl Worthb1854fd2010-05-25 16:28:26 -0700778 paren_count == 1)
779 {
Carl Worth9ce18cf2010-05-25 17:32:21 -0700780 argument = NULL;
781 }
782 else {
783 if (argument == NULL) {
Carl Worthc7581c22010-05-25 17:41:07 -0700784 /* Don't treat initial whitespace as
785 * part of the arguement. */
786 if (node->token->type == SPACE)
787 continue;
Carl Worth9ce18cf2010-05-25 17:32:21 -0700788 argument = _token_list_create (arguments);
789 _argument_list_append (arguments, argument);
790 }
791 _token_list_append (argument, node->token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700792 }
Carl Worthc7581c22010-05-25 17:41:07 -0700793 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700794
795 if (node && paren_count)
796 return FUNCTION_UNBALANCED_PARENTHESES;
797
798 *node_ret = last;
799
800 return FUNCTION_STATUS_SUCCESS;
801}
802
803/* Prints the expansion of *node (consuming further tokens from the
804 * list as necessary). Upon return *node will be the last consumed
805 * node, such that further processing can continue with node->next. */
806static void
807_glcpp_parser_print_expanded_function (glcpp_parser_t *parser,
808 token_node_t **node_ret)
809{
810 macro_t *macro;
811 token_node_t *node;
812 const char *identifier;
813 argument_list_t *arguments;
814 function_status_t status;
Carl Worth9ce18cf2010-05-25 17:32:21 -0700815 token_list_t *expanded;
816 token_node_t *i, *j;
817 int parameter_index;
Carl Worthb1854fd2010-05-25 16:28:26 -0700818
819 node = *node_ret;
820 identifier = node->token->value.str;
821
822 macro = hash_table_find (parser->defines, identifier);
823
824 assert (macro->is_function);
825
Carl Worth9ce18cf2010-05-25 17:32:21 -0700826 arguments = _argument_list_create (parser);
827 status = _arguments_parse (arguments, node_ret);
Carl Worthb1854fd2010-05-25 16:28:26 -0700828
829 switch (status) {
830 case FUNCTION_STATUS_SUCCESS:
831 break;
832 case FUNCTION_NOT_A_FUNCTION:
833 printf ("%s", identifier);
Carl Worthae6517f2010-05-25 15:24:59 -0700834 return;
Carl Worthb1854fd2010-05-25 16:28:26 -0700835 case FUNCTION_UNBALANCED_PARENTHESES:
836 fprintf (stderr, "Error: Macro %s call has unbalanced parentheses\n",
837 identifier);
838 exit (1);
Carl Worthae6517f2010-05-25 15:24:59 -0700839 }
840
Carl Worth9ce18cf2010-05-25 17:32:21 -0700841 if (macro->replacements == NULL) {
842 talloc_free (arguments);
843 return;
844 }
845
846
847 if (_argument_list_length (arguments) !=
848 _string_list_length (macro->parameters))
849 {
850 fprintf (stderr,
851 "Error: macro %s invoked with %d arguments (expected %d)\n",
852 identifier,
853 _argument_list_length (arguments),
854 _string_list_length (macro->parameters));
855 return;
856 }
857
858 expanded = _token_list_create (arguments);
859
860 for (i = macro->replacements->head; i; i = i->next) {
861 if (i->token->type == IDENTIFIER &&
862 _string_list_contains (macro->parameters,
863 i->token->value.str,
864 &parameter_index))
865 {
866 token_list_t *argument;
867 argument = _argument_list_member_at (arguments,
868 parameter_index);
869 for (j = argument->head; j; j = j->next)
870 {
871 _token_list_append (expanded, j->token);
872 }
873 } else {
874 _token_list_append (expanded, i->token);
875 }
876 }
877
Carl Worthae6517f2010-05-25 15:24:59 -0700878 _string_list_push (parser->active, identifier);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700879 _glcpp_parser_print_expanded_token_list (parser, expanded);
Carl Worthae6517f2010-05-25 15:24:59 -0700880 _string_list_pop (parser->active);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700881
882 talloc_free (arguments);
Carl Worthae6517f2010-05-25 15:24:59 -0700883}
884
885void
886_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
887 token_list_t *list)
888{
889 token_node_t *node;
Carl Worthb1854fd2010-05-25 16:28:26 -0700890 function_status_t function_status;
Carl Worthae6517f2010-05-25 15:24:59 -0700891
892 if (list == NULL)
893 return;
894
895 for (node = list->head; node; node = node->next) {
Carl Worthb1854fd2010-05-25 16:28:26 -0700896 if (_glcpp_parser_print_expanded_token (parser, node->token))
897 _glcpp_parser_print_expanded_function (parser, &node);
Carl Worthae6517f2010-05-25 15:24:59 -0700898 }
899}
900
901void
Carl Worthfcbbb462010-05-13 09:36:23 -0700902_define_object_macro (glcpp_parser_t *parser,
903 const char *identifier,
Carl Worth47252442010-05-19 13:54:37 -0700904 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700905{
906 macro_t *macro;
907
908 macro = xtalloc (parser, macro_t);
909
910 macro->is_function = 0;
Carl Worthc5e98552010-05-14 10:12:21 -0700911 macro->parameters = NULL;
Carl Wortha807fb72010-05-18 22:10:04 -0700912 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700913 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700914
915 hash_table_insert (parser->defines, macro, identifier);
916}
917
918void
919_define_function_macro (glcpp_parser_t *parser,
920 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -0700921 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -0700922 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700923{
924 macro_t *macro;
925
926 macro = xtalloc (parser, macro_t);
927
928 macro->is_function = 1;
Carl Worthc5e98552010-05-14 10:12:21 -0700929 macro->parameters = talloc_steal (macro, parameters);
Carl Wortha807fb72010-05-18 22:10:04 -0700930 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700931 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700932
933 hash_table_insert (parser->defines, macro, identifier);
934}
935
Carl Wortha807fb72010-05-18 22:10:04 -0700936static void
Carl Worthc10a51b2010-05-20 15:15:26 -0700937_glcpp_parser_push_expansion (glcpp_parser_t *parser,
938 macro_t *macro,
939 token_node_t *replacements)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700940{
Carl Wortha807fb72010-05-18 22:10:04 -0700941 expansion_node_t *node;
942
943 node = xtalloc (parser, expansion_node_t);
944
945 node->macro = macro;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700946 node->replacements = replacements;
Carl Wortha807fb72010-05-18 22:10:04 -0700947
948 node->next = parser->expansions;
949 parser->expansions = node;
Carl Wortha807fb72010-05-18 22:10:04 -0700950}
951
Carl Worthaaa9acb2010-05-19 13:28:24 -0700952static void
Carl Wortha807fb72010-05-18 22:10:04 -0700953glcpp_parser_pop_expansion (glcpp_parser_t *parser)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700954{
Carl Wortha807fb72010-05-18 22:10:04 -0700955 expansion_node_t *node;
Carl Worth420d05a2010-05-17 10:15:23 -0700956
Carl Wortha807fb72010-05-18 22:10:04 -0700957 node = parser->expansions;
Carl Worth420d05a2010-05-17 10:15:23 -0700958
Carl Wortha807fb72010-05-18 22:10:04 -0700959 if (node == NULL) {
960 fprintf (stderr, "Internal error: _expansion_list_pop called on an empty list.\n");
961 exit (1);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700962 }
963
Carl Wortha807fb72010-05-18 22:10:04 -0700964 parser->expansions = node->next;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700965
Carl Wortha807fb72010-05-18 22:10:04 -0700966 talloc_free (node);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700967}
968
Carl Wortha807fb72010-05-18 22:10:04 -0700969void
Carl Worth2be8be02010-05-14 10:31:43 -0700970_expand_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700971{
Carl Worthfcbbb462010-05-13 09:36:23 -0700972 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700973
Carl Worthfcbbb462010-05-13 09:36:23 -0700974 macro = hash_table_find (parser->defines, identifier);
975 assert (! macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700976 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700977
Carl Worthc10a51b2010-05-20 15:15:26 -0700978 _glcpp_parser_push_expansion (parser, macro, macro->replacements->head);
Carl Worthfcbbb462010-05-13 09:36:23 -0700979}
980
Carl Wortha807fb72010-05-18 22:10:04 -0700981void
Carl Worth2be8be02010-05-14 10:31:43 -0700982_expand_function_macro (glcpp_parser_t *parser,
983 const char *identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700984 argument_list_t *arguments)
Carl Worthfcbbb462010-05-13 09:36:23 -0700985{
Carl Worthfcbbb462010-05-13 09:36:23 -0700986 macro_t *macro;
Carl Worthc10a51b2010-05-20 15:15:26 -0700987 token_list_t *expanded;
988 token_node_t *i, *j;
989 int parameter_index;
Carl Worthfcbbb462010-05-13 09:36:23 -0700990
991 macro = hash_table_find (parser->defines, identifier);
992 assert (macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700993 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700994
Carl Worth8f6a8282010-05-14 10:44:19 -0700995 if (_argument_list_length (arguments) !=
Carl Worth2be8be02010-05-14 10:31:43 -0700996 _string_list_length (macro->parameters))
997 {
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700998 fprintf (stderr,
999 "Error: macro %s invoked with %d arguments (expected %d)\n",
1000 identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -07001001 _argument_list_length (arguments),
Carl Worthc5e98552010-05-14 10:12:21 -07001002 _string_list_length (macro->parameters));
Carl Wortha807fb72010-05-18 22:10:04 -07001003 return;
Carl Worthdcc2ecd2010-05-13 12:56:42 -07001004 }
Carl Worthfcbbb462010-05-13 09:36:23 -07001005
Carl Worthc10a51b2010-05-20 15:15:26 -07001006 expanded = _token_list_create (macro);
1007
1008 for (i = macro->replacements->head; i; i = i->next) {
Carl Worth808401f2010-05-25 14:52:43 -07001009 if (_string_list_contains (macro->parameters,
1010 i->token->value.str,
Carl Worthc10a51b2010-05-20 15:15:26 -07001011 &parameter_index))
1012 {
1013 token_list_t *argument;
1014 argument = _argument_list_member_at (arguments,
1015 parameter_index);
1016 for (j = argument->head; j; j = j->next)
1017 {
Carl Worth808401f2010-05-25 14:52:43 -07001018 _token_list_append (expanded, j->token);
Carl Worthc10a51b2010-05-20 15:15:26 -07001019 }
1020 } else {
Carl Worth808401f2010-05-25 14:52:43 -07001021 _token_list_append (expanded, i->token);
Carl Worthc10a51b2010-05-20 15:15:26 -07001022 }
1023 }
1024
1025 _glcpp_parser_push_expansion (parser, macro, expanded->head);
Carl Worth33cc4002010-05-12 12:17:10 -07001026}
Carl Worth8f38aff2010-05-19 10:01:29 -07001027
1028static int
Carl Worth0293b2e2010-05-19 10:05:40 -07001029glcpp_parser_lex (glcpp_parser_t *parser)
Carl Worth8f38aff2010-05-19 10:01:29 -07001030{
Carl Worthaaa9acb2010-05-19 13:28:24 -07001031 expansion_node_t *expansion;
Carl Worth47252442010-05-19 13:54:37 -07001032 token_node_t *replacements;
Carl Worthaaa9acb2010-05-19 13:28:24 -07001033 int parameter_index;
Carl Worthd8327e52010-05-20 15:18:54 -07001034 const char *token;
1035 token_class_t class;
Carl Worthaaa9acb2010-05-19 13:28:24 -07001036
1037 /* Who says C can't do efficient tail recursion? */
1038 RECURSE:
1039
1040 expansion = parser->expansions;
1041
1042 if (expansion == NULL)
1043 return glcpp_lex (parser->scanner);
1044
1045 replacements = expansion->replacements;
1046
1047 /* Pop expansion when replacements is exhausted. */
1048 if (replacements == NULL) {
1049 glcpp_parser_pop_expansion (parser);
1050 goto RECURSE;
1051 }
1052
1053 expansion->replacements = replacements->next;
1054
Carl Worth808401f2010-05-25 14:52:43 -07001055 token = replacements->token->value.str;
Carl Worthd8327e52010-05-20 15:18:54 -07001056
1057 /* Implement token pasting. */
Carl Worth808401f2010-05-25 14:52:43 -07001058 if (replacements->next && strcmp (replacements->next->token->value.str, "##") == 0) {
Carl Worthd8327e52010-05-20 15:18:54 -07001059 token_node_t *next_node;
1060
1061 next_node = replacements->next->next;
1062
1063 if (next_node == NULL) {
1064 fprintf (stderr, "Error: '##' cannot appear at the end of a macro expansion.\n");
1065 exit (1);
1066 }
1067
1068 token = xtalloc_asprintf (parser, "%s%s",
Carl Worth808401f2010-05-25 14:52:43 -07001069 token, next_node->token->value.str);
Carl Worthd8327e52010-05-20 15:18:54 -07001070 expansion->replacements = next_node->next;
1071 }
1072
1073
1074 if (strcmp (token, "(") == 0)
Carl Worthaaa9acb2010-05-19 13:28:24 -07001075 return '(';
Carl Worthd8327e52010-05-20 15:18:54 -07001076 else if (strcmp (token, ")") == 0)
Carl Worthaaa9acb2010-05-19 13:28:24 -07001077 return ')';
Carl Worthaaa9acb2010-05-19 13:28:24 -07001078
Carl Worthd8327e52010-05-20 15:18:54 -07001079 yylval.str = xtalloc_strdup (parser, token);
Carl Worthaaa9acb2010-05-19 13:28:24 -07001080
Carl Worthb5693832010-05-20 08:01:44 -07001081 /* Carefully refuse to expand any finalized identifier. */
Carl Worth808401f2010-05-25 14:52:43 -07001082 if (replacements->token->type == IDENTIFIER_FINALIZED)
Carl Worthb5693832010-05-20 08:01:44 -07001083 return IDENTIFIER_FINALIZED;
1084
Carl Worthaaa9acb2010-05-19 13:28:24 -07001085 switch (glcpp_parser_classify_token (parser, yylval.str,
1086 &parameter_index))
1087 {
Carl Worthaaa9acb2010-05-19 13:28:24 -07001088 case TOKEN_CLASS_IDENTIFIER:
1089 return IDENTIFIER;
1090 break;
Carl Worthb5693832010-05-20 08:01:44 -07001091 case TOKEN_CLASS_IDENTIFIER_FINALIZED:
1092 return IDENTIFIER_FINALIZED;
1093 break;
Carl Worthaaa9acb2010-05-19 13:28:24 -07001094 case TOKEN_CLASS_FUNC_MACRO:
1095 return FUNC_MACRO;
1096 break;
1097 default:
1098 case TOKEN_CLASS_OBJ_MACRO:
1099 return OBJ_MACRO;
1100 break;
1101 }
Carl Worth8f38aff2010-05-19 10:01:29 -07001102}
Carl Worthb20d33c2010-05-20 22:27:07 -07001103
1104static void
1105_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition)
1106{
1107 skip_type_t current = SKIP_NO_SKIP;
1108 skip_node_t *node;
1109
1110 if (parser->skip_stack)
1111 current = parser->skip_stack->type;
1112
1113 node = xtalloc (parser, skip_node_t);
1114
1115 if (current == SKIP_NO_SKIP) {
1116 if (condition)
1117 node->type = SKIP_NO_SKIP;
1118 else
1119 node->type = SKIP_TO_ELSE;
1120 } else {
1121 node->type = SKIP_TO_ENDIF;
1122 }
1123
1124 node->next = parser->skip_stack;
1125 parser->skip_stack = node;
1126}
1127
1128static void
1129_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
1130 int condition)
1131{
1132 if (parser->skip_stack == NULL) {
1133 fprintf (stderr, "Error: %s without #if\n", type);
1134 exit (1);
1135 }
1136
1137 if (parser->skip_stack->type == SKIP_TO_ELSE) {
1138 if (condition)
1139 parser->skip_stack->type = SKIP_NO_SKIP;
1140 } else {
1141 parser->skip_stack->type = SKIP_TO_ENDIF;
1142 }
1143}
Carl Worth80dc60b2010-05-25 14:42:00 -07001144
Carl Worthb20d33c2010-05-20 22:27:07 -07001145static void
1146_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser)
1147{
1148 skip_node_t *node;
1149
1150 if (parser->skip_stack == NULL) {
1151 fprintf (stderr, "Error: #endif without #if\n");
1152 exit (1);
1153 }
1154
1155 node = parser->skip_stack;
1156 parser->skip_stack = node->next;
1157 talloc_free (node);
1158}