blob: 0d3afa7af64c8ae9573d0a36633400dba5416357 [file] [log] [blame]
Carl Worth3a37b872010-05-10 11:44:09 -07001%{
2/*
3 * Copyright © 2010 Intel Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
Carl Worthfcbbb462010-05-13 09:36:23 -070027#include <assert.h>
Carl Worth3a37b872010-05-10 11:44:09 -070028
Carl Wortha1e32bc2010-05-10 13:17:25 -070029#include "glcpp.h"
30
Carl Worth3a37b872010-05-10 11:44:09 -070031void
Carl Wortha1e32bc2010-05-10 13:17:25 -070032yyerror (void *scanner, const char *error);
Carl Worth3a37b872010-05-10 11:44:09 -070033
Carl Worth33cc4002010-05-12 12:17:10 -070034void
Carl Worthfcbbb462010-05-13 09:36:23 -070035_define_object_macro (glcpp_parser_t *parser,
36 const char *macro,
Carl Worth47252442010-05-19 13:54:37 -070037 token_list_t *replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -070038
39void
40_define_function_macro (glcpp_parser_t *parser,
41 const char *macro,
Carl Worthc5e98552010-05-14 10:12:21 -070042 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -070043 token_list_t *replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -070044
Carl Wortha807fb72010-05-18 22:10:04 -070045void
Carl Worth2be8be02010-05-14 10:31:43 -070046_expand_object_macro (glcpp_parser_t *parser, const char *identifier);
47
Carl Wortha807fb72010-05-18 22:10:04 -070048void
Carl Worth2be8be02010-05-14 10:31:43 -070049_expand_function_macro (glcpp_parser_t *parser,
50 const char *identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -070051 argument_list_t *arguments);
Carl Worthfcbbb462010-05-13 09:36:23 -070052
Carl Worth610053b2010-05-14 10:05:11 -070053string_list_t *
54_string_list_create (void *ctx);
Carl Worth33cc4002010-05-12 12:17:10 -070055
56void
Carl Worth610053b2010-05-14 10:05:11 -070057_string_list_append_item (string_list_t *list, const char *str);
Carl Worthfcbbb462010-05-13 09:36:23 -070058
59void
Carl Worth610053b2010-05-14 10:05:11 -070060_string_list_append_list (string_list_t *list, string_list_t *tail);
Carl Worthc6d5af32010-05-11 12:30:09 -070061
Carl Worthdcc2ecd2010-05-13 12:56:42 -070062int
Carl Worth610053b2010-05-14 10:05:11 -070063_string_list_contains (string_list_t *list, const char *member, int *index);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070064
Carl Worthdcc2ecd2010-05-13 12:56:42 -070065int
Carl Worth610053b2010-05-14 10:05:11 -070066_string_list_length (string_list_t *list);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070067
Carl Worth8f6a8282010-05-14 10:44:19 -070068argument_list_t *
69_argument_list_create (void *ctx);
70
71void
Carl Worth47252442010-05-19 13:54:37 -070072_argument_list_append (argument_list_t *list, token_list_t *argument);
Carl Worth8f6a8282010-05-14 10:44:19 -070073
74int
75_argument_list_length (argument_list_t *list);
76
Carl Worth47252442010-05-19 13:54:37 -070077token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -070078_argument_list_member_at (argument_list_t *list, int index);
79
Carl Worth47252442010-05-19 13:54:37 -070080token_list_t *
81_token_list_create (void *ctx);
82
83void
84_token_list_append (token_list_t *list, int type, const char *value);
85
86void
87_token_list_append_list (token_list_t *list, token_list_t *tail);
88
Carl Worthaaa9acb2010-05-19 13:28:24 -070089static void
Carl Worthaaa9acb2010-05-19 13:28:24 -070090glcpp_parser_pop_expansion (glcpp_parser_t *parser);
91
Carl Worthb20d33c2010-05-20 22:27:07 -070092static void
93_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition);
94
95static void
96_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
97 int condition);
98
99static void
100_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser);
101
Carl Worth0293b2e2010-05-19 10:05:40 -0700102#define yylex glcpp_parser_lex
103
Carl Worth8f38aff2010-05-19 10:01:29 -0700104static int
Carl Worth0293b2e2010-05-19 10:05:40 -0700105glcpp_parser_lex (glcpp_parser_t *parser);
Carl Worth8f38aff2010-05-19 10:01:29 -0700106
Carl Worth3a37b872010-05-10 11:44:09 -0700107%}
108
Carl Worth33cc4002010-05-12 12:17:10 -0700109%union {
Carl Worth005b3202010-05-20 14:19:57 -0700110 int ival;
Carl Worth33cc4002010-05-12 12:17:10 -0700111 char *str;
Carl Worth8f6a8282010-05-14 10:44:19 -0700112 argument_list_t *argument_list;
Carl Worth47252442010-05-19 13:54:37 -0700113 string_list_t *string_list;
Carl Worthb5693832010-05-20 08:01:44 -0700114 token_t token;
Carl Worth47252442010-05-19 13:54:37 -0700115 token_list_t *token_list;
Carl Worth33cc4002010-05-12 12:17:10 -0700116}
117
Carl Worth0b27b5f2010-05-10 16:16:06 -0700118%parse-param {glcpp_parser_t *parser}
Carl Worth0293b2e2010-05-19 10:05:40 -0700119%lex-param {glcpp_parser_t *parser}
Carl Worth38aa8352010-05-10 11:52:29 -0700120
Carl Worthbcbd5872010-05-24 10:37:38 -0700121%token DEFINE DEFINED ELIF ELSE ENDIF FUNC_MACRO IDENTIFIER IDENTIFIER_FINALIZED IF IFDEF IFNDEF INTEGER OBJ_MACRO NEWLINE SPACE TOKEN UNDEF
Carl Worthb20d33c2010-05-20 22:27:07 -0700122%type <ival> expression INTEGER punctuator
Carl Worth005b3202010-05-20 14:19:57 -0700123%type <str> content FUNC_MACRO IDENTIFIER IDENTIFIER_FINALIZED OBJ_MACRO
Carl Worth8f6a8282010-05-14 10:44:19 -0700124%type <argument_list> argument_list
Carl Worth47252442010-05-19 13:54:37 -0700125%type <string_list> macro parameter_list
Carl Worth9f3d2c42010-05-20 08:42:02 -0700126%type <token> TOKEN argument_word argument_word_or_comma
127%type <token_list> argument argument_or_comma replacement_list pp_tokens
Carl Worthbcbd5872010-05-24 10:37:38 -0700128%left OR
129%left AND
130%left '|'
131%left '^'
132%left '&'
133%left EQUAL NOT_EQUAL
134%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL
135%left LEFT_SHIFT RIGHT_SHIFT
136%left '+' '-'
137%left '*' '/' '%'
138%right UNARY
Carl Worth3a37b872010-05-10 11:44:09 -0700139
Carl Worth796e1f02010-05-17 12:45:16 -0700140/* Hard to remove shift/reduce conflicts documented as follows:
141 *
142 * 1. '(' after FUNC_MACRO name which is correctly resolved to shift
143 * to form macro invocation rather than reducing directly to
144 * content.
Carl Worth69f390d2010-05-19 07:42:42 -0700145 *
146 * 2. Similarly, '(' after FUNC_MACRO which is correctly resolved to
147 * shift to form macro invocation rather than reducing directly to
148 * argument.
Carl Worth9f3d2c42010-05-20 08:42:02 -0700149 *
150 * 3. Similarly again now that we added argument_or_comma as well.
Carl Worth796e1f02010-05-17 12:45:16 -0700151 */
Carl Worth9f3d2c42010-05-20 08:42:02 -0700152%expect 3
Carl Worth796e1f02010-05-17 12:45:16 -0700153
Carl Worth3a37b872010-05-10 11:44:09 -0700154%%
155
Carl Worthbcbd5872010-05-24 10:37:38 -0700156 /* We do all printing at the input level. */
Carl Worth33cc4002010-05-12 12:17:10 -0700157input:
Carl Worth005b3202010-05-20 14:19:57 -0700158 /* empty */ {
Carl Worth5a6b9a22010-05-20 14:29:43 -0700159 parser->just_printed_separator = 1;
Carl Worth005b3202010-05-20 14:19:57 -0700160 }
161| input content {
162 int is_token;
Carl Worthb20d33c2010-05-20 22:27:07 -0700163 int skipping = 0;
Carl Worth005b3202010-05-20 14:19:57 -0700164
Carl Worthb20d33c2010-05-20 22:27:07 -0700165 if (parser->skip_stack && parser->skip_stack->type != SKIP_NO_SKIP)
166 skipping = 1;
167
168 if ($2 && strlen ($2) && ! skipping) {
Carl Worth005b3202010-05-20 14:19:57 -0700169 int c = $2[0];
170 int is_not_separator = ((c >= 'a' && c <= 'z') ||
171 (c >= 'A' && c <= 'Z') ||
172 (c >= 'A' && c <= 'Z') ||
173 (c >= '0' && c <= '9') ||
174 (c == '_'));
175
Carl Worth5a6b9a22010-05-20 14:29:43 -0700176 if (! parser->just_printed_separator && is_not_separator)
177 {
Carl Worth005b3202010-05-20 14:19:57 -0700178 printf (" ");
Carl Worth5a6b9a22010-05-20 14:29:43 -0700179 }
Carl Worth005b3202010-05-20 14:19:57 -0700180 printf ("%s", $2);
Carl Worth5a6b9a22010-05-20 14:29:43 -0700181
Carl Worth005b3202010-05-20 14:19:57 -0700182 if (is_not_separator)
Carl Worth5a6b9a22010-05-20 14:29:43 -0700183 parser->just_printed_separator = 0;
Carl Worth005b3202010-05-20 14:19:57 -0700184 else
Carl Worth5a6b9a22010-05-20 14:29:43 -0700185 parser->just_printed_separator = 1;
Carl Worth005b3202010-05-20 14:19:57 -0700186 }
Carl Worth5a6b9a22010-05-20 14:29:43 -0700187
Carl Worth005b3202010-05-20 14:19:57 -0700188 if ($2)
189 talloc_free ($2);
Carl Worth876e5102010-05-20 14:38:06 -0700190
191 if (parser->need_newline) {
192 printf ("\n");
193 parser->just_printed_separator = 1;
194 parser->need_newline = 0;
195 }
Carl Worth005b3202010-05-20 14:19:57 -0700196 }
Carl Worth3a37b872010-05-10 11:44:09 -0700197;
198
Carl Worth33cc4002010-05-12 12:17:10 -0700199content:
Carl Worth9f62a7e2010-05-13 07:38:29 -0700200 IDENTIFIER {
Carl Worth005b3202010-05-20 14:19:57 -0700201 $$ = $1;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700202 }
Carl Worthb5693832010-05-20 08:01:44 -0700203| IDENTIFIER_FINALIZED {
Carl Worth005b3202010-05-20 14:19:57 -0700204 $$ = $1;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700205 }
Carl Worthb5693832010-05-20 08:01:44 -0700206| TOKEN {
Carl Worth005b3202010-05-20 14:19:57 -0700207 $$ = $1.value;
Carl Worthb5693832010-05-20 08:01:44 -0700208 }
Carl Worthacf87bc2010-05-17 10:34:29 -0700209| FUNC_MACRO {
Carl Worth005b3202010-05-20 14:19:57 -0700210 $$ = $1;
Carl Worthacf87bc2010-05-17 10:34:29 -0700211 }
Carl Wortha807fb72010-05-18 22:10:04 -0700212| directive {
Carl Worth005b3202010-05-20 14:19:57 -0700213 $$ = talloc_strdup (parser, "\n");
Carl Worth2be8be02010-05-14 10:31:43 -0700214 }
Carl Worth005b3202010-05-20 14:19:57 -0700215| punctuator {
216 $$ = talloc_asprintf (parser, "%c", $1);
217 }
218| macro {
219 $$ = NULL;
220 }
Carl Worthcd27e642010-05-12 13:11:50 -0700221;
222
Carl Worth005b3202010-05-20 14:19:57 -0700223punctuator:
224 '(' { $$ = '('; }
225| ')' { $$ = ')'; }
226| ',' { $$ = ','; }
227 ;
228
Carl Worthfcbbb462010-05-13 09:36:23 -0700229macro:
230 FUNC_MACRO '(' argument_list ')' {
Carl Wortha807fb72010-05-18 22:10:04 -0700231 _expand_function_macro (parser, $1, $3);
Carl Worthfcbbb462010-05-13 09:36:23 -0700232 }
233| OBJ_MACRO {
Carl Wortha807fb72010-05-18 22:10:04 -0700234 _expand_object_macro (parser, $1);
Carl Worthfcbbb462010-05-13 09:36:23 -0700235 talloc_free ($1);
236 }
237;
238
239argument_list:
Carl Worthac070e82010-05-14 11:33:00 -0700240 /* empty */ {
241 $$ = _argument_list_create (parser);
242 }
243| argument {
Carl Worth8f6a8282010-05-14 10:44:19 -0700244 $$ = _argument_list_create (parser);
245 _argument_list_append ($$, $1);
246 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700247| argument_list ',' argument {
Carl Worth8f6a8282010-05-14 10:44:19 -0700248 _argument_list_append ($1, $3);
Carl Worthfcbbb462010-05-13 09:36:23 -0700249 $$ = $1;
250 }
251;
252
253argument:
Carl Worth59ca9892010-05-19 07:49:47 -0700254 argument_word {
Carl Worth47252442010-05-19 13:54:37 -0700255 $$ = _token_list_create (parser);
Carl Worthb5693832010-05-20 08:01:44 -0700256 _token_list_append ($$, $1.type, $1.value);
Carl Worthfcbbb462010-05-13 09:36:23 -0700257 }
Carl Worth59ca9892010-05-19 07:49:47 -0700258| argument argument_word {
Carl Worthb5693832010-05-20 08:01:44 -0700259 _token_list_append ($1, $2.type, $2.value);
260 talloc_free ($2.value);
Carl Worth3596bb12010-05-14 16:53:52 -0700261 $$ = $1;
Carl Worthfcbbb462010-05-13 09:36:23 -0700262 }
Carl Worth9f3d2c42010-05-20 08:42:02 -0700263| argument '(' argument_or_comma ')' {
Carl Worth47252442010-05-19 13:54:37 -0700264 _token_list_append ($1, '(', "(");
265 _token_list_append_list ($1, $3);
266 _token_list_append ($1, ')', ")");
Carl Worth3596bb12010-05-14 16:53:52 -0700267 $$ = $1;
268 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700269;
270
Carl Worth59ca9892010-05-19 07:49:47 -0700271argument_word:
Carl Worthb5693832010-05-20 08:01:44 -0700272 IDENTIFIER { $$.type = IDENTIFIER; $$.value = $1; }
273| IDENTIFIER_FINALIZED { $$.type = IDENTIFIER_FINALIZED; $$.value = $1; }
Carl Worth59ca9892010-05-19 07:49:47 -0700274| TOKEN { $$ = $1; }
Carl Worthb5693832010-05-20 08:01:44 -0700275| FUNC_MACRO { $$.type = FUNC_MACRO; $$.value = $1; }
276| macro { $$.type = TOKEN; $$.value = xtalloc_strdup (parser, ""); }
Carl Worth59ca9892010-05-19 07:49:47 -0700277;
278
Carl Worth9f3d2c42010-05-20 08:42:02 -0700279 /* XXX: The body of argument_or_comma is the same as the body
280 * of argument, but with "argument" and "argument_word"
281 * changed to "argument_or_comma" and
282 * "argument_word_or_comma". It would be nice to have less
283 * redundancy here, but I'm not sure how.
284 *
285 * It would also be nice to have a less ugly grammar to have
286 * to implement, but such is the C preprocessor.
287 */
288argument_or_comma:
289 argument_word_or_comma {
290 $$ = _token_list_create (parser);
291 _token_list_append ($$, $1.type, $1.value);
292 }
293| argument_or_comma argument_word_or_comma {
294 _token_list_append ($1, $2.type, $2.value);
295 $$ = $1;
296 }
297| argument_or_comma '(' argument_or_comma ')' {
298 _token_list_append ($1, '(', "(");
299 _token_list_append_list ($1, $3);
300 _token_list_append ($1, ')', ")");
301 $$ = $1;
302 }
303;
304
305argument_word_or_comma:
306 IDENTIFIER { $$.type = IDENTIFIER; $$.value = $1; }
307| IDENTIFIER_FINALIZED { $$.type = IDENTIFIER_FINALIZED; $$.value = $1; }
308| TOKEN { $$ = $1; }
309| FUNC_MACRO { $$.type = FUNC_MACRO; $$.value = $1; }
310| macro { $$.type = TOKEN; $$.value = xtalloc_strdup (parser, ""); }
311| ',' { $$.type = ','; $$.value = xtalloc_strdup (parser, ","); }
312;
Carl Worth59ca9892010-05-19 07:49:47 -0700313
Carl Worth33cc4002010-05-12 12:17:10 -0700314directive:
Carl Worthaaa9acb2010-05-19 13:28:24 -0700315 DEFINE IDENTIFIER NEWLINE {
Carl Worth47252442010-05-19 13:54:37 -0700316 token_list_t *list = _token_list_create (parser);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700317 _define_object_macro (parser, $2, list);
Carl Worth0a93cbb2010-05-13 10:29:07 -0700318 }
Carl Worthaaa9acb2010-05-19 13:28:24 -0700319| DEFINE IDENTIFIER SPACE replacement_list NEWLINE {
320 _define_object_macro (parser, $2, $4);
321 }
322| DEFINE IDENTIFIER '(' parameter_list ')' replacement_list NEWLINE {
Carl Worth81f01432010-05-14 17:08:45 -0700323 _define_function_macro (parser, $2, $4, $6);
Carl Worthfcbbb462010-05-13 09:36:23 -0700324 }
Carl Worthb20d33c2010-05-20 22:27:07 -0700325| IF expression NEWLINE {
326 _glcpp_parser_skip_stack_push_if (parser, $2);
327 }
328| IFDEF IDENTIFIER NEWLINE {
329 string_list_t *macro = hash_table_find (parser->defines, $2);
330 talloc_free ($2);
331 _glcpp_parser_skip_stack_push_if (parser, macro != NULL);
332 }
333| IFNDEF IDENTIFIER NEWLINE {
334 string_list_t *macro = hash_table_find (parser->defines, $2);
335 talloc_free ($2);
336 _glcpp_parser_skip_stack_push_if (parser, macro == NULL);
337 }
338| ELIF expression NEWLINE {
339 _glcpp_parser_skip_stack_change_if (parser, "#elif", $2);
340 }
341| ELSE {
342 _glcpp_parser_skip_stack_change_if (parser, "else", 1);
343 }
344| ENDIF {
345 _glcpp_parser_skip_stack_pop (parser);
346 }
Carl Wortha807fb72010-05-18 22:10:04 -0700347| UNDEF IDENTIFIER {
348 string_list_t *macro = hash_table_find (parser->defines, $2);
349 if (macro) {
Carl Worthfcbbb462010-05-13 09:36:23 -0700350 /* XXX: Need hash table to support a real way
351 * to remove an element rather than prefixing
352 * a new node with data of NULL like this. */
353 hash_table_insert (parser->defines, NULL, $2);
Carl Wortha807fb72010-05-18 22:10:04 -0700354 talloc_free (macro);
Carl Worthfcbbb462010-05-13 09:36:23 -0700355 }
356 talloc_free ($2);
357 }
Carl Worth38bd27b2010-05-14 12:05:37 -0700358;
359
Carl Worthb20d33c2010-05-20 22:27:07 -0700360expression:
361 INTEGER {
362 $$ = $1;
363 }
Carl Worthbcbd5872010-05-24 10:37:38 -0700364| expression OR expression {
365 $$ = $1 || $3;
366 }
367| expression AND expression {
368 $$ = $1 && $3;
369 }
370| expression '|' expression {
371 $$ = $1 | $3;
372 }
373| expression '^' expression {
374 $$ = $1 ^ $3;
375 }
376| expression '&' expression {
377 $$ = $1 & $3;
378 }
379| expression NOT_EQUAL expression {
380 $$ = $1 != $3;
381 }
382| expression EQUAL expression {
383 $$ = $1 == $3;
384 }
385| expression GREATER_OR_EQUAL expression {
386 $$ = $1 >= $3;
387 }
388| expression LESS_OR_EQUAL expression {
389 $$ = $1 <= $3;
390 }
391| expression '>' expression {
392 $$ = $1 > $3;
393 }
394| expression '<' expression {
395 $$ = $1 < $3;
396 }
397| expression RIGHT_SHIFT expression {
398 $$ = $1 >> $3;
399 }
400| expression LEFT_SHIFT expression {
401 $$ = $1 << $3;
402 }
403| expression '-' expression {
404 $$ = $1 - $3;
405 }
406| expression '+' expression {
407 $$ = $1 + $3;
408 }
409| expression '%' expression {
410 $$ = $1 % $3;
411 }
412| expression '/' expression {
413 $$ = $1 / $3;
414 }
415| expression '*' expression {
416 $$ = $1 * $3;
417 }
418| '!' expression %prec UNARY {
419 $$ = ! $2;
420 }
421| '~' expression %prec UNARY {
422 $$ = ~ $2;
423 }
424| '-' expression %prec UNARY {
425 $$ = - $2;
426 }
427| '+' expression %prec UNARY {
428 $$ = + $2;
429 }
430| DEFINED IDENTIFIER %prec UNARY {
431 string_list_t *macro = hash_table_find (parser->defines, $2);
432 talloc_free ($2);
433 if (macro)
434 $$ = 1;
435 else
436 $$ = 0;
437 }
438| '(' expression ')' {
439 $$ = $2;
440 }
Carl Worthb20d33c2010-05-20 22:27:07 -0700441;
442
Carl Worthfcbbb462010-05-13 09:36:23 -0700443parameter_list:
444 /* empty */ {
Carl Worth610053b2010-05-14 10:05:11 -0700445 $$ = _string_list_create (parser);
Carl Worthfcbbb462010-05-13 09:36:23 -0700446 }
Carl Wortha807fb72010-05-18 22:10:04 -0700447| IDENTIFIER {
Carl Worth610053b2010-05-14 10:05:11 -0700448 $$ = _string_list_create (parser);
449 _string_list_append_item ($$, $1);
Carl Worthfcbbb462010-05-13 09:36:23 -0700450 talloc_free ($1);
451 }
Carl Wortha807fb72010-05-18 22:10:04 -0700452| parameter_list ',' IDENTIFIER {
Carl Worth610053b2010-05-14 10:05:11 -0700453 _string_list_append_item ($1, $3);
Carl Worthfcbbb462010-05-13 09:36:23 -0700454 talloc_free ($3);
455 $$ = $1;
456 }
457;
458
Carl Worthaaa9acb2010-05-19 13:28:24 -0700459replacement_list:
460 /* empty */ {
Carl Worth47252442010-05-19 13:54:37 -0700461 $$ = _token_list_create (parser);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700462 }
463| pp_tokens {
464 $$ = $1;
465 }
466;
467
468
469pp_tokens:
470 TOKEN {
Carl Worth47252442010-05-19 13:54:37 -0700471 $$ = _token_list_create (parser);
Carl Worthb5693832010-05-20 08:01:44 -0700472 _token_list_append ($$, $1.type, $1.value);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700473 }
474| pp_tokens TOKEN {
Carl Worthb5693832010-05-20 08:01:44 -0700475 _token_list_append ($1, $2.type, $2.value);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700476 $$ = $1;
477 }
478;
479
Carl Worth33cc4002010-05-12 12:17:10 -0700480%%
481
Carl Worth610053b2010-05-14 10:05:11 -0700482string_list_t *
483_string_list_create (void *ctx)
Carl Worth33cc4002010-05-12 12:17:10 -0700484{
Carl Worth610053b2010-05-14 10:05:11 -0700485 string_list_t *list;
Carl Worth33cc4002010-05-12 12:17:10 -0700486
Carl Worth610053b2010-05-14 10:05:11 -0700487 list = xtalloc (ctx, string_list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700488 list->head = NULL;
489 list->tail = NULL;
490
491 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700492}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700493
Carl Worth33cc4002010-05-12 12:17:10 -0700494void
Carl Worth610053b2010-05-14 10:05:11 -0700495_string_list_append_list (string_list_t *list, string_list_t *tail)
Carl Worthfcbbb462010-05-13 09:36:23 -0700496{
497 if (list->head == NULL) {
498 list->head = tail->head;
499 } else {
500 list->tail->next = tail->head;
501 }
502
503 list->tail = tail->tail;
504}
505
506void
Carl Worth610053b2010-05-14 10:05:11 -0700507_string_list_append_item (string_list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700508{
Carl Worth610053b2010-05-14 10:05:11 -0700509 string_node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700510
Carl Worth610053b2010-05-14 10:05:11 -0700511 node = xtalloc (list, string_node_t);
Carl Worth5070a202010-05-12 12:45:33 -0700512 node->str = xtalloc_strdup (node, str);
Carl Worth33cc4002010-05-12 12:17:10 -0700513
514 node->next = NULL;
515
516 if (list->head == NULL) {
517 list->head = node;
518 } else {
519 list->tail->next = node;
520 }
521
522 list->tail = node;
523}
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700524
525int
Carl Worth610053b2010-05-14 10:05:11 -0700526_string_list_contains (string_list_t *list, const char *member, int *index)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700527{
Carl Worth610053b2010-05-14 10:05:11 -0700528 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700529 int i;
530
531 if (list == NULL)
532 return 0;
533
534 for (i = 0, node = list->head; node; i++, node = node->next) {
535 if (strcmp (node->str, member) == 0) {
Carl Worth420d05a2010-05-17 10:15:23 -0700536 if (index)
537 *index = i;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700538 return 1;
539 }
540 }
541
542 return 0;
543}
544
545int
Carl Worth610053b2010-05-14 10:05:11 -0700546_string_list_length (string_list_t *list)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700547{
548 int length = 0;
Carl Worth610053b2010-05-14 10:05:11 -0700549 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700550
551 if (list == NULL)
552 return 0;
553
554 for (node = list->head; node; node = node->next)
555 length++;
556
557 return length;
558}
559
Carl Worth8f6a8282010-05-14 10:44:19 -0700560argument_list_t *
561_argument_list_create (void *ctx)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700562{
Carl Worth8f6a8282010-05-14 10:44:19 -0700563 argument_list_t *list;
564
565 list = xtalloc (ctx, argument_list_t);
566 list->head = NULL;
567 list->tail = NULL;
568
569 return list;
570}
571
572void
Carl Worth47252442010-05-19 13:54:37 -0700573_argument_list_append (argument_list_t *list, token_list_t *argument)
Carl Worth8f6a8282010-05-14 10:44:19 -0700574{
575 argument_node_t *node;
576
577 if (argument == NULL || argument->head == NULL)
578 return;
579
580 node = xtalloc (list, argument_node_t);
581 node->argument = argument;
582
583 node->next = NULL;
584
585 if (list->head == NULL) {
586 list->head = node;
587 } else {
588 list->tail->next = node;
589 }
590
591 list->tail = node;
592}
593
594int
595_argument_list_length (argument_list_t *list)
596{
597 int length = 0;
598 argument_node_t *node;
599
600 if (list == NULL)
601 return 0;
602
603 for (node = list->head; node; node = node->next)
604 length++;
605
606 return length;
607}
608
Carl Worth47252442010-05-19 13:54:37 -0700609token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -0700610_argument_list_member_at (argument_list_t *list, int index)
611{
612 argument_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700613 int i;
614
615 if (list == NULL)
616 return NULL;
617
618 node = list->head;
619 for (i = 0; i < index; i++) {
620 node = node->next;
621 if (node == NULL)
622 break;
623 }
624
625 if (node)
Carl Worth8f6a8282010-05-14 10:44:19 -0700626 return node->argument;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700627
628 return NULL;
629}
Carl Worth47252442010-05-19 13:54:37 -0700630
631token_list_t *
632_token_list_create (void *ctx)
633{
634 token_list_t *list;
635
636 list = xtalloc (ctx, token_list_t);
637 list->head = NULL;
638 list->tail = NULL;
639
640 return list;
641}
642
643void
644_token_list_append (token_list_t *list, int type, const char *value)
645{
646 token_node_t *node;
647
648 node = xtalloc (list, token_node_t);
649 node->type = type;
650 node->value = xtalloc_strdup (list, value);
651
652 node->next = NULL;
653
654 if (list->head == NULL) {
655 list->head = node;
656 } else {
657 list->tail->next = node;
658 }
659
660 list->tail = node;
661}
662
663void
664_token_list_append_list (token_list_t *list, token_list_t *tail)
665{
666 if (list->head == NULL) {
667 list->head = tail->head;
668 } else {
669 list->tail->next = tail->head;
670 }
671
672 list->tail = tail->tail;
673}
Carl Worth33cc4002010-05-12 12:17:10 -0700674
Carl Worth3a37b872010-05-10 11:44:09 -0700675void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700676yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700677{
678 fprintf (stderr, "Parse error: %s\n", error);
679}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700680
Carl Worth33cc4002010-05-12 12:17:10 -0700681glcpp_parser_t *
682glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700683{
Carl Worth33cc4002010-05-12 12:17:10 -0700684 glcpp_parser_t *parser;
685
Carl Worth5070a202010-05-12 12:45:33 -0700686 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700687
Carl Worth8f38aff2010-05-19 10:01:29 -0700688 glcpp_lex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700689 parser->defines = hash_table_ctor (32, hash_table_string_hash,
690 hash_table_string_compare);
Carl Wortha807fb72010-05-18 22:10:04 -0700691 parser->expansions = NULL;
692
Carl Worth5a6b9a22010-05-20 14:29:43 -0700693 parser->just_printed_separator = 1;
Carl Worth876e5102010-05-20 14:38:06 -0700694 parser->need_newline = 0;
Carl Worth5a6b9a22010-05-20 14:29:43 -0700695
Carl Worthb20d33c2010-05-20 22:27:07 -0700696 parser->skip_stack = NULL;
697
Carl Worth33cc4002010-05-12 12:17:10 -0700698 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700699}
700
701int
702glcpp_parser_parse (glcpp_parser_t *parser)
703{
704 return yyparse (parser);
705}
706
707void
Carl Worth33cc4002010-05-12 12:17:10 -0700708glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700709{
Carl Worth876e5102010-05-20 14:38:06 -0700710 if (parser->need_newline)
711 printf ("\n");
Carl Worthb20d33c2010-05-20 22:27:07 -0700712 if (parser->skip_stack)
713 fprintf (stderr, "Error: Unterminated #if\n");
Carl Worth8f38aff2010-05-19 10:01:29 -0700714 glcpp_lex_destroy (parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700715 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700716 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700717}
Carl Worthc6d5af32010-05-11 12:30:09 -0700718
Carl Worthbe0e2e92010-05-19 07:29:22 -0700719static int
720glcpp_parser_is_expanding (glcpp_parser_t *parser, const char *member)
721{
722 expansion_node_t *node;
723
724 for (node = parser->expansions; node; node = node->next) {
725 if (node->macro &&
726 strcmp (node->macro->identifier, member) == 0)
727 {
728 return 1;
729 }
730 }
731
732 return 0;
733}
734
Carl Wortha807fb72010-05-18 22:10:04 -0700735token_class_t
736glcpp_parser_classify_token (glcpp_parser_t *parser,
737 const char *identifier,
738 int *parameter_index)
Carl Worth9f62a7e2010-05-13 07:38:29 -0700739{
Carl Worthfcbbb462010-05-13 09:36:23 -0700740 macro_t *macro;
741
Carl Worthc10a51b2010-05-20 15:15:26 -0700742 /* Is this token a defined macro? */
Carl Worthfcbbb462010-05-13 09:36:23 -0700743 macro = hash_table_find (parser->defines, identifier);
744
745 if (macro == NULL)
Carl Wortha807fb72010-05-18 22:10:04 -0700746 return TOKEN_CLASS_IDENTIFIER;
Carl Worthfcbbb462010-05-13 09:36:23 -0700747
Carl Worthbe0e2e92010-05-19 07:29:22 -0700748 /* Don't consider this a macro if we are already actively
749 * expanding this macro. */
750 if (glcpp_parser_is_expanding (parser, identifier))
Carl Worthb5693832010-05-20 08:01:44 -0700751 return TOKEN_CLASS_IDENTIFIER_FINALIZED;
Carl Worthbe0e2e92010-05-19 07:29:22 -0700752
753 /* Definitely a macro. Just need to check if it's function-like. */
Carl Worthfcbbb462010-05-13 09:36:23 -0700754 if (macro->is_function)
Carl Wortha807fb72010-05-18 22:10:04 -0700755 return TOKEN_CLASS_FUNC_MACRO;
Carl Worthfcbbb462010-05-13 09:36:23 -0700756 else
Carl Wortha807fb72010-05-18 22:10:04 -0700757 return TOKEN_CLASS_OBJ_MACRO;
Carl Worth9f62a7e2010-05-13 07:38:29 -0700758}
759
Carl Worth33cc4002010-05-12 12:17:10 -0700760void
Carl Worthfcbbb462010-05-13 09:36:23 -0700761_define_object_macro (glcpp_parser_t *parser,
762 const char *identifier,
Carl Worth47252442010-05-19 13:54:37 -0700763 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700764{
765 macro_t *macro;
766
767 macro = xtalloc (parser, macro_t);
768
769 macro->is_function = 0;
Carl Worthc5e98552010-05-14 10:12:21 -0700770 macro->parameters = NULL;
Carl Wortha807fb72010-05-18 22:10:04 -0700771 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700772 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700773
774 hash_table_insert (parser->defines, macro, identifier);
775}
776
777void
778_define_function_macro (glcpp_parser_t *parser,
779 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -0700780 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -0700781 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700782{
783 macro_t *macro;
784
785 macro = xtalloc (parser, macro_t);
786
787 macro->is_function = 1;
Carl Worthc5e98552010-05-14 10:12:21 -0700788 macro->parameters = talloc_steal (macro, parameters);
Carl Wortha807fb72010-05-18 22:10:04 -0700789 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700790 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700791
792 hash_table_insert (parser->defines, macro, identifier);
793}
794
Carl Wortha807fb72010-05-18 22:10:04 -0700795static void
Carl Worthc10a51b2010-05-20 15:15:26 -0700796_glcpp_parser_push_expansion (glcpp_parser_t *parser,
797 macro_t *macro,
798 token_node_t *replacements)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700799{
Carl Wortha807fb72010-05-18 22:10:04 -0700800 expansion_node_t *node;
801
802 node = xtalloc (parser, expansion_node_t);
803
804 node->macro = macro;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700805 node->replacements = replacements;
Carl Wortha807fb72010-05-18 22:10:04 -0700806
807 node->next = parser->expansions;
808 parser->expansions = node;
Carl Wortha807fb72010-05-18 22:10:04 -0700809}
810
Carl Worthaaa9acb2010-05-19 13:28:24 -0700811static void
Carl Wortha807fb72010-05-18 22:10:04 -0700812glcpp_parser_pop_expansion (glcpp_parser_t *parser)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700813{
Carl Wortha807fb72010-05-18 22:10:04 -0700814 expansion_node_t *node;
Carl Worth420d05a2010-05-17 10:15:23 -0700815
Carl Wortha807fb72010-05-18 22:10:04 -0700816 node = parser->expansions;
Carl Worth420d05a2010-05-17 10:15:23 -0700817
Carl Wortha807fb72010-05-18 22:10:04 -0700818 if (node == NULL) {
819 fprintf (stderr, "Internal error: _expansion_list_pop called on an empty list.\n");
820 exit (1);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700821 }
822
Carl Wortha807fb72010-05-18 22:10:04 -0700823 parser->expansions = node->next;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700824
Carl Wortha807fb72010-05-18 22:10:04 -0700825 talloc_free (node);
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700826}
827
Carl Wortha807fb72010-05-18 22:10:04 -0700828void
Carl Worth2be8be02010-05-14 10:31:43 -0700829_expand_object_macro (glcpp_parser_t *parser, const char *identifier)
Carl Worth33cc4002010-05-12 12:17:10 -0700830{
Carl Worthfcbbb462010-05-13 09:36:23 -0700831 macro_t *macro;
Carl Worth33cc4002010-05-12 12:17:10 -0700832
Carl Worthfcbbb462010-05-13 09:36:23 -0700833 macro = hash_table_find (parser->defines, identifier);
834 assert (! macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700835 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700836
Carl Worthc10a51b2010-05-20 15:15:26 -0700837 _glcpp_parser_push_expansion (parser, macro, macro->replacements->head);
Carl Worthfcbbb462010-05-13 09:36:23 -0700838}
839
Carl Wortha807fb72010-05-18 22:10:04 -0700840void
Carl Worth2be8be02010-05-14 10:31:43 -0700841_expand_function_macro (glcpp_parser_t *parser,
842 const char *identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700843 argument_list_t *arguments)
Carl Worthfcbbb462010-05-13 09:36:23 -0700844{
Carl Worthfcbbb462010-05-13 09:36:23 -0700845 macro_t *macro;
Carl Worthc10a51b2010-05-20 15:15:26 -0700846 token_list_t *expanded;
847 token_node_t *i, *j;
848 int parameter_index;
Carl Worthfcbbb462010-05-13 09:36:23 -0700849
850 macro = hash_table_find (parser->defines, identifier);
851 assert (macro->is_function);
Carl Worthbe0e2e92010-05-19 07:29:22 -0700852 assert (! glcpp_parser_is_expanding (parser, identifier));
Carl Worthfcbbb462010-05-13 09:36:23 -0700853
Carl Worth8f6a8282010-05-14 10:44:19 -0700854 if (_argument_list_length (arguments) !=
Carl Worth2be8be02010-05-14 10:31:43 -0700855 _string_list_length (macro->parameters))
856 {
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700857 fprintf (stderr,
858 "Error: macro %s invoked with %d arguments (expected %d)\n",
859 identifier,
Carl Worth8f6a8282010-05-14 10:44:19 -0700860 _argument_list_length (arguments),
Carl Worthc5e98552010-05-14 10:12:21 -0700861 _string_list_length (macro->parameters));
Carl Wortha807fb72010-05-18 22:10:04 -0700862 return;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700863 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700864
Carl Worthc10a51b2010-05-20 15:15:26 -0700865 expanded = _token_list_create (macro);
866
867 for (i = macro->replacements->head; i; i = i->next) {
868 if (_string_list_contains (macro->parameters, i->value,
869 &parameter_index))
870 {
871 token_list_t *argument;
872 argument = _argument_list_member_at (arguments,
873 parameter_index);
874 for (j = argument->head; j; j = j->next)
875 {
876 _token_list_append (expanded, j->type,
877 j->value);
878 }
879 } else {
880 _token_list_append (expanded, i->type, i->value);
881 }
882 }
883
884 _glcpp_parser_push_expansion (parser, macro, expanded->head);
Carl Worth33cc4002010-05-12 12:17:10 -0700885}
Carl Worth8f38aff2010-05-19 10:01:29 -0700886
887static int
Carl Worth0293b2e2010-05-19 10:05:40 -0700888glcpp_parser_lex (glcpp_parser_t *parser)
Carl Worth8f38aff2010-05-19 10:01:29 -0700889{
Carl Worthaaa9acb2010-05-19 13:28:24 -0700890 expansion_node_t *expansion;
Carl Worth47252442010-05-19 13:54:37 -0700891 token_node_t *replacements;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700892 int parameter_index;
Carl Worthd8327e52010-05-20 15:18:54 -0700893 const char *token;
894 token_class_t class;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700895
896 /* Who says C can't do efficient tail recursion? */
897 RECURSE:
898
899 expansion = parser->expansions;
900
901 if (expansion == NULL)
902 return glcpp_lex (parser->scanner);
903
904 replacements = expansion->replacements;
905
906 /* Pop expansion when replacements is exhausted. */
907 if (replacements == NULL) {
908 glcpp_parser_pop_expansion (parser);
909 goto RECURSE;
910 }
911
912 expansion->replacements = replacements->next;
913
Carl Worthd8327e52010-05-20 15:18:54 -0700914 token = replacements->value;
915
916 /* Implement token pasting. */
917 if (replacements->next && strcmp (replacements->next->value, "##") == 0) {
918 token_node_t *next_node;
919
920 next_node = replacements->next->next;
921
922 if (next_node == NULL) {
923 fprintf (stderr, "Error: '##' cannot appear at the end of a macro expansion.\n");
924 exit (1);
925 }
926
927 token = xtalloc_asprintf (parser, "%s%s",
928 token, next_node->value);
929 expansion->replacements = next_node->next;
930 }
931
932
933 if (strcmp (token, "(") == 0)
Carl Worthaaa9acb2010-05-19 13:28:24 -0700934 return '(';
Carl Worthd8327e52010-05-20 15:18:54 -0700935 else if (strcmp (token, ")") == 0)
Carl Worthaaa9acb2010-05-19 13:28:24 -0700936 return ')';
Carl Worthaaa9acb2010-05-19 13:28:24 -0700937
Carl Worthd8327e52010-05-20 15:18:54 -0700938 yylval.str = xtalloc_strdup (parser, token);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700939
Carl Worthb5693832010-05-20 08:01:44 -0700940 /* Carefully refuse to expand any finalized identifier. */
941 if (replacements->type == IDENTIFIER_FINALIZED)
942 return IDENTIFIER_FINALIZED;
943
Carl Worthaaa9acb2010-05-19 13:28:24 -0700944 switch (glcpp_parser_classify_token (parser, yylval.str,
945 &parameter_index))
946 {
Carl Worthaaa9acb2010-05-19 13:28:24 -0700947 case TOKEN_CLASS_IDENTIFIER:
948 return IDENTIFIER;
949 break;
Carl Worthb5693832010-05-20 08:01:44 -0700950 case TOKEN_CLASS_IDENTIFIER_FINALIZED:
951 return IDENTIFIER_FINALIZED;
952 break;
Carl Worthaaa9acb2010-05-19 13:28:24 -0700953 case TOKEN_CLASS_FUNC_MACRO:
954 return FUNC_MACRO;
955 break;
956 default:
957 case TOKEN_CLASS_OBJ_MACRO:
958 return OBJ_MACRO;
959 break;
960 }
Carl Worth8f38aff2010-05-19 10:01:29 -0700961}
Carl Worthb20d33c2010-05-20 22:27:07 -0700962
963static void
964_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition)
965{
966 skip_type_t current = SKIP_NO_SKIP;
967 skip_node_t *node;
968
969 if (parser->skip_stack)
970 current = parser->skip_stack->type;
971
972 node = xtalloc (parser, skip_node_t);
973
974 if (current == SKIP_NO_SKIP) {
975 if (condition)
976 node->type = SKIP_NO_SKIP;
977 else
978 node->type = SKIP_TO_ELSE;
979 } else {
980 node->type = SKIP_TO_ENDIF;
981 }
982
983 node->next = parser->skip_stack;
984 parser->skip_stack = node;
985}
986
987static void
988_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
989 int condition)
990{
991 if (parser->skip_stack == NULL) {
992 fprintf (stderr, "Error: %s without #if\n", type);
993 exit (1);
994 }
995
996 if (parser->skip_stack->type == SKIP_TO_ELSE) {
997 if (condition)
998 parser->skip_stack->type = SKIP_NO_SKIP;
999 } else {
1000 parser->skip_stack->type = SKIP_TO_ENDIF;
1001 }
1002}
1003
1004static void
1005_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser)
1006{
1007 skip_node_t *node;
1008
1009 if (parser->skip_stack == NULL) {
1010 fprintf (stderr, "Error: #endif without #if\n");
1011 exit (1);
1012 }
1013
1014 node = parser->skip_stack;
1015 parser->skip_stack = node->next;
1016 talloc_free (node);
1017}