blob: a1981995fd0f897509ee39f1ffe1b75c674b85cb [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 Worth808401f2010-05-25 14:52:43 -0700135%type <ival> punctuator
Carl Worthb1854fd2010-05-25 16:28:26 -0700136%type <str> IDENTIFIER OTHER SPACE
137%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 Worthf34a0002010-05-25 16:59:02 -0700238 $$ = _token_create_str (parser, SPACE, $1);
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:
Carl Worthf34a0002010-05-25 16:59:02 -0700498 case SPACE:
Carl Worth808401f2010-05-25 14:52:43 -0700499 printf ("%s", token->value.str);
500 break;
501 case LEFT_SHIFT:
502 printf ("<<");
503 break;
504 case RIGHT_SHIFT:
505 printf (">>");
506 break;
507 case LESS_OR_EQUAL:
508 printf ("<=");
509 break;
510 case GREATER_OR_EQUAL:
511 printf (">=");
512 break;
513 case EQUAL:
514 printf ("==");
515 break;
516 case NOT_EQUAL:
517 printf ("!=");
518 break;
519 case AND:
520 printf ("&&");
521 break;
522 case OR:
523 printf ("||");
524 break;
525 case PASTE:
526 printf ("##");
527 break;
528 default:
529 fprintf (stderr, "Error: Don't know how to print token type %d\n", token->type);
530 break;
531 }
532}
533
Carl Worth47252442010-05-19 13:54:37 -0700534token_list_t *
535_token_list_create (void *ctx)
536{
537 token_list_t *list;
538
539 list = xtalloc (ctx, token_list_t);
540 list->head = NULL;
541 list->tail = NULL;
542
543 return list;
544}
545
546void
Carl Worth808401f2010-05-25 14:52:43 -0700547_token_list_append (token_list_t *list, token_t *token)
Carl Worth47252442010-05-19 13:54:37 -0700548{
549 token_node_t *node;
550
551 node = xtalloc (list, token_node_t);
Carl Worth808401f2010-05-25 14:52:43 -0700552 node->token = xtalloc_reference (list, token);
Carl Worth47252442010-05-19 13:54:37 -0700553
554 node->next = NULL;
555
556 if (list->head == NULL) {
557 list->head = node;
558 } else {
559 list->tail->next = node;
560 }
561
562 list->tail = node;
563}
564
565void
566_token_list_append_list (token_list_t *list, token_list_t *tail)
567{
568 if (list->head == NULL) {
569 list->head = tail->head;
570 } else {
571 list->tail->next = tail->head;
572 }
573
574 list->tail = tail->tail;
575}
Carl Worth80dc60b2010-05-25 14:42:00 -0700576
Carl Worth3a37b872010-05-10 11:44:09 -0700577void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700578yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700579{
580 fprintf (stderr, "Parse error: %s\n", error);
581}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700582
Carl Worth33cc4002010-05-12 12:17:10 -0700583glcpp_parser_t *
584glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700585{
Carl Worth33cc4002010-05-12 12:17:10 -0700586 glcpp_parser_t *parser;
587
Carl Worth5070a202010-05-12 12:45:33 -0700588 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700589
Carl Worth8f38aff2010-05-19 10:01:29 -0700590 glcpp_lex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700591 parser->defines = hash_table_ctor (32, hash_table_string_hash,
592 hash_table_string_compare);
Carl Worthae6517f2010-05-25 15:24:59 -0700593 parser->active = _string_list_create (parser);
Carl Worthf34a0002010-05-25 16:59:02 -0700594 parser->space_tokens = 1;
Carl Wortha807fb72010-05-18 22:10:04 -0700595 parser->expansions = NULL;
596
Carl Worth5a6b9a22010-05-20 14:29:43 -0700597 parser->just_printed_separator = 1;
Carl Worth876e5102010-05-20 14:38:06 -0700598 parser->need_newline = 0;
Carl Worth5a6b9a22010-05-20 14:29:43 -0700599
Carl Worthb20d33c2010-05-20 22:27:07 -0700600 parser->skip_stack = NULL;
601
Carl Worth33cc4002010-05-12 12:17:10 -0700602 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700603}
604
605int
606glcpp_parser_parse (glcpp_parser_t *parser)
607{
608 return yyparse (parser);
609}
610
611void
Carl Worth33cc4002010-05-12 12:17:10 -0700612glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700613{
Carl Worth876e5102010-05-20 14:38:06 -0700614 if (parser->need_newline)
615 printf ("\n");
Carl Worthb20d33c2010-05-20 22:27:07 -0700616 if (parser->skip_stack)
617 fprintf (stderr, "Error: Unterminated #if\n");
Carl Worth8f38aff2010-05-19 10:01:29 -0700618 glcpp_lex_destroy (parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700619 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700620 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700621}
Carl Worthc6d5af32010-05-11 12:30:09 -0700622
Carl Worthbe0e2e92010-05-19 07:29:22 -0700623static int
624glcpp_parser_is_expanding (glcpp_parser_t *parser, const char *member)
625{
626 expansion_node_t *node;
627
628 for (node = parser->expansions; node; node = node->next) {
629 if (node->macro &&
630 strcmp (node->macro->identifier, member) == 0)
631 {
632 return 1;
633 }
634 }
635
636 return 0;
637}
638
Carl Wortha807fb72010-05-18 22:10:04 -0700639token_class_t
640glcpp_parser_classify_token (glcpp_parser_t *parser,
641 const char *identifier,
642 int *parameter_index)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700643{
Carl Worthfcbbb462010-05-13 09:36:23 -0700644 macro_t *macro;
645
Carl Worthc10a51b2010-05-20 15:15:26 -0700646 /* Is this token a defined macro? */
Carl Worthfcbbb462010-05-13 09:36:23 -0700647 macro = hash_table_find (parser->defines, identifier);
648
649 if (macro == NULL)
Carl Wortha807fb72010-05-18 22:10:04 -0700650 return TOKEN_CLASS_IDENTIFIER;
Carl Worthfcbbb462010-05-13 09:36:23 -0700651
Carl Worthbe0e2e92010-05-19 07:29:22 -0700652 /* Don't consider this a macro if we are already actively
653 * expanding this macro. */
654 if (glcpp_parser_is_expanding (parser, identifier))
Carl Worthb5693832010-05-20 08:01:44 -0700655 return TOKEN_CLASS_IDENTIFIER_FINALIZED;
Carl Worthbe0e2e92010-05-19 07:29:22 -0700656
657 /* Definitely a macro. Just need to check if it's function-like. */
Carl Worthfcbbb462010-05-13 09:36:23 -0700658 if (macro->is_function)
Carl Wortha807fb72010-05-18 22:10:04 -0700659 return TOKEN_CLASS_FUNC_MACRO;
Carl Worthfcbbb462010-05-13 09:36:23 -0700660 else
Carl Wortha807fb72010-05-18 22:10:04 -0700661 return TOKEN_CLASS_OBJ_MACRO;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700662}
663
Carl Worthb1854fd2010-05-25 16:28:26 -0700664/* Print a non-macro token, or the expansion of an object-like macro.
665 *
666 * Returns 0 if this token is completely printed.
667 *
668 * Returns 1 in the case that 'token' is a function-like macro that
669 * needs further expansion.
670 */
671static int
Carl Worthae6517f2010-05-25 15:24:59 -0700672_glcpp_parser_print_expanded_token (glcpp_parser_t *parser,
673 token_t *token)
674{
675 const char *identifier;
676 macro_t *macro;
677
678 /* We only expand identifiers */
679 if (token->type != IDENTIFIER) {
680 _token_print (token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700681 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700682 }
683
684 /* Look up this identifier in the hash table. */
685 identifier = token->value.str;
686 macro = hash_table_find (parser->defines, identifier);
687
688 /* Not a macro, so just print directly. */
689 if (macro == NULL) {
690 printf ("%s", identifier);
Carl Worthb1854fd2010-05-25 16:28:26 -0700691 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700692 }
693
Carl Worthb1854fd2010-05-25 16:28:26 -0700694 /* For function-like macros return 1 for further processing. */
Carl Worthae6517f2010-05-25 15:24:59 -0700695 if (macro->is_function) {
Carl Worthb1854fd2010-05-25 16:28:26 -0700696 return 1;
Carl Worthae6517f2010-05-25 15:24:59 -0700697 }
698
699 /* Finally, don't expand this macro if we're already actively
700 * expanding it, (to avoid infinite recursion). */
701 if (_string_list_contains (parser->active, identifier, NULL)) {
702 printf ("%s", identifier);
Carl Worthb1854fd2010-05-25 16:28:26 -0700703 return 0;
704 }
705
706 _string_list_push (parser->active, identifier);
707 _glcpp_parser_print_expanded_token_list (parser,
708 macro->replacements);
709 _string_list_pop (parser->active);
710
711 return 0;
712}
713
714typedef enum function_status
715{
716 FUNCTION_STATUS_SUCCESS,
717 FUNCTION_NOT_A_FUNCTION,
718 FUNCTION_UNBALANCED_PARENTHESES
719} function_status_t;
720
721/* Find a set of function-like macro arguments by looking for a
722 * balanced set of parentheses. Upon return *node will be the last
723 * consumed node, such that further processing can continue with
724 * node->next.
725 *
726 * Return values:
727 *
728 * FUNCTION_STATUS_SUCCESS:
729 *
730 * Successfully parsed a set of function arguments.
731 *
732 * FUNCTION_NOT_A_FUNCTION:
733 *
734 * Macro name not followed by a '('. This is not an error, but
735 * simply that the macro name should be treated as a non-macro.
736 *
737 * FUNCTION_UNBLANCED_PARENTHESES
738 *
739 * Macro name is not followed by a balanced set of parentheses.
740 */
741static function_status_t
742_find_arguments (token_node_t **node_ret, argument_list_t **arguments)
743{
744 token_node_t *node = *node_ret, *last;
745 int paren_count;
746 int arg_count;
747
748 last = node;
749 node = node->next;
750
751 /* Ignore whitespace before first parenthesis. */
752 while (node && node->token->type == SPACE)
753 node = node->next;
754
755 if (node == NULL || node->token->type != '(')
756 return FUNCTION_NOT_A_FUNCTION;
757
758 paren_count = 0;
759 arg_count = 0;
760 do {
761 if (node->token->type == '(')
762 {
763 paren_count++;
764 }
765 else if (node->token->type == ')')
766 {
767 paren_count--;
768 }
769 else if (node->token->type == ',' &&
770 paren_count == 1)
771 {
772 arg_count++;
773 }
774
775 last = node;
776 node = node->next;
777
778 } while (node && paren_count);
779
780 if (node && paren_count)
781 return FUNCTION_UNBALANCED_PARENTHESES;
782
783 *node_ret = last;
784
785 return FUNCTION_STATUS_SUCCESS;
786}
787
788/* Prints the expansion of *node (consuming further tokens from the
789 * list as necessary). Upon return *node will be the last consumed
790 * node, such that further processing can continue with node->next. */
791static void
792_glcpp_parser_print_expanded_function (glcpp_parser_t *parser,
793 token_node_t **node_ret)
794{
795 macro_t *macro;
796 token_node_t *node;
797 const char *identifier;
798 argument_list_t *arguments;
799 function_status_t status;
800
801 node = *node_ret;
802 identifier = node->token->value.str;
803
804 macro = hash_table_find (parser->defines, identifier);
805
806 assert (macro->is_function);
807
808 status = _find_arguments (node_ret, &arguments);
809
810 switch (status) {
811 case FUNCTION_STATUS_SUCCESS:
812 break;
813 case FUNCTION_NOT_A_FUNCTION:
814 printf ("%s", identifier);
Carl Worthae6517f2010-05-25 15:24:59 -0700815 return;
Carl Worthb1854fd2010-05-25 16:28:26 -0700816 case FUNCTION_UNBALANCED_PARENTHESES:
817 fprintf (stderr, "Error: Macro %s call has unbalanced parentheses\n",
818 identifier);
819 exit (1);
Carl Worthae6517f2010-05-25 15:24:59 -0700820 }
821
822 _string_list_push (parser->active, identifier);
823 _glcpp_parser_print_expanded_token_list (parser,
824 macro->replacements);
825 _string_list_pop (parser->active);
826}
827
828void
829_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
830 token_list_t *list)
831{
832 token_node_t *node;
Carl Worthb1854fd2010-05-25 16:28:26 -0700833 function_status_t function_status;
Carl Worthae6517f2010-05-25 15:24:59 -0700834
835 if (list == NULL)
836 return;
837
838 for (node = list->head; node; node = node->next) {
Carl Worthb1854fd2010-05-25 16:28:26 -0700839 if (_glcpp_parser_print_expanded_token (parser, node->token))
840 _glcpp_parser_print_expanded_function (parser, &node);
Carl Worthae6517f2010-05-25 15:24:59 -0700841 }
842}
843
844void
Carl Worthfcbbb462010-05-13 09:36:23 -0700845_define_object_macro (glcpp_parser_t *parser,
846 const char *identifier,
Carl Worth47252442010-05-19 13:54:37 -0700847 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700848{
849 macro_t *macro;
850
851 macro = xtalloc (parser, macro_t);
852
853 macro->is_function = 0;
Carl Worthc5e98552010-05-14 10:12:21 -0700854 macro->parameters = NULL;
Carl Wortha807fb72010-05-18 22:10:04 -0700855 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700856 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700857
858 hash_table_insert (parser->defines, macro, identifier);
859}
860
861void
862_define_function_macro (glcpp_parser_t *parser,
863 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -0700864 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -0700865 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700866{
867 macro_t *macro;
868
869 macro = xtalloc (parser, macro_t);
870
871 macro->is_function = 1;
Carl Worthc5e98552010-05-14 10:12:21 -0700872 macro->parameters = talloc_steal (macro, parameters);
Carl Wortha807fb72010-05-18 22:10:04 -0700873 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700874 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700875
876 hash_table_insert (parser->defines, macro, identifier);
877}
878
Carl Wortha807fb72010-05-18 22:10:04 -0700879static void
Carl Worthc10a51b2010-05-20 15:15:26 -0700880_glcpp_parser_push_expansion (glcpp_parser_t *parser,
881 macro_t *macro,
882 token_node_t *replacements)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700883{
Carl Wortha807fb72010-05-18 22:10:04 -0700884 expansion_node_t *node;
885
886 node = xtalloc (parser, expansion_node_t);
887
888 node->macro = macro;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700889 node->replacements = replacements;
Carl Wortha807fb72010-05-18 22:10:04 -0700890
891 node->next = parser->expansions;
892 parser->expansions = node;
Carl Wortha807fb72010-05-18 22:10:04 -0700893}
894
Carl Worthaaa9acb2010-05-19 13:28:24 -0700895static void
Carl Wortha807fb72010-05-18 22:10:04 -0700896glcpp_parser_pop_expansion (glcpp_parser_t *parser)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700897{
Carl Wortha807fb72010-05-18 22:10:04 -0700898 expansion_node_t *node;
Carl Worth420d05a2010-05-17 10:15:23 -0700899
Carl Wortha807fb72010-05-18 22:10:04 -0700900 node = parser->expansions;
Carl Worth420d05a2010-05-17 10:15:23 -0700901
Carl Wortha807fb72010-05-18 22:10:04 -0700902 if (node == NULL) {
903 fprintf (stderr, "Internal error: _expansion_list_pop called on an empty list.\n");
904 exit (1);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700905 }
906
Carl Wortha807fb72010-05-18 22:10:04 -0700907 parser->expansions = node->next;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700908
Carl Wortha807fb72010-05-18 22:10:04 -0700909 talloc_free (node);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700910}
911
Carl Wortha807fb72010-05-18 22:10:04 -0700912void
Carl Worth2be8be02010-05-14 10:31:43 -0700913_expand_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700914{
Carl Worthfcbbb462010-05-13 09:36:23 -0700915 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700916
Carl Worthfcbbb462010-05-13 09:36:23 -0700917 macro = hash_table_find (parser->defines, identifier);
918 assert (! macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700919 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700920
Carl Worthc10a51b2010-05-20 15:15:26 -0700921 _glcpp_parser_push_expansion (parser, macro, macro->replacements->head);
Carl Worthfcbbb462010-05-13 09:36:23 -0700922}
923
Carl Wortha807fb72010-05-18 22:10:04 -0700924void
Carl Worth2be8be02010-05-14 10:31:43 -0700925_expand_function_macro (glcpp_parser_t *parser,
926 const char *identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700927 argument_list_t *arguments)
Carl Worthfcbbb462010-05-13 09:36:23 -0700928{
Carl Worthfcbbb462010-05-13 09:36:23 -0700929 macro_t *macro;
Carl Worthc10a51b2010-05-20 15:15:26 -0700930 token_list_t *expanded;
931 token_node_t *i, *j;
932 int parameter_index;
Carl Worthfcbbb462010-05-13 09:36:23 -0700933
934 macro = hash_table_find (parser->defines, identifier);
935 assert (macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700936 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700937
Carl Worth8f6a8282010-05-14 10:44:19 -0700938 if (_argument_list_length (arguments) !=
Carl Worth2be8be02010-05-14 10:31:43 -0700939 _string_list_length (macro->parameters))
940 {
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700941 fprintf (stderr,
942 "Error: macro %s invoked with %d arguments (expected %d)\n",
943 identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700944 _argument_list_length (arguments),
Carl Worthc5e98552010-05-14 10:12:21 -0700945 _string_list_length (macro->parameters));
Carl Wortha807fb72010-05-18 22:10:04 -0700946 return;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700947 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700948
Carl Worthc10a51b2010-05-20 15:15:26 -0700949 expanded = _token_list_create (macro);
950
951 for (i = macro->replacements->head; i; i = i->next) {
Carl Worth808401f2010-05-25 14:52:43 -0700952 if (_string_list_contains (macro->parameters,
953 i->token->value.str,
Carl Worthc10a51b2010-05-20 15:15:26 -0700954 &parameter_index))
955 {
956 token_list_t *argument;
957 argument = _argument_list_member_at (arguments,
958 parameter_index);
959 for (j = argument->head; j; j = j->next)
960 {
Carl Worth808401f2010-05-25 14:52:43 -0700961 _token_list_append (expanded, j->token);
Carl Worthc10a51b2010-05-20 15:15:26 -0700962 }
963 } else {
Carl Worth808401f2010-05-25 14:52:43 -0700964 _token_list_append (expanded, i->token);
Carl Worthc10a51b2010-05-20 15:15:26 -0700965 }
966 }
967
968 _glcpp_parser_push_expansion (parser, macro, expanded->head);
Carl Worth33cc4002010-05-12 12:17:10 -0700969}
Carl Worth8f38aff2010-05-19 10:01:29 -0700970
971static int
Carl Worth0293b2e2010-05-19 10:05:40 -0700972glcpp_parser_lex (glcpp_parser_t *parser)
Carl Worth8f38aff2010-05-19 10:01:29 -0700973{
Carl Worthaaa9acb2010-05-19 13:28:24 -0700974 expansion_node_t *expansion;
Carl Worth47252442010-05-19 13:54:37 -0700975 token_node_t *replacements;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700976 int parameter_index;
Carl Worthd8327e52010-05-20 15:18:54 -0700977 const char *token;
978 token_class_t class;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700979
980 /* Who says C can't do efficient tail recursion? */
981 RECURSE:
982
983 expansion = parser->expansions;
984
985 if (expansion == NULL)
986 return glcpp_lex (parser->scanner);
987
988 replacements = expansion->replacements;
989
990 /* Pop expansion when replacements is exhausted. */
991 if (replacements == NULL) {
992 glcpp_parser_pop_expansion (parser);
993 goto RECURSE;
994 }
995
996 expansion->replacements = replacements->next;
997
Carl Worth808401f2010-05-25 14:52:43 -0700998 token = replacements->token->value.str;
Carl Worthd8327e52010-05-20 15:18:54 -0700999
1000 /* Implement token pasting. */
Carl Worth808401f2010-05-25 14:52:43 -07001001 if (replacements->next && strcmp (replacements->next->token->value.str, "##") == 0) {
Carl Worthd8327e52010-05-20 15:18:54 -07001002 token_node_t *next_node;
1003
1004 next_node = replacements->next->next;
1005
1006 if (next_node == NULL) {
1007 fprintf (stderr, "Error: '##' cannot appear at the end of a macro expansion.\n");
1008 exit (1);
1009 }
1010
1011 token = xtalloc_asprintf (parser, "%s%s",
Carl Worth808401f2010-05-25 14:52:43 -07001012 token, next_node->token->value.str);
Carl Worthd8327e52010-05-20 15:18:54 -07001013 expansion->replacements = next_node->next;
1014 }
1015
1016
1017 if (strcmp (token, "(") == 0)
Carl Worthaaa9acb2010-05-19 13:28:24 -07001018 return '(';
Carl Worthd8327e52010-05-20 15:18:54 -07001019 else if (strcmp (token, ")") == 0)
Carl Worthaaa9acb2010-05-19 13:28:24 -07001020 return ')';
Carl Worthaaa9acb2010-05-19 13:28:24 -07001021
Carl Worthd8327e52010-05-20 15:18:54 -07001022 yylval.str = xtalloc_strdup (parser, token);
Carl Worthaaa9acb2010-05-19 13:28:24 -07001023
Carl Worthb5693832010-05-20 08:01:44 -07001024 /* Carefully refuse to expand any finalized identifier. */
Carl Worth808401f2010-05-25 14:52:43 -07001025 if (replacements->token->type == IDENTIFIER_FINALIZED)
Carl Worthb5693832010-05-20 08:01:44 -07001026 return IDENTIFIER_FINALIZED;
1027
Carl Worthaaa9acb2010-05-19 13:28:24 -07001028 switch (glcpp_parser_classify_token (parser, yylval.str,
1029 &parameter_index))
1030 {
Carl Worthaaa9acb2010-05-19 13:28:24 -07001031 case TOKEN_CLASS_IDENTIFIER:
1032 return IDENTIFIER;
1033 break;
Carl Worthb5693832010-05-20 08:01:44 -07001034 case TOKEN_CLASS_IDENTIFIER_FINALIZED:
1035 return IDENTIFIER_FINALIZED;
1036 break;
Carl Worthaaa9acb2010-05-19 13:28:24 -07001037 case TOKEN_CLASS_FUNC_MACRO:
1038 return FUNC_MACRO;
1039 break;
1040 default:
1041 case TOKEN_CLASS_OBJ_MACRO:
1042 return OBJ_MACRO;
1043 break;
1044 }
Carl Worth8f38aff2010-05-19 10:01:29 -07001045}
Carl Worthb20d33c2010-05-20 22:27:07 -07001046
1047static void
1048_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition)
1049{
1050 skip_type_t current = SKIP_NO_SKIP;
1051 skip_node_t *node;
1052
1053 if (parser->skip_stack)
1054 current = parser->skip_stack->type;
1055
1056 node = xtalloc (parser, skip_node_t);
1057
1058 if (current == SKIP_NO_SKIP) {
1059 if (condition)
1060 node->type = SKIP_NO_SKIP;
1061 else
1062 node->type = SKIP_TO_ELSE;
1063 } else {
1064 node->type = SKIP_TO_ENDIF;
1065 }
1066
1067 node->next = parser->skip_stack;
1068 parser->skip_stack = node;
1069}
1070
1071static void
1072_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
1073 int condition)
1074{
1075 if (parser->skip_stack == NULL) {
1076 fprintf (stderr, "Error: %s without #if\n", type);
1077 exit (1);
1078 }
1079
1080 if (parser->skip_stack->type == SKIP_TO_ELSE) {
1081 if (condition)
1082 parser->skip_stack->type = SKIP_NO_SKIP;
1083 } else {
1084 parser->skip_stack->type = SKIP_TO_ENDIF;
1085 }
1086}
Carl Worth80dc60b2010-05-25 14:42:00 -07001087
Carl Worthb20d33c2010-05-20 22:27:07 -07001088static void
1089_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser)
1090{
1091 skip_node_t *node;
1092
1093 if (parser->skip_stack == NULL) {
1094 fprintf (stderr, "Error: #endif without #if\n");
1095 exit (1);
1096 }
1097
1098 node = parser->skip_stack;
1099 parser->skip_stack = node->next;
1100 talloc_free (node);
1101}