blob: 330d3ab3bc4da375a632d017c9c230b2684026a3 [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 Worth5aa7ea02010-05-25 18:39:43 -070031static void
Carl Wortha1e32bc2010-05-10 13:17:25 -070032yyerror (void *scanner, const char *error);
Carl Worth3a37b872010-05-10 11:44:09 -070033
Carl Worth5aa7ea02010-05-25 18:39:43 -070034static void
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
Carl Worth5aa7ea02010-05-25 18:39:43 -070039static void
Carl Worthfcbbb462010-05-13 09:36:23 -070040_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 Worth5aa7ea02010-05-25 18:39:43 -070045static string_list_t *
Carl Worth610053b2010-05-14 10:05:11 -070046_string_list_create (void *ctx);
Carl Worth33cc4002010-05-12 12:17:10 -070047
Carl Worth5aa7ea02010-05-25 18:39:43 -070048static void
Carl Worth610053b2010-05-14 10:05:11 -070049_string_list_append_item (string_list_t *list, const char *str);
Carl Worthfcbbb462010-05-13 09:36:23 -070050
Carl Worth5aa7ea02010-05-25 18:39:43 -070051static void
Carl Worth610053b2010-05-14 10:05:11 -070052_string_list_append_list (string_list_t *list, string_list_t *tail);
Carl Worthc6d5af32010-05-11 12:30:09 -070053
Carl Worth5aa7ea02010-05-25 18:39:43 -070054static void
Carl Worthae6517f2010-05-25 15:24:59 -070055_string_list_push (string_list_t *list, const char *str);
56
Carl Worth5aa7ea02010-05-25 18:39:43 -070057static void
Carl Worthae6517f2010-05-25 15:24:59 -070058_string_list_pop (string_list_t *list);
59
Carl Worth5aa7ea02010-05-25 18:39:43 -070060static int
Carl Worth610053b2010-05-14 10:05:11 -070061_string_list_contains (string_list_t *list, const char *member, int *index);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070062
Carl Worth5aa7ea02010-05-25 18:39:43 -070063static int
Carl Worth610053b2010-05-14 10:05:11 -070064_string_list_length (string_list_t *list);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070065
Carl Worth5aa7ea02010-05-25 18:39:43 -070066static argument_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -070067_argument_list_create (void *ctx);
68
Carl Worth5aa7ea02010-05-25 18:39:43 -070069static void
Carl Worth47252442010-05-19 13:54:37 -070070_argument_list_append (argument_list_t *list, token_list_t *argument);
Carl Worth8f6a8282010-05-14 10:44:19 -070071
Carl Worth5aa7ea02010-05-25 18:39:43 -070072static int
Carl Worth8f6a8282010-05-14 10:44:19 -070073_argument_list_length (argument_list_t *list);
74
Carl Worth5aa7ea02010-05-25 18:39:43 -070075static token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -070076_argument_list_member_at (argument_list_t *list, int index);
77
Carl Worth808401f2010-05-25 14:52:43 -070078/* Note: This function talloc_steal()s the str pointer. */
Carl Worth5aa7ea02010-05-25 18:39:43 -070079static token_t *
Carl Worth808401f2010-05-25 14:52:43 -070080_token_create_str (void *ctx, int type, char *str);
81
Carl Worth5aa7ea02010-05-25 18:39:43 -070082static token_t *
Carl Worth808401f2010-05-25 14:52:43 -070083_token_create_ival (void *ctx, int type, int ival);
84
Carl Worth5aa7ea02010-05-25 18:39:43 -070085static token_list_t *
Carl Worth47252442010-05-19 13:54:37 -070086_token_list_create (void *ctx);
87
Carl Worthb1ae61a2010-05-26 08:10:38 -070088/* Note: This function adds a talloc_reference() to token.
Carl Worth808401f2010-05-25 14:52:43 -070089 *
90 * You may want to talloc_unlink any current reference if you no
91 * longer need it. */
Carl Worth5aa7ea02010-05-25 18:39:43 -070092static void
Carl Worth808401f2010-05-25 14:52:43 -070093_token_list_append (token_list_t *list, token_t *token);
Carl Worth47252442010-05-19 13:54:37 -070094
Carl Worth5aa7ea02010-05-25 18:39:43 -070095static void
Carl Worth47252442010-05-19 13:54:37 -070096_token_list_append_list (token_list_t *list, token_list_t *tail);
97
Carl Worth5aa7ea02010-05-25 18:39:43 -070098static void
Carl Worthae6517f2010-05-25 15:24:59 -070099_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
100 token_list_t *list);
Carl Worth808401f2010-05-25 14:52:43 -0700101
Carl Worthaaa9acb2010-05-19 13:28:24 -0700102static void
Carl Worth0197e9b2010-05-26 08:05:19 -0700103_glcpp_parser_expand_token_list_onto (glcpp_parser_t *parser,
104 token_list_t *list,
105 token_list_t *result);
106
107static void
Carl Worthb20d33c2010-05-20 22:27:07 -0700108_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition);
109
110static void
111_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
112 int condition);
Carl Worth80dc60b2010-05-25 14:42:00 -0700113
Carl Worthb20d33c2010-05-20 22:27:07 -0700114static void
115_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser);
116
Carl Worth0293b2e2010-05-19 10:05:40 -0700117#define yylex glcpp_parser_lex
118
Carl Worth8f38aff2010-05-19 10:01:29 -0700119static int
Carl Worth0293b2e2010-05-19 10:05:40 -0700120glcpp_parser_lex (glcpp_parser_t *parser);
Carl Worth8f38aff2010-05-19 10:01:29 -0700121
Carl Worth3a37b872010-05-10 11:44:09 -0700122%}
123
Carl Worth0b27b5f2010-05-10 16:16:06 -0700124%parse-param {glcpp_parser_t *parser}
Carl Worth0293b2e2010-05-19 10:05:40 -0700125%lex-param {glcpp_parser_t *parser}
Carl Worth38aa8352010-05-10 11:52:29 -0700126
Carl Worthb1854fd2010-05-25 16:28:26 -0700127%token HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_UNDEF IDENTIFIER NEWLINE OTHER SPACE
Carl Worth3ff81672010-05-25 13:09:03 -0700128%token LEFT_SHIFT RIGHT_SHIFT LESS_OR_EQUAL GREATER_OR_EQUAL EQUAL NOT_EQUAL AND OR PASTE
Carl Worthe9397862010-05-25 17:08:07 -0700129%type <ival> punctuator SPACE
130%type <str> IDENTIFIER OTHER
Carl Worthb1854fd2010-05-25 16:28:26 -0700131%type <string_list> identifier_list
Carl Worth808401f2010-05-25 14:52:43 -0700132%type <token> preprocessing_token
133%type <token_list> pp_tokens replacement_list text_line
Carl Worth3a37b872010-05-10 11:44:09 -0700134
135%%
136
Carl Worth33cc4002010-05-12 12:17:10 -0700137input:
Carl Worth3ff81672010-05-25 13:09:03 -0700138 /* empty */
Carl Worthae6517f2010-05-25 15:24:59 -0700139| input line {
140 printf ("\n");
141 }
Carl Worth3a37b872010-05-10 11:44:09 -0700142;
143
Carl Worth3ff81672010-05-25 13:09:03 -0700144line:
145 control_line
Carl Worth808401f2010-05-25 14:52:43 -0700146| text_line {
Carl Worthae6517f2010-05-25 15:24:59 -0700147 _glcpp_parser_print_expanded_token_list (parser, $1);
Carl Worth808401f2010-05-25 14:52:43 -0700148 talloc_free ($1);
149 }
Carl Worth3ff81672010-05-25 13:09:03 -0700150| HASH non_directive
Carl Worthcd27e642010-05-12 13:11:50 -0700151;
152
Carl Worth3ff81672010-05-25 13:09:03 -0700153control_line:
Carl Worthf34a0002010-05-25 16:59:02 -0700154 HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
Carl Worthae6517f2010-05-25 15:24:59 -0700155 _define_object_macro (parser, $2, $3);
156 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700157| HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
158 _define_function_macro (parser, $2, NULL, $5);
159 }
160| HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
161 _define_function_macro (parser, $2, $4, $6);
162 }
Carl Worthe6fb7822010-05-25 15:28:58 -0700163| HASH_UNDEF IDENTIFIER NEWLINE {
164 string_list_t *macro = hash_table_find (parser->defines, $2);
165 if (macro) {
166 /* XXX: Need hash table to support a real way
167 * to remove an element rather than prefixing
168 * a new node with data of NULL like this. */
169 hash_table_insert (parser->defines, NULL, $2);
170 talloc_free (macro);
171 }
172 talloc_free ($2);
173 }
Carl Worth3ff81672010-05-25 13:09:03 -0700174| HASH NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700175;
176
Carl Worth3ff81672010-05-25 13:09:03 -0700177identifier_list:
Carl Worthb1854fd2010-05-25 16:28:26 -0700178 IDENTIFIER {
179 $$ = _string_list_create (parser);
180 _string_list_append_item ($$, $1);
181 talloc_steal ($$, $1);
182 }
183| identifier_list ',' IDENTIFIER {
184 $$ = $1;
185 _string_list_append_item ($$, $3);
186 talloc_steal ($$, $3);
187 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700188;
189
Carl Worth3ff81672010-05-25 13:09:03 -0700190text_line:
Carl Worth808401f2010-05-25 14:52:43 -0700191 NEWLINE { $$ = NULL; }
Carl Worth3ff81672010-05-25 13:09:03 -0700192| pp_tokens NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700193;
194
Carl Worth3ff81672010-05-25 13:09:03 -0700195non_directive:
196 pp_tokens NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700197;
198
Carl Worthaaa9acb2010-05-19 13:28:24 -0700199replacement_list:
Carl Worth808401f2010-05-25 14:52:43 -0700200 /* empty */ { $$ = NULL; }
Carl Worth3ff81672010-05-25 13:09:03 -0700201| pp_tokens
Carl Worthaaa9acb2010-05-19 13:28:24 -0700202;
203
Carl Worthaaa9acb2010-05-19 13:28:24 -0700204pp_tokens:
Carl Worth808401f2010-05-25 14:52:43 -0700205 preprocessing_token {
Carl Worthf34a0002010-05-25 16:59:02 -0700206 parser->space_tokens = 1;
Carl Worth808401f2010-05-25 14:52:43 -0700207 $$ = _token_list_create (parser);
208 _token_list_append ($$, $1);
209 talloc_unlink (parser, $1);
210 }
211| pp_tokens preprocessing_token {
212 $$ = $1;
213 _token_list_append ($$, $2);
214 talloc_unlink (parser, $2);
215 }
Carl Worthaaa9acb2010-05-19 13:28:24 -0700216;
217
Carl Worth3ff81672010-05-25 13:09:03 -0700218preprocessing_token:
Carl Worth808401f2010-05-25 14:52:43 -0700219 IDENTIFIER {
220 $$ = _token_create_str (parser, IDENTIFIER, $1);
221 }
222| punctuator {
223 $$ = _token_create_ival (parser, $1, $1);
224 }
225| OTHER {
226 $$ = _token_create_str (parser, OTHER, $1);
227 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700228| SPACE {
Carl Worthe9397862010-05-25 17:08:07 -0700229 $$ = _token_create_ival (parser, SPACE, SPACE);
Carl Worthb1854fd2010-05-25 16:28:26 -0700230 }
Carl Worth3ff81672010-05-25 13:09:03 -0700231;
232
233punctuator:
Carl Worth808401f2010-05-25 14:52:43 -0700234 '[' { $$ = '['; }
235| ']' { $$ = ']'; }
236| '(' { $$ = '('; }
237| ')' { $$ = ')'; }
238| '{' { $$ = '{'; }
239| '}' { $$ = '}'; }
240| '.' { $$ = '.'; }
241| '&' { $$ = '&'; }
242| '*' { $$ = '*'; }
243| '+' { $$ = '+'; }
244| '-' { $$ = '-'; }
245| '~' { $$ = '~'; }
246| '!' { $$ = '!'; }
247| '/' { $$ = '/'; }
248| '%' { $$ = '%'; }
249| LEFT_SHIFT { $$ = LEFT_SHIFT; }
250| RIGHT_SHIFT { $$ = RIGHT_SHIFT; }
251| '<' { $$ = '<'; }
252| '>' { $$ = '>'; }
253| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; }
254| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; }
255| EQUAL { $$ = EQUAL; }
256| NOT_EQUAL { $$ = NOT_EQUAL; }
257| '^' { $$ = '^'; }
258| '|' { $$ = '|'; }
259| AND { $$ = AND; }
260| OR { $$ = OR; }
261| ';' { $$ = ';'; }
262| ',' { $$ = ','; }
263| PASTE { $$ = PASTE; }
Carl Worth3ff81672010-05-25 13:09:03 -0700264;
265
Carl Worth33cc4002010-05-12 12:17:10 -0700266%%
267
Carl Worth610053b2010-05-14 10:05:11 -0700268string_list_t *
269_string_list_create (void *ctx)
Carl Worth33cc4002010-05-12 12:17:10 -0700270{
Carl Worth610053b2010-05-14 10:05:11 -0700271 string_list_t *list;
Carl Worth33cc4002010-05-12 12:17:10 -0700272
Carl Worth610053b2010-05-14 10:05:11 -0700273 list = xtalloc (ctx, string_list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700274 list->head = NULL;
275 list->tail = NULL;
276
277 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700278}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700279
Carl Worth33cc4002010-05-12 12:17:10 -0700280void
Carl Worth610053b2010-05-14 10:05:11 -0700281_string_list_append_list (string_list_t *list, string_list_t *tail)
Carl Worthfcbbb462010-05-13 09:36:23 -0700282{
283 if (list->head == NULL) {
284 list->head = tail->head;
285 } else {
286 list->tail->next = tail->head;
287 }
288
289 list->tail = tail->tail;
290}
291
292void
Carl Worth610053b2010-05-14 10:05:11 -0700293_string_list_append_item (string_list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700294{
Carl Worth610053b2010-05-14 10:05:11 -0700295 string_node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700296
Carl Worth610053b2010-05-14 10:05:11 -0700297 node = xtalloc (list, string_node_t);
Carl Worth5070a202010-05-12 12:45:33 -0700298 node->str = xtalloc_strdup (node, str);
Carl Worth80dc60b2010-05-25 14:42:00 -0700299
Carl Worth33cc4002010-05-12 12:17:10 -0700300 node->next = NULL;
301
302 if (list->head == NULL) {
303 list->head = node;
304 } else {
305 list->tail->next = node;
306 }
307
308 list->tail = node;
309}
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700310
Carl Worthae6517f2010-05-25 15:24:59 -0700311void
312_string_list_push (string_list_t *list, const char *str)
313{
314 string_node_t *node;
315
316 node = xtalloc (list, string_node_t);
317 node->str = xtalloc_strdup (node, str);
318 node->next = list->head;
319
320 if (list->tail == NULL) {
321 list->tail = node;
322 }
323 list->head = node;
324}
325
326void
327_string_list_pop (string_list_t *list)
328{
329 string_node_t *node;
330
331 node = list->head;
332
333 if (node == NULL) {
334 fprintf (stderr, "Internal error: _string_list_pop called on an empty list.\n");
335 exit (1);
336 }
337
338 list->head = node->next;
339 if (list->tail == node) {
340 assert (node->next == NULL);
341 list->tail = NULL;
342 }
343
344 talloc_free (node);
345}
346
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700347int
Carl Worth610053b2010-05-14 10:05:11 -0700348_string_list_contains (string_list_t *list, const char *member, int *index)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700349{
Carl Worth610053b2010-05-14 10:05:11 -0700350 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700351 int i;
352
353 if (list == NULL)
354 return 0;
355
356 for (i = 0, node = list->head; node; i++, node = node->next) {
357 if (strcmp (node->str, member) == 0) {
Carl Worth420d05a2010-05-17 10:15:23 -0700358 if (index)
359 *index = i;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700360 return 1;
361 }
362 }
363
364 return 0;
365}
366
367int
Carl Worth610053b2010-05-14 10:05:11 -0700368_string_list_length (string_list_t *list)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700369{
370 int length = 0;
Carl Worth610053b2010-05-14 10:05:11 -0700371 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700372
373 if (list == NULL)
374 return 0;
375
376 for (node = list->head; node; node = node->next)
377 length++;
378
379 return length;
380}
381
Carl Worth8f6a8282010-05-14 10:44:19 -0700382argument_list_t *
383_argument_list_create (void *ctx)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700384{
Carl Worth8f6a8282010-05-14 10:44:19 -0700385 argument_list_t *list;
386
387 list = xtalloc (ctx, argument_list_t);
388 list->head = NULL;
389 list->tail = NULL;
390
391 return list;
392}
393
394void
Carl Worth47252442010-05-19 13:54:37 -0700395_argument_list_append (argument_list_t *list, token_list_t *argument)
Carl Worth8f6a8282010-05-14 10:44:19 -0700396{
397 argument_node_t *node;
398
Carl Worth8f6a8282010-05-14 10:44:19 -0700399 node = xtalloc (list, argument_node_t);
400 node->argument = argument;
401
402 node->next = NULL;
403
404 if (list->head == NULL) {
405 list->head = node;
406 } else {
407 list->tail->next = node;
408 }
409
410 list->tail = node;
411}
412
413int
414_argument_list_length (argument_list_t *list)
415{
416 int length = 0;
417 argument_node_t *node;
418
419 if (list == NULL)
420 return 0;
421
422 for (node = list->head; node; node = node->next)
423 length++;
424
425 return length;
426}
427
Carl Worth47252442010-05-19 13:54:37 -0700428token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -0700429_argument_list_member_at (argument_list_t *list, int index)
430{
431 argument_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700432 int i;
433
434 if (list == NULL)
435 return NULL;
436
437 node = list->head;
438 for (i = 0; i < index; i++) {
439 node = node->next;
440 if (node == NULL)
441 break;
442 }
443
444 if (node)
Carl Worth8f6a8282010-05-14 10:44:19 -0700445 return node->argument;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700446
447 return NULL;
448}
Carl Worth47252442010-05-19 13:54:37 -0700449
Carl Worth808401f2010-05-25 14:52:43 -0700450/* Note: This function talloc_steal()s the str pointer. */
451token_t *
452_token_create_str (void *ctx, int type, char *str)
453{
454 token_t *token;
455
456 token = xtalloc (ctx, token_t);
457 token->type = type;
458 token->value.str = talloc_steal (token, str);
459
460 return token;
461}
462
463token_t *
464_token_create_ival (void *ctx, int type, int ival)
465{
466 token_t *token;
467
468 token = xtalloc (ctx, token_t);
469 token->type = type;
470 token->value.ival = ival;
471
472 return token;
473}
474
Carl Worth47252442010-05-19 13:54:37 -0700475token_list_t *
476_token_list_create (void *ctx)
477{
478 token_list_t *list;
479
480 list = xtalloc (ctx, token_list_t);
481 list->head = NULL;
482 list->tail = NULL;
Carl Worth10ae4382010-05-25 20:35:01 -0700483 list->non_space_tail = NULL;
Carl Worth47252442010-05-19 13:54:37 -0700484
485 return list;
486}
487
488void
Carl Worth808401f2010-05-25 14:52:43 -0700489_token_list_append (token_list_t *list, token_t *token)
Carl Worth47252442010-05-19 13:54:37 -0700490{
491 token_node_t *node;
492
493 node = xtalloc (list, token_node_t);
Carl Worth808401f2010-05-25 14:52:43 -0700494 node->token = xtalloc_reference (list, token);
Carl Worth47252442010-05-19 13:54:37 -0700495
496 node->next = NULL;
497
498 if (list->head == NULL) {
499 list->head = node;
500 } else {
501 list->tail->next = node;
502 }
503
504 list->tail = node;
Carl Worth10ae4382010-05-25 20:35:01 -0700505 if (token->type != SPACE)
506 list->non_space_tail = node;
Carl Worth47252442010-05-19 13:54:37 -0700507}
508
509void
510_token_list_append_list (token_list_t *list, token_list_t *tail)
511{
512 if (list->head == NULL) {
513 list->head = tail->head;
514 } else {
515 list->tail->next = tail->head;
516 }
517
518 list->tail = tail->tail;
Carl Worth10ae4382010-05-25 20:35:01 -0700519 list->non_space_tail = tail->non_space_tail;
520}
521
522void
523_token_list_trim_trailing_space (token_list_t *list)
524{
525 token_node_t *tail, *next;
526
527 if (list->non_space_tail) {
528 tail = list->non_space_tail->next;
529 list->non_space_tail->next = NULL;
530 list->tail = list->non_space_tail;
531
532 while (tail) {
533 next = tail->next;
534 talloc_free (tail);
535 tail = next;
536 }
537 }
Carl Worth47252442010-05-19 13:54:37 -0700538}
Carl Worth80dc60b2010-05-25 14:42:00 -0700539
Carl Worth0197e9b2010-05-26 08:05:19 -0700540static void
541_token_print (token_t *token)
542{
543 if (token->type < 256) {
544 printf ("%c", token->type);
545 return;
546 }
547
548 switch (token->type) {
549 case IDENTIFIER:
550 case OTHER:
551 printf ("%s", token->value.str);
552 break;
553 case SPACE:
554 printf (" ");
555 break;
556 case LEFT_SHIFT:
557 printf ("<<");
558 break;
559 case RIGHT_SHIFT:
560 printf (">>");
561 break;
562 case LESS_OR_EQUAL:
563 printf ("<=");
564 break;
565 case GREATER_OR_EQUAL:
566 printf (">=");
567 break;
568 case EQUAL:
569 printf ("==");
570 break;
571 case NOT_EQUAL:
572 printf ("!=");
573 break;
574 case AND:
575 printf ("&&");
576 break;
577 case OR:
578 printf ("||");
579 break;
580 case PASTE:
581 printf ("##");
582 break;
583 default:
584 fprintf (stderr, "Error: Don't know how to print token type %d\n", token->type);
585 break;
586 }
587}
588
Carl Worthad0dee62010-05-26 09:04:50 -0700589/* Change 'token' into a new token formed by pasting 'other'. */
590static void
591_token_paste (token_t *token, token_t *other)
592{
593 /* A very few single-character punctuators can be combined
594 * with another to form a multi-character punctuator. */
595 switch (token->type) {
596 case '<':
597 if (other->type == '<') {
598 token->type = LEFT_SHIFT;
599 token->value.ival = LEFT_SHIFT;
600 return;
601 } else if (other->type == '=') {
602 token->type = LESS_OR_EQUAL;
603 token->value.ival = LESS_OR_EQUAL;
604 return;
605 }
606 break;
607 case '>':
608 if (other->type == '>') {
609 token->type = RIGHT_SHIFT;
610 token->value.ival = RIGHT_SHIFT;
611 return;
612 } else if (other->type == '=') {
613 token->type = GREATER_OR_EQUAL;
614 token->value.ival = GREATER_OR_EQUAL;
615 return;
616 }
617 break;
618 case '=':
619 if (other->type == '=') {
620 token->type = EQUAL;
621 token->value.ival = EQUAL;
622 return;
623 }
624 break;
625 case '!':
626 if (other->type == '=') {
627 token->type = NOT_EQUAL;
628 token->value.ival = NOT_EQUAL;
629 return;
630 }
631 break;
632 case '&':
633 if (other->type == '&') {
634 token->type = AND;
635 token->value.ival = AND;
636 return;
637 }
638 break;
639 case '|':
640 if (other->type == '|') {
641 token->type = OR;
642 token->value.ival = OR;
643 return;
644 }
645 break;
646 }
647
648 /* Two string-valued tokens can usually just be mashed
649 * together.
650 *
651 * XXX: Since our 'OTHER' case is currently so loose, this may
652 * allow some things thruogh that should be treated as
653 * errors. */
654 if ((token->type == IDENTIFIER || token->type == OTHER) &&
655 (other->type == IDENTIFIER || other->type == OTHER))
656 {
657 token->value.str = talloc_strdup_append (token->value.str,
658 other->value.str);
659 return;
660 }
661
662 printf ("Error: Pasting \"");
663 _token_print (token);
664 printf ("\" and \"");
665 _token_print (other);
666 printf ("\" does not give a valid preprocessing token.\n");
667}
668
Carl Worth0197e9b2010-05-26 08:05:19 -0700669static void
670_token_list_print (token_list_t *list)
671{
672 token_node_t *node;
673
674 if (list == NULL)
675 return;
676
677 for (node = list->head; node; node = node->next)
678 _token_print (node->token);
679}
680
Carl Worth3a37b872010-05-10 11:44:09 -0700681void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700682yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700683{
684 fprintf (stderr, "Parse error: %s\n", error);
685}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700686
Carl Worth33cc4002010-05-12 12:17:10 -0700687glcpp_parser_t *
688glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700689{
Carl Worth33cc4002010-05-12 12:17:10 -0700690 glcpp_parser_t *parser;
691
Carl Worth5070a202010-05-12 12:45:33 -0700692 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700693
Carl Worth8f38aff2010-05-19 10:01:29 -0700694 glcpp_lex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700695 parser->defines = hash_table_ctor (32, hash_table_string_hash,
696 hash_table_string_compare);
Carl Worthae6517f2010-05-25 15:24:59 -0700697 parser->active = _string_list_create (parser);
Carl Worthf34a0002010-05-25 16:59:02 -0700698 parser->space_tokens = 1;
Carl Worth5a6b9a22010-05-20 14:29:43 -0700699
Carl Worthb20d33c2010-05-20 22:27:07 -0700700 parser->skip_stack = NULL;
701
Carl Worth33cc4002010-05-12 12:17:10 -0700702 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700703}
704
705int
706glcpp_parser_parse (glcpp_parser_t *parser)
707{
708 return yyparse (parser);
709}
710
711void
Carl Worth33cc4002010-05-12 12:17:10 -0700712glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700713{
Carl Worthb20d33c2010-05-20 22:27:07 -0700714 if (parser->skip_stack)
715 fprintf (stderr, "Error: Unterminated #if\n");
Carl Worth8f38aff2010-05-19 10:01:29 -0700716 glcpp_lex_destroy (parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700717 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700718 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700719}
Carl Worthc6d5af32010-05-11 12:30:09 -0700720
Carl Worth0197e9b2010-05-26 08:05:19 -0700721/* Appends onto 'expansion' a non-macro token or the expansion of an
722 * object-like macro.
Carl Worthb1854fd2010-05-25 16:28:26 -0700723 *
Carl Worth0197e9b2010-05-26 08:05:19 -0700724 * Returns 0 if this token is completely processed.
Carl Worthb1854fd2010-05-25 16:28:26 -0700725 *
726 * Returns 1 in the case that 'token' is a function-like macro that
727 * needs further expansion.
728 */
729static int
Carl Worth0197e9b2010-05-26 08:05:19 -0700730_glcpp_parser_expand_token_onto (glcpp_parser_t *parser,
731 token_t *token,
732 token_list_t *result)
Carl Worthae6517f2010-05-25 15:24:59 -0700733{
734 const char *identifier;
735 macro_t *macro;
Carl Worth0197e9b2010-05-26 08:05:19 -0700736 token_list_t *expansion;
Carl Worthae6517f2010-05-25 15:24:59 -0700737
738 /* We only expand identifiers */
739 if (token->type != IDENTIFIER) {
Carl Worth0197e9b2010-05-26 08:05:19 -0700740 _token_list_append (result, token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700741 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700742 }
743
744 /* Look up this identifier in the hash table. */
745 identifier = token->value.str;
746 macro = hash_table_find (parser->defines, identifier);
747
Carl Worth0197e9b2010-05-26 08:05:19 -0700748 /* Not a macro, so just append. */
Carl Worthae6517f2010-05-25 15:24:59 -0700749 if (macro == NULL) {
Carl Worth0197e9b2010-05-26 08:05:19 -0700750 _token_list_append (result, token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700751 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700752 }
753
Carl Worthae6517f2010-05-25 15:24:59 -0700754 /* Finally, don't expand this macro if we're already actively
755 * expanding it, (to avoid infinite recursion). */
Carl Worthec4ada02010-05-26 08:15:49 -0700756 if (_string_list_contains (parser->active, identifier, NULL))
757 {
758 /* We change the token type here from IDENTIFIER to
759 * OTHER to prevent any future expansion of this
760 * unexpanded token. */
761 char *str;
762 token_t *new_token;
763
764 str = xtalloc_strdup (result, token->value.str);
765 new_token = _token_create_str (result, OTHER, str);
766 _token_list_append (result, new_token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700767 return 0;
768 }
769
Carl Worthc0607d52010-05-26 08:01:42 -0700770 /* For function-like macros return 1 for further processing. */
771 if (macro->is_function) {
772 return 1;
773 }
774
Carl Worthb1854fd2010-05-25 16:28:26 -0700775 _string_list_push (parser->active, identifier);
Carl Worth0197e9b2010-05-26 08:05:19 -0700776 _glcpp_parser_expand_token_list_onto (parser,
777 macro->replacements,
778 result);
Carl Worthb1854fd2010-05-25 16:28:26 -0700779 _string_list_pop (parser->active);
780
781 return 0;
782}
783
784typedef enum function_status
785{
786 FUNCTION_STATUS_SUCCESS,
787 FUNCTION_NOT_A_FUNCTION,
788 FUNCTION_UNBALANCED_PARENTHESES
789} function_status_t;
790
791/* Find a set of function-like macro arguments by looking for a
792 * balanced set of parentheses. Upon return *node will be the last
793 * consumed node, such that further processing can continue with
794 * node->next.
795 *
796 * Return values:
797 *
798 * FUNCTION_STATUS_SUCCESS:
799 *
800 * Successfully parsed a set of function arguments.
801 *
802 * FUNCTION_NOT_A_FUNCTION:
803 *
804 * Macro name not followed by a '('. This is not an error, but
805 * simply that the macro name should be treated as a non-macro.
806 *
807 * FUNCTION_UNBLANCED_PARENTHESES
808 *
809 * Macro name is not followed by a balanced set of parentheses.
810 */
811static function_status_t
Carl Worth9ce18cf2010-05-25 17:32:21 -0700812_arguments_parse (argument_list_t *arguments, token_node_t **node_ret)
Carl Worthb1854fd2010-05-25 16:28:26 -0700813{
Carl Worth9ce18cf2010-05-25 17:32:21 -0700814 token_list_t *argument;
Carl Worthb1854fd2010-05-25 16:28:26 -0700815 token_node_t *node = *node_ret, *last;
816 int paren_count;
Carl Worthb1854fd2010-05-25 16:28:26 -0700817
818 last = node;
819 node = node->next;
820
821 /* Ignore whitespace before first parenthesis. */
822 while (node && node->token->type == SPACE)
823 node = node->next;
824
825 if (node == NULL || node->token->type != '(')
826 return FUNCTION_NOT_A_FUNCTION;
827
Carl Worth652fa272010-05-25 17:45:22 -0700828 last = node;
829 node = node->next;
830
Carl Worth9ce18cf2010-05-25 17:32:21 -0700831 argument = NULL;
832
Carl Worth652fa272010-05-25 17:45:22 -0700833 for (paren_count = 1; node; last = node, node = node->next) {
Carl Worthb1854fd2010-05-25 16:28:26 -0700834 if (node->token->type == '(')
835 {
836 paren_count++;
837 }
838 else if (node->token->type == ')')
839 {
840 paren_count--;
Carl Worthc7581c22010-05-25 17:41:07 -0700841 if (paren_count == 0) {
842 last = node;
843 node = node->next;
844 break;
845 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700846 }
Carl Worth652fa272010-05-25 17:45:22 -0700847
848 if (node->token->type == ',' &&
Carl Worthb1854fd2010-05-25 16:28:26 -0700849 paren_count == 1)
850 {
Carl Worth10ae4382010-05-25 20:35:01 -0700851 if (argument)
852 _token_list_trim_trailing_space (argument);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700853 argument = NULL;
854 }
855 else {
856 if (argument == NULL) {
Carl Worthc7581c22010-05-25 17:41:07 -0700857 /* Don't treat initial whitespace as
858 * part of the arguement. */
859 if (node->token->type == SPACE)
860 continue;
Carl Worth9ce18cf2010-05-25 17:32:21 -0700861 argument = _token_list_create (arguments);
862 _argument_list_append (arguments, argument);
863 }
864 _token_list_append (argument, node->token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700865 }
Carl Worthc7581c22010-05-25 17:41:07 -0700866 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700867
868 if (node && paren_count)
869 return FUNCTION_UNBALANCED_PARENTHESES;
870
871 *node_ret = last;
872
873 return FUNCTION_STATUS_SUCCESS;
874}
875
876/* Prints the expansion of *node (consuming further tokens from the
877 * list as necessary). Upon return *node will be the last consumed
878 * node, such that further processing can continue with node->next. */
879static void
Carl Worth0197e9b2010-05-26 08:05:19 -0700880_glcpp_parser_expand_function_onto (glcpp_parser_t *parser,
881 token_node_t **node_ret,
882 token_list_t *result)
Carl Worthb1854fd2010-05-25 16:28:26 -0700883{
884 macro_t *macro;
885 token_node_t *node;
886 const char *identifier;
887 argument_list_t *arguments;
888 function_status_t status;
Carl Worth0197e9b2010-05-26 08:05:19 -0700889 token_list_t *substituted;
Carl Worth9ce18cf2010-05-25 17:32:21 -0700890 int parameter_index;
Carl Worthb1854fd2010-05-25 16:28:26 -0700891
892 node = *node_ret;
893 identifier = node->token->value.str;
894
895 macro = hash_table_find (parser->defines, identifier);
896
897 assert (macro->is_function);
898
Carl Worth9ce18cf2010-05-25 17:32:21 -0700899 arguments = _argument_list_create (parser);
900 status = _arguments_parse (arguments, node_ret);
Carl Worthb1854fd2010-05-25 16:28:26 -0700901
902 switch (status) {
903 case FUNCTION_STATUS_SUCCESS:
904 break;
905 case FUNCTION_NOT_A_FUNCTION:
Carl Worth0197e9b2010-05-26 08:05:19 -0700906 _token_list_append (result, node->token);
Carl Worthae6517f2010-05-25 15:24:59 -0700907 return;
Carl Worthb1854fd2010-05-25 16:28:26 -0700908 case FUNCTION_UNBALANCED_PARENTHESES:
909 fprintf (stderr, "Error: Macro %s call has unbalanced parentheses\n",
910 identifier);
911 exit (1);
Carl Worthae6517f2010-05-25 15:24:59 -0700912 }
913
Carl Worth9ce18cf2010-05-25 17:32:21 -0700914 if (macro->replacements == NULL) {
915 talloc_free (arguments);
916 return;
917 }
918
Carl Worth9ce18cf2010-05-25 17:32:21 -0700919 if (_argument_list_length (arguments) !=
920 _string_list_length (macro->parameters))
921 {
922 fprintf (stderr,
923 "Error: macro %s invoked with %d arguments (expected %d)\n",
924 identifier,
925 _argument_list_length (arguments),
926 _string_list_length (macro->parameters));
927 return;
928 }
929
Carl Worth0197e9b2010-05-26 08:05:19 -0700930 /* Perform argument substitution on the replacement list. */
931 substituted = _token_list_create (arguments);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700932
Carl Worthce540f22010-05-26 08:25:44 -0700933 for (node = macro->replacements->head; node; node = node->next)
934 {
935 if (node->token->type == IDENTIFIER &&
Carl Worth9ce18cf2010-05-25 17:32:21 -0700936 _string_list_contains (macro->parameters,
Carl Worthce540f22010-05-26 08:25:44 -0700937 node->token->value.str,
Carl Worth9ce18cf2010-05-25 17:32:21 -0700938 &parameter_index))
939 {
940 token_list_t *argument;
941 argument = _argument_list_member_at (arguments,
942 parameter_index);
Carl Worthd5cd4032010-05-26 08:09:29 -0700943 /* Before substituting, we expand the argument
944 * tokens. */
945 _glcpp_parser_expand_token_list_onto (parser,
946 argument,
947 substituted);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700948 } else {
Carl Worthce540f22010-05-26 08:25:44 -0700949 _token_list_append (substituted, node->token);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700950 }
951 }
952
Carl Worthad0dee62010-05-26 09:04:50 -0700953 /* After argument substitution, and before further expansion
954 * below, implement token pasting. */
955
956 node = substituted->head;
957 while (node)
958 {
959 token_node_t *next_non_space;
960
961 /* Look ahead for a PASTE token, skipping space. */
962 next_non_space = node->next;
963 while (next_non_space && next_non_space->token->type == SPACE)
964 next_non_space = next_non_space->next;
965
966 if (next_non_space == NULL)
967 break;
968
969 if (next_non_space->token->type != PASTE) {
970 node = next_non_space;
971 continue;
972 }
973
974 /* Now find the next non-space token after the PASTE. */
975 next_non_space = next_non_space->next;
976 while (next_non_space && next_non_space->token->type == SPACE)
977 next_non_space = next_non_space->next;
978
979 if (next_non_space == NULL) {
980 fprintf (stderr, "Error: '##' cannot appear at either end of a macro expansion\n");
981 exit (1);
982 }
983
984 _token_paste (node->token, next_non_space->token);
985 node->next = next_non_space->next;
986
987 node = node->next;
988 }
989
Carl Worthae6517f2010-05-25 15:24:59 -0700990 _string_list_push (parser->active, identifier);
Carl Worth0197e9b2010-05-26 08:05:19 -0700991 _glcpp_parser_expand_token_list_onto (parser, substituted, result);
Carl Worthae6517f2010-05-25 15:24:59 -0700992 _string_list_pop (parser->active);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700993
994 talloc_free (arguments);
Carl Worthae6517f2010-05-25 15:24:59 -0700995}
996
Carl Worth0197e9b2010-05-26 08:05:19 -0700997static void
998_glcpp_parser_expand_token_list_onto (glcpp_parser_t *parser,
999 token_list_t *list,
1000 token_list_t *result)
1001{
1002 token_node_t *node;
1003
1004 if (list == NULL)
1005 return;
1006
1007 for (node = list->head; node; node = node->next)
1008 {
1009 if (_glcpp_parser_expand_token_onto (parser, node->token,
1010 result))
1011 {
1012 _glcpp_parser_expand_function_onto (parser, &node,
1013 result);
1014 }
1015 }
1016}
1017
Carl Worthae6517f2010-05-25 15:24:59 -07001018void
1019_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
1020 token_list_t *list)
1021{
Carl Worth0197e9b2010-05-26 08:05:19 -07001022 token_list_t *expanded;
Carl Worthae6517f2010-05-25 15:24:59 -07001023 token_node_t *node;
Carl Worthb1854fd2010-05-25 16:28:26 -07001024 function_status_t function_status;
Carl Worthae6517f2010-05-25 15:24:59 -07001025
1026 if (list == NULL)
1027 return;
1028
Carl Worth0197e9b2010-05-26 08:05:19 -07001029 expanded = _token_list_create (parser);
Carl Worth10ae4382010-05-25 20:35:01 -07001030
Carl Worth0197e9b2010-05-26 08:05:19 -07001031 _glcpp_parser_expand_token_list_onto (parser, list, expanded);
1032
1033 _token_list_trim_trailing_space (expanded);
1034
1035 _token_list_print (expanded);
1036
1037 talloc_free (expanded);
Carl Worthae6517f2010-05-25 15:24:59 -07001038}
1039
1040void
Carl Worthfcbbb462010-05-13 09:36:23 -07001041_define_object_macro (glcpp_parser_t *parser,
1042 const char *identifier,
Carl Worth47252442010-05-19 13:54:37 -07001043 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -07001044{
1045 macro_t *macro;
1046
1047 macro = xtalloc (parser, macro_t);
1048
1049 macro->is_function = 0;
Carl Worthc5e98552010-05-14 10:12:21 -07001050 macro->parameters = NULL;
Carl Wortha807fb72010-05-18 22:10:04 -07001051 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -07001052 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -07001053
1054 hash_table_insert (parser->defines, macro, identifier);
1055}
1056
1057void
1058_define_function_macro (glcpp_parser_t *parser,
1059 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -07001060 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -07001061 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -07001062{
1063 macro_t *macro;
1064
1065 macro = xtalloc (parser, macro_t);
1066
1067 macro->is_function = 1;
Carl Worthc5e98552010-05-14 10:12:21 -07001068 macro->parameters = talloc_steal (macro, parameters);
Carl Wortha807fb72010-05-18 22:10:04 -07001069 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -07001070 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -07001071
1072 hash_table_insert (parser->defines, macro, identifier);
1073}
1074
Carl Worth8f38aff2010-05-19 10:01:29 -07001075static int
Carl Worth0293b2e2010-05-19 10:05:40 -07001076glcpp_parser_lex (glcpp_parser_t *parser)
Carl Worth8f38aff2010-05-19 10:01:29 -07001077{
Carl Worth5aa7ea02010-05-25 18:39:43 -07001078 return glcpp_lex (parser->scanner);
Carl Worth8f38aff2010-05-19 10:01:29 -07001079}
Carl Worthb20d33c2010-05-20 22:27:07 -07001080
1081static void
1082_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition)
1083{
1084 skip_type_t current = SKIP_NO_SKIP;
1085 skip_node_t *node;
1086
1087 if (parser->skip_stack)
1088 current = parser->skip_stack->type;
1089
1090 node = xtalloc (parser, skip_node_t);
1091
1092 if (current == SKIP_NO_SKIP) {
1093 if (condition)
1094 node->type = SKIP_NO_SKIP;
1095 else
1096 node->type = SKIP_TO_ELSE;
1097 } else {
1098 node->type = SKIP_TO_ENDIF;
1099 }
1100
1101 node->next = parser->skip_stack;
1102 parser->skip_stack = node;
1103}
1104
1105static void
1106_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
1107 int condition)
1108{
1109 if (parser->skip_stack == NULL) {
1110 fprintf (stderr, "Error: %s without #if\n", type);
1111 exit (1);
1112 }
1113
1114 if (parser->skip_stack->type == SKIP_TO_ELSE) {
1115 if (condition)
1116 parser->skip_stack->type = SKIP_NO_SKIP;
1117 } else {
1118 parser->skip_stack->type = SKIP_TO_ENDIF;
1119 }
1120}
Carl Worth80dc60b2010-05-25 14:42:00 -07001121
Carl Worthb20d33c2010-05-20 22:27:07 -07001122static void
1123_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser)
1124{
1125 skip_node_t *node;
1126
1127 if (parser->skip_stack == NULL) {
1128 fprintf (stderr, "Error: #endif without #if\n");
1129 exit (1);
1130 }
1131
1132 node = parser->skip_stack;
1133 parser->skip_stack = node->next;
1134 talloc_free (node);
1135}