blob: 0460f71f74688a314084fd632709bd3893de7d7d [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
408 if (argument == NULL || argument->head == NULL)
409 return;
410
411 node = xtalloc (list, argument_node_t);
412 node->argument = argument;
413
414 node->next = NULL;
415
416 if (list->head == NULL) {
417 list->head = node;
418 } else {
419 list->tail->next = node;
420 }
421
422 list->tail = node;
423}
424
425int
426_argument_list_length (argument_list_t *list)
427{
428 int length = 0;
429 argument_node_t *node;
430
431 if (list == NULL)
432 return 0;
433
434 for (node = list->head; node; node = node->next)
435 length++;
436
437 return length;
438}
439
Carl Worth47252442010-05-19 13:54:37 -0700440token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -0700441_argument_list_member_at (argument_list_t *list, int index)
442{
443 argument_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700444 int i;
445
446 if (list == NULL)
447 return NULL;
448
449 node = list->head;
450 for (i = 0; i < index; i++) {
451 node = node->next;
452 if (node == NULL)
453 break;
454 }
455
456 if (node)
Carl Worth8f6a8282010-05-14 10:44:19 -0700457 return node->argument;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700458
459 return NULL;
460}
Carl Worth47252442010-05-19 13:54:37 -0700461
Carl Worth808401f2010-05-25 14:52:43 -0700462/* Note: This function talloc_steal()s the str pointer. */
463token_t *
464_token_create_str (void *ctx, int type, char *str)
465{
466 token_t *token;
467
468 token = xtalloc (ctx, token_t);
469 token->type = type;
470 token->value.str = talloc_steal (token, str);
471
472 return token;
473}
474
475token_t *
476_token_create_ival (void *ctx, int type, int ival)
477{
478 token_t *token;
479
480 token = xtalloc (ctx, token_t);
481 token->type = type;
482 token->value.ival = ival;
483
484 return token;
485}
486
487void
488_token_print (token_t *token)
489{
490 if (token->type < 256) {
491 printf ("%c", token->type);
492 return;
493 }
494
495 switch (token->type) {
496 case IDENTIFIER:
497 case OTHER:
498 printf ("%s", token->value.str);
499 break;
Carl Worthe9397862010-05-25 17:08:07 -0700500 case SPACE:
501 printf (" ");
502 break;
Carl Worth808401f2010-05-25 14:52:43 -0700503 case LEFT_SHIFT:
504 printf ("<<");
505 break;
506 case RIGHT_SHIFT:
507 printf (">>");
508 break;
509 case LESS_OR_EQUAL:
510 printf ("<=");
511 break;
512 case GREATER_OR_EQUAL:
513 printf (">=");
514 break;
515 case EQUAL:
516 printf ("==");
517 break;
518 case NOT_EQUAL:
519 printf ("!=");
520 break;
521 case AND:
522 printf ("&&");
523 break;
524 case OR:
525 printf ("||");
526 break;
527 case PASTE:
528 printf ("##");
529 break;
530 default:
531 fprintf (stderr, "Error: Don't know how to print token type %d\n", token->type);
532 break;
533 }
534}
535
Carl Worth47252442010-05-19 13:54:37 -0700536token_list_t *
537_token_list_create (void *ctx)
538{
539 token_list_t *list;
540
541 list = xtalloc (ctx, token_list_t);
542 list->head = NULL;
543 list->tail = NULL;
544
545 return list;
546}
547
548void
Carl Worth808401f2010-05-25 14:52:43 -0700549_token_list_append (token_list_t *list, token_t *token)
Carl Worth47252442010-05-19 13:54:37 -0700550{
551 token_node_t *node;
552
553 node = xtalloc (list, token_node_t);
Carl Worth808401f2010-05-25 14:52:43 -0700554 node->token = xtalloc_reference (list, token);
Carl Worth47252442010-05-19 13:54:37 -0700555
556 node->next = NULL;
557
558 if (list->head == NULL) {
559 list->head = node;
560 } else {
561 list->tail->next = node;
562 }
563
564 list->tail = node;
565}
566
567void
568_token_list_append_list (token_list_t *list, token_list_t *tail)
569{
570 if (list->head == NULL) {
571 list->head = tail->head;
572 } else {
573 list->tail->next = tail->head;
574 }
575
576 list->tail = tail->tail;
577}
Carl Worth80dc60b2010-05-25 14:42:00 -0700578
Carl Worth3a37b872010-05-10 11:44:09 -0700579void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700580yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700581{
582 fprintf (stderr, "Parse error: %s\n", error);
583}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700584
Carl Worth33cc4002010-05-12 12:17:10 -0700585glcpp_parser_t *
586glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700587{
Carl Worth33cc4002010-05-12 12:17:10 -0700588 glcpp_parser_t *parser;
589
Carl Worth5070a202010-05-12 12:45:33 -0700590 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700591
Carl Worth8f38aff2010-05-19 10:01:29 -0700592 glcpp_lex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700593 parser->defines = hash_table_ctor (32, hash_table_string_hash,
594 hash_table_string_compare);
Carl Worthae6517f2010-05-25 15:24:59 -0700595 parser->active = _string_list_create (parser);
Carl Worthf34a0002010-05-25 16:59:02 -0700596 parser->space_tokens = 1;
Carl Wortha807fb72010-05-18 22:10:04 -0700597 parser->expansions = NULL;
598
Carl Worth5a6b9a22010-05-20 14:29:43 -0700599 parser->just_printed_separator = 1;
Carl Worth876e5102010-05-20 14:38:06 -0700600 parser->need_newline = 0;
Carl Worth5a6b9a22010-05-20 14:29:43 -0700601
Carl Worthb20d33c2010-05-20 22:27:07 -0700602 parser->skip_stack = NULL;
603
Carl Worth33cc4002010-05-12 12:17:10 -0700604 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700605}
606
607int
608glcpp_parser_parse (glcpp_parser_t *parser)
609{
610 return yyparse (parser);
611}
612
613void
Carl Worth33cc4002010-05-12 12:17:10 -0700614glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700615{
Carl Worth876e5102010-05-20 14:38:06 -0700616 if (parser->need_newline)
617 printf ("\n");
Carl Worthb20d33c2010-05-20 22:27:07 -0700618 if (parser->skip_stack)
619 fprintf (stderr, "Error: Unterminated #if\n");
Carl Worth8f38aff2010-05-19 10:01:29 -0700620 glcpp_lex_destroy (parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700621 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700622 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700623}
Carl Worthc6d5af32010-05-11 12:30:09 -0700624
Carl Worthbe0e2e92010-05-19 07:29:22 -0700625static int
626glcpp_parser_is_expanding (glcpp_parser_t *parser, const char *member)
627{
628 expansion_node_t *node;
629
630 for (node = parser->expansions; node; node = node->next) {
631 if (node->macro &&
632 strcmp (node->macro->identifier, member) == 0)
633 {
634 return 1;
635 }
636 }
637
638 return 0;
639}
640
Carl Wortha807fb72010-05-18 22:10:04 -0700641token_class_t
642glcpp_parser_classify_token (glcpp_parser_t *parser,
643 const char *identifier,
644 int *parameter_index)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700645{
Carl Worthfcbbb462010-05-13 09:36:23 -0700646 macro_t *macro;
647
Carl Worthc10a51b2010-05-20 15:15:26 -0700648 /* Is this token a defined macro? */
Carl Worthfcbbb462010-05-13 09:36:23 -0700649 macro = hash_table_find (parser->defines, identifier);
650
651 if (macro == NULL)
Carl Wortha807fb72010-05-18 22:10:04 -0700652 return TOKEN_CLASS_IDENTIFIER;
Carl Worthfcbbb462010-05-13 09:36:23 -0700653
Carl Worthbe0e2e92010-05-19 07:29:22 -0700654 /* Don't consider this a macro if we are already actively
655 * expanding this macro. */
656 if (glcpp_parser_is_expanding (parser, identifier))
Carl Worthb5693832010-05-20 08:01:44 -0700657 return TOKEN_CLASS_IDENTIFIER_FINALIZED;
Carl Worthbe0e2e92010-05-19 07:29:22 -0700658
659 /* Definitely a macro. Just need to check if it's function-like. */
Carl Worthfcbbb462010-05-13 09:36:23 -0700660 if (macro->is_function)
Carl Wortha807fb72010-05-18 22:10:04 -0700661 return TOKEN_CLASS_FUNC_MACRO;
Carl Worthfcbbb462010-05-13 09:36:23 -0700662 else
Carl Wortha807fb72010-05-18 22:10:04 -0700663 return TOKEN_CLASS_OBJ_MACRO;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700664}
665
Carl Worthb1854fd2010-05-25 16:28:26 -0700666/* Print a non-macro token, or the expansion of an object-like macro.
667 *
668 * Returns 0 if this token is completely printed.
669 *
670 * Returns 1 in the case that 'token' is a function-like macro that
671 * needs further expansion.
672 */
673static int
Carl Worthae6517f2010-05-25 15:24:59 -0700674_glcpp_parser_print_expanded_token (glcpp_parser_t *parser,
675 token_t *token)
676{
677 const char *identifier;
678 macro_t *macro;
679
680 /* We only expand identifiers */
681 if (token->type != IDENTIFIER) {
682 _token_print (token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700683 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700684 }
685
686 /* Look up this identifier in the hash table. */
687 identifier = token->value.str;
688 macro = hash_table_find (parser->defines, identifier);
689
690 /* Not a macro, so just print directly. */
691 if (macro == NULL) {
692 printf ("%s", identifier);
Carl Worthb1854fd2010-05-25 16:28:26 -0700693 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700694 }
695
Carl Worthb1854fd2010-05-25 16:28:26 -0700696 /* For function-like macros return 1 for further processing. */
Carl Worthae6517f2010-05-25 15:24:59 -0700697 if (macro->is_function) {
Carl Worthb1854fd2010-05-25 16:28:26 -0700698 return 1;
Carl Worthae6517f2010-05-25 15:24:59 -0700699 }
700
701 /* Finally, don't expand this macro if we're already actively
702 * expanding it, (to avoid infinite recursion). */
703 if (_string_list_contains (parser->active, identifier, NULL)) {
704 printf ("%s", identifier);
Carl Worthb1854fd2010-05-25 16:28:26 -0700705 return 0;
706 }
707
708 _string_list_push (parser->active, identifier);
709 _glcpp_parser_print_expanded_token_list (parser,
710 macro->replacements);
711 _string_list_pop (parser->active);
712
713 return 0;
714}
715
716typedef enum function_status
717{
718 FUNCTION_STATUS_SUCCESS,
719 FUNCTION_NOT_A_FUNCTION,
720 FUNCTION_UNBALANCED_PARENTHESES
721} function_status_t;
722
723/* Find a set of function-like macro arguments by looking for a
724 * balanced set of parentheses. Upon return *node will be the last
725 * consumed node, such that further processing can continue with
726 * node->next.
727 *
728 * Return values:
729 *
730 * FUNCTION_STATUS_SUCCESS:
731 *
732 * Successfully parsed a set of function arguments.
733 *
734 * FUNCTION_NOT_A_FUNCTION:
735 *
736 * Macro name not followed by a '('. This is not an error, but
737 * simply that the macro name should be treated as a non-macro.
738 *
739 * FUNCTION_UNBLANCED_PARENTHESES
740 *
741 * Macro name is not followed by a balanced set of parentheses.
742 */
743static function_status_t
744_find_arguments (token_node_t **node_ret, argument_list_t **arguments)
745{
746 token_node_t *node = *node_ret, *last;
747 int paren_count;
748 int arg_count;
749
750 last = node;
751 node = node->next;
752
753 /* Ignore whitespace before first parenthesis. */
754 while (node && node->token->type == SPACE)
755 node = node->next;
756
757 if (node == NULL || node->token->type != '(')
758 return FUNCTION_NOT_A_FUNCTION;
759
760 paren_count = 0;
761 arg_count = 0;
762 do {
763 if (node->token->type == '(')
764 {
765 paren_count++;
766 }
767 else if (node->token->type == ')')
768 {
769 paren_count--;
770 }
771 else if (node->token->type == ',' &&
772 paren_count == 1)
773 {
774 arg_count++;
775 }
776
777 last = node;
778 node = node->next;
779
780 } while (node && paren_count);
781
782 if (node && paren_count)
783 return FUNCTION_UNBALANCED_PARENTHESES;
784
785 *node_ret = last;
786
787 return FUNCTION_STATUS_SUCCESS;
788}
789
790/* Prints the expansion of *node (consuming further tokens from the
791 * list as necessary). Upon return *node will be the last consumed
792 * node, such that further processing can continue with node->next. */
793static void
794_glcpp_parser_print_expanded_function (glcpp_parser_t *parser,
795 token_node_t **node_ret)
796{
797 macro_t *macro;
798 token_node_t *node;
799 const char *identifier;
800 argument_list_t *arguments;
801 function_status_t status;
802
803 node = *node_ret;
804 identifier = node->token->value.str;
805
806 macro = hash_table_find (parser->defines, identifier);
807
808 assert (macro->is_function);
809
810 status = _find_arguments (node_ret, &arguments);
811
812 switch (status) {
813 case FUNCTION_STATUS_SUCCESS:
814 break;
815 case FUNCTION_NOT_A_FUNCTION:
816 printf ("%s", identifier);
Carl Worthae6517f2010-05-25 15:24:59 -0700817 return;
Carl Worthb1854fd2010-05-25 16:28:26 -0700818 case FUNCTION_UNBALANCED_PARENTHESES:
819 fprintf (stderr, "Error: Macro %s call has unbalanced parentheses\n",
820 identifier);
821 exit (1);
Carl Worthae6517f2010-05-25 15:24:59 -0700822 }
823
824 _string_list_push (parser->active, identifier);
825 _glcpp_parser_print_expanded_token_list (parser,
826 macro->replacements);
827 _string_list_pop (parser->active);
828}
829
830void
831_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
832 token_list_t *list)
833{
834 token_node_t *node;
Carl Worthb1854fd2010-05-25 16:28:26 -0700835 function_status_t function_status;
Carl Worthae6517f2010-05-25 15:24:59 -0700836
837 if (list == NULL)
838 return;
839
840 for (node = list->head; node; node = node->next) {
Carl Worthb1854fd2010-05-25 16:28:26 -0700841 if (_glcpp_parser_print_expanded_token (parser, node->token))
842 _glcpp_parser_print_expanded_function (parser, &node);
Carl Worthae6517f2010-05-25 15:24:59 -0700843 }
844}
845
846void
Carl Worthfcbbb462010-05-13 09:36:23 -0700847_define_object_macro (glcpp_parser_t *parser,
848 const char *identifier,
Carl Worth47252442010-05-19 13:54:37 -0700849 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700850{
851 macro_t *macro;
852
853 macro = xtalloc (parser, macro_t);
854
855 macro->is_function = 0;
Carl Worthc5e98552010-05-14 10:12:21 -0700856 macro->parameters = NULL;
Carl Wortha807fb72010-05-18 22:10:04 -0700857 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700858 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700859
860 hash_table_insert (parser->defines, macro, identifier);
861}
862
863void
864_define_function_macro (glcpp_parser_t *parser,
865 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -0700866 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -0700867 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700868{
869 macro_t *macro;
870
871 macro = xtalloc (parser, macro_t);
872
873 macro->is_function = 1;
Carl Worthc5e98552010-05-14 10:12:21 -0700874 macro->parameters = talloc_steal (macro, parameters);
Carl Wortha807fb72010-05-18 22:10:04 -0700875 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700876 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700877
878 hash_table_insert (parser->defines, macro, identifier);
879}
880
Carl Wortha807fb72010-05-18 22:10:04 -0700881static void
Carl Worthc10a51b2010-05-20 15:15:26 -0700882_glcpp_parser_push_expansion (glcpp_parser_t *parser,
883 macro_t *macro,
884 token_node_t *replacements)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700885{
Carl Wortha807fb72010-05-18 22:10:04 -0700886 expansion_node_t *node;
887
888 node = xtalloc (parser, expansion_node_t);
889
890 node->macro = macro;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700891 node->replacements = replacements;
Carl Wortha807fb72010-05-18 22:10:04 -0700892
893 node->next = parser->expansions;
894 parser->expansions = node;
Carl Wortha807fb72010-05-18 22:10:04 -0700895}
896
Carl Worthaaa9acb2010-05-19 13:28:24 -0700897static void
Carl Wortha807fb72010-05-18 22:10:04 -0700898glcpp_parser_pop_expansion (glcpp_parser_t *parser)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700899{
Carl Wortha807fb72010-05-18 22:10:04 -0700900 expansion_node_t *node;
Carl Worth420d05a2010-05-17 10:15:23 -0700901
Carl Wortha807fb72010-05-18 22:10:04 -0700902 node = parser->expansions;
Carl Worth420d05a2010-05-17 10:15:23 -0700903
Carl Wortha807fb72010-05-18 22:10:04 -0700904 if (node == NULL) {
905 fprintf (stderr, "Internal error: _expansion_list_pop called on an empty list.\n");
906 exit (1);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700907 }
908
Carl Wortha807fb72010-05-18 22:10:04 -0700909 parser->expansions = node->next;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700910
Carl Wortha807fb72010-05-18 22:10:04 -0700911 talloc_free (node);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700912}
913
Carl Wortha807fb72010-05-18 22:10:04 -0700914void
Carl Worth2be8be02010-05-14 10:31:43 -0700915_expand_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700916{
Carl Worthfcbbb462010-05-13 09:36:23 -0700917 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700918
Carl Worthfcbbb462010-05-13 09:36:23 -0700919 macro = hash_table_find (parser->defines, identifier);
920 assert (! macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700921 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700922
Carl Worthc10a51b2010-05-20 15:15:26 -0700923 _glcpp_parser_push_expansion (parser, macro, macro->replacements->head);
Carl Worthfcbbb462010-05-13 09:36:23 -0700924}
925
Carl Wortha807fb72010-05-18 22:10:04 -0700926void
Carl Worth2be8be02010-05-14 10:31:43 -0700927_expand_function_macro (glcpp_parser_t *parser,
928 const char *identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700929 argument_list_t *arguments)
Carl Worthfcbbb462010-05-13 09:36:23 -0700930{
Carl Worthfcbbb462010-05-13 09:36:23 -0700931 macro_t *macro;
Carl Worthc10a51b2010-05-20 15:15:26 -0700932 token_list_t *expanded;
933 token_node_t *i, *j;
934 int parameter_index;
Carl Worthfcbbb462010-05-13 09:36:23 -0700935
936 macro = hash_table_find (parser->defines, identifier);
937 assert (macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700938 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700939
Carl Worth8f6a8282010-05-14 10:44:19 -0700940 if (_argument_list_length (arguments) !=
Carl Worth2be8be02010-05-14 10:31:43 -0700941 _string_list_length (macro->parameters))
942 {
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700943 fprintf (stderr,
944 "Error: macro %s invoked with %d arguments (expected %d)\n",
945 identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700946 _argument_list_length (arguments),
Carl Worthc5e98552010-05-14 10:12:21 -0700947 _string_list_length (macro->parameters));
Carl Wortha807fb72010-05-18 22:10:04 -0700948 return;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700949 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700950
Carl Worthc10a51b2010-05-20 15:15:26 -0700951 expanded = _token_list_create (macro);
952
953 for (i = macro->replacements->head; i; i = i->next) {
Carl Worth808401f2010-05-25 14:52:43 -0700954 if (_string_list_contains (macro->parameters,
955 i->token->value.str,
Carl Worthc10a51b2010-05-20 15:15:26 -0700956 &parameter_index))
957 {
958 token_list_t *argument;
959 argument = _argument_list_member_at (arguments,
960 parameter_index);
961 for (j = argument->head; j; j = j->next)
962 {
Carl Worth808401f2010-05-25 14:52:43 -0700963 _token_list_append (expanded, j->token);
Carl Worthc10a51b2010-05-20 15:15:26 -0700964 }
965 } else {
Carl Worth808401f2010-05-25 14:52:43 -0700966 _token_list_append (expanded, i->token);
Carl Worthc10a51b2010-05-20 15:15:26 -0700967 }
968 }
969
970 _glcpp_parser_push_expansion (parser, macro, expanded->head);
Carl Worth33cc4002010-05-12 12:17:10 -0700971}
Carl Worth8f38aff2010-05-19 10:01:29 -0700972
973static int
Carl Worth0293b2e2010-05-19 10:05:40 -0700974glcpp_parser_lex (glcpp_parser_t *parser)
Carl Worth8f38aff2010-05-19 10:01:29 -0700975{
Carl Worthaaa9acb2010-05-19 13:28:24 -0700976 expansion_node_t *expansion;
Carl Worth47252442010-05-19 13:54:37 -0700977 token_node_t *replacements;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700978 int parameter_index;
Carl Worthd8327e52010-05-20 15:18:54 -0700979 const char *token;
980 token_class_t class;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700981
982 /* Who says C can't do efficient tail recursion? */
983 RECURSE:
984
985 expansion = parser->expansions;
986
987 if (expansion == NULL)
988 return glcpp_lex (parser->scanner);
989
990 replacements = expansion->replacements;
991
992 /* Pop expansion when replacements is exhausted. */
993 if (replacements == NULL) {
994 glcpp_parser_pop_expansion (parser);
995 goto RECURSE;
996 }
997
998 expansion->replacements = replacements->next;
999
Carl Worth808401f2010-05-25 14:52:43 -07001000 token = replacements->token->value.str;
Carl Worthd8327e52010-05-20 15:18:54 -07001001
1002 /* Implement token pasting. */
Carl Worth808401f2010-05-25 14:52:43 -07001003 if (replacements->next && strcmp (replacements->next->token->value.str, "##") == 0) {
Carl Worthd8327e52010-05-20 15:18:54 -07001004 token_node_t *next_node;
1005
1006 next_node = replacements->next->next;
1007
1008 if (next_node == NULL) {
1009 fprintf (stderr, "Error: '##' cannot appear at the end of a macro expansion.\n");
1010 exit (1);
1011 }
1012
1013 token = xtalloc_asprintf (parser, "%s%s",
Carl Worth808401f2010-05-25 14:52:43 -07001014 token, next_node->token->value.str);
Carl Worthd8327e52010-05-20 15:18:54 -07001015 expansion->replacements = next_node->next;
1016 }
1017
1018
1019 if (strcmp (token, "(") == 0)
Carl Worthaaa9acb2010-05-19 13:28:24 -07001020 return '(';
Carl Worthd8327e52010-05-20 15:18:54 -07001021 else if (strcmp (token, ")") == 0)
Carl Worthaaa9acb2010-05-19 13:28:24 -07001022 return ')';
Carl Worthaaa9acb2010-05-19 13:28:24 -07001023
Carl Worthd8327e52010-05-20 15:18:54 -07001024 yylval.str = xtalloc_strdup (parser, token);
Carl Worthaaa9acb2010-05-19 13:28:24 -07001025
Carl Worthb5693832010-05-20 08:01:44 -07001026 /* Carefully refuse to expand any finalized identifier. */
Carl Worth808401f2010-05-25 14:52:43 -07001027 if (replacements->token->type == IDENTIFIER_FINALIZED)
Carl Worthb5693832010-05-20 08:01:44 -07001028 return IDENTIFIER_FINALIZED;
1029
Carl Worthaaa9acb2010-05-19 13:28:24 -07001030 switch (glcpp_parser_classify_token (parser, yylval.str,
1031 &parameter_index))
1032 {
Carl Worthaaa9acb2010-05-19 13:28:24 -07001033 case TOKEN_CLASS_IDENTIFIER:
1034 return IDENTIFIER;
1035 break;
Carl Worthb5693832010-05-20 08:01:44 -07001036 case TOKEN_CLASS_IDENTIFIER_FINALIZED:
1037 return IDENTIFIER_FINALIZED;
1038 break;
Carl Worthaaa9acb2010-05-19 13:28:24 -07001039 case TOKEN_CLASS_FUNC_MACRO:
1040 return FUNC_MACRO;
1041 break;
1042 default:
1043 case TOKEN_CLASS_OBJ_MACRO:
1044 return OBJ_MACRO;
1045 break;
1046 }
Carl Worth8f38aff2010-05-19 10:01:29 -07001047}
Carl Worthb20d33c2010-05-20 22:27:07 -07001048
1049static void
1050_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition)
1051{
1052 skip_type_t current = SKIP_NO_SKIP;
1053 skip_node_t *node;
1054
1055 if (parser->skip_stack)
1056 current = parser->skip_stack->type;
1057
1058 node = xtalloc (parser, skip_node_t);
1059
1060 if (current == SKIP_NO_SKIP) {
1061 if (condition)
1062 node->type = SKIP_NO_SKIP;
1063 else
1064 node->type = SKIP_TO_ELSE;
1065 } else {
1066 node->type = SKIP_TO_ENDIF;
1067 }
1068
1069 node->next = parser->skip_stack;
1070 parser->skip_stack = node;
1071}
1072
1073static void
1074_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
1075 int condition)
1076{
1077 if (parser->skip_stack == NULL) {
1078 fprintf (stderr, "Error: %s without #if\n", type);
1079 exit (1);
1080 }
1081
1082 if (parser->skip_stack->type == SKIP_TO_ELSE) {
1083 if (condition)
1084 parser->skip_stack->type = SKIP_NO_SKIP;
1085 } else {
1086 parser->skip_stack->type = SKIP_TO_ENDIF;
1087 }
1088}
Carl Worth80dc60b2010-05-25 14:42:00 -07001089
Carl Worthb20d33c2010-05-20 22:27:07 -07001090static void
1091_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser)
1092{
1093 skip_node_t *node;
1094
1095 if (parser->skip_stack == NULL) {
1096 fprintf (stderr, "Error: #endif without #if\n");
1097 exit (1);
1098 }
1099
1100 node = parser->skip_stack;
1101 parser->skip_stack = node->next;
1102 talloc_free (node);
1103}