blob: 58e1e655fdb66a1eddd445565c2a477376cda638 [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 Worth8fed1cd2010-05-26 09:32:12 -070028#include <inttypes.h>
Carl Worth3a37b872010-05-10 11:44:09 -070029
Carl Wortha1e32bc2010-05-10 13:17:25 -070030#include "glcpp.h"
31
Carl Worth5aa7ea02010-05-25 18:39:43 -070032static void
Carl Wortha1e32bc2010-05-10 13:17:25 -070033yyerror (void *scanner, const char *error);
Carl Worth3a37b872010-05-10 11:44:09 -070034
Carl Worth5aa7ea02010-05-25 18:39:43 -070035static void
Carl Worthfcbbb462010-05-13 09:36:23 -070036_define_object_macro (glcpp_parser_t *parser,
37 const char *macro,
Carl Worth47252442010-05-19 13:54:37 -070038 token_list_t *replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -070039
Carl Worth5aa7ea02010-05-25 18:39:43 -070040static void
Carl Worthfcbbb462010-05-13 09:36:23 -070041_define_function_macro (glcpp_parser_t *parser,
42 const char *macro,
Carl Worthc5e98552010-05-14 10:12:21 -070043 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -070044 token_list_t *replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -070045
Carl Worth5aa7ea02010-05-25 18:39:43 -070046static string_list_t *
Carl Worth610053b2010-05-14 10:05:11 -070047_string_list_create (void *ctx);
Carl Worth33cc4002010-05-12 12:17:10 -070048
Carl Worth5aa7ea02010-05-25 18:39:43 -070049static void
Carl Worth610053b2010-05-14 10:05:11 -070050_string_list_append_item (string_list_t *list, const char *str);
Carl Worthfcbbb462010-05-13 09:36:23 -070051
Carl Worth5aa7ea02010-05-25 18:39:43 -070052static void
Carl Worth610053b2010-05-14 10:05:11 -070053_string_list_append_list (string_list_t *list, string_list_t *tail);
Carl Worthc6d5af32010-05-11 12:30:09 -070054
Carl Worth5aa7ea02010-05-25 18:39:43 -070055static void
Carl Worthae6517f2010-05-25 15:24:59 -070056_string_list_push (string_list_t *list, const char *str);
57
Carl Worth5aa7ea02010-05-25 18:39:43 -070058static void
Carl Worthae6517f2010-05-25 15:24:59 -070059_string_list_pop (string_list_t *list);
60
Carl Worth5aa7ea02010-05-25 18:39:43 -070061static int
Carl Worth610053b2010-05-14 10:05:11 -070062_string_list_contains (string_list_t *list, const char *member, int *index);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070063
Carl Worth5aa7ea02010-05-25 18:39:43 -070064static int
Carl Worth610053b2010-05-14 10:05:11 -070065_string_list_length (string_list_t *list);
Carl Worthdcc2ecd2010-05-13 12:56:42 -070066
Carl Worth5aa7ea02010-05-25 18:39:43 -070067static argument_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -070068_argument_list_create (void *ctx);
69
Carl Worth5aa7ea02010-05-25 18:39:43 -070070static void
Carl Worth47252442010-05-19 13:54:37 -070071_argument_list_append (argument_list_t *list, token_list_t *argument);
Carl Worth8f6a8282010-05-14 10:44:19 -070072
Carl Worth5aa7ea02010-05-25 18:39:43 -070073static int
Carl Worth8f6a8282010-05-14 10:44:19 -070074_argument_list_length (argument_list_t *list);
75
Carl Worth5aa7ea02010-05-25 18:39:43 -070076static token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -070077_argument_list_member_at (argument_list_t *list, int index);
78
Carl Worth808401f2010-05-25 14:52:43 -070079/* Note: This function talloc_steal()s the str pointer. */
Carl Worth5aa7ea02010-05-25 18:39:43 -070080static token_t *
Carl Worth808401f2010-05-25 14:52:43 -070081_token_create_str (void *ctx, int type, char *str);
82
Carl Worth5aa7ea02010-05-25 18:39:43 -070083static token_t *
Carl Worth808401f2010-05-25 14:52:43 -070084_token_create_ival (void *ctx, int type, int ival);
85
Carl Worth5aa7ea02010-05-25 18:39:43 -070086static token_list_t *
Carl Worth47252442010-05-19 13:54:37 -070087_token_list_create (void *ctx);
88
Carl Worthb1ae61a2010-05-26 08:10:38 -070089/* Note: This function adds a talloc_reference() to token.
Carl Worth808401f2010-05-25 14:52:43 -070090 *
91 * You may want to talloc_unlink any current reference if you no
92 * longer need it. */
Carl Worth5aa7ea02010-05-25 18:39:43 -070093static void
Carl Worth808401f2010-05-25 14:52:43 -070094_token_list_append (token_list_t *list, token_t *token);
Carl Worth47252442010-05-19 13:54:37 -070095
Carl Worth5aa7ea02010-05-25 18:39:43 -070096static void
Carl Worth47252442010-05-19 13:54:37 -070097_token_list_append_list (token_list_t *list, token_list_t *tail);
98
Carl Worth5aa7ea02010-05-25 18:39:43 -070099static void
Carl Worthae6517f2010-05-25 15:24:59 -0700100_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
101 token_list_t *list);
Carl Worth808401f2010-05-25 14:52:43 -0700102
Carl Worthaaa9acb2010-05-19 13:28:24 -0700103static void
Carl Worth0197e9b2010-05-26 08:05:19 -0700104_glcpp_parser_expand_token_list_onto (glcpp_parser_t *parser,
105 token_list_t *list,
106 token_list_t *result);
107
108static void
Carl Worthb20d33c2010-05-20 22:27:07 -0700109_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition);
110
111static void
112_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
113 int condition);
Carl Worth80dc60b2010-05-25 14:42:00 -0700114
Carl Worthb20d33c2010-05-20 22:27:07 -0700115static void
116_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser);
117
Carl Worth0293b2e2010-05-19 10:05:40 -0700118#define yylex glcpp_parser_lex
119
Carl Worth8f38aff2010-05-19 10:01:29 -0700120static int
Carl Worth0293b2e2010-05-19 10:05:40 -0700121glcpp_parser_lex (glcpp_parser_t *parser);
Carl Worth8f38aff2010-05-19 10:01:29 -0700122
Carl Worth3a37b872010-05-10 11:44:09 -0700123%}
124
Carl Worth0b27b5f2010-05-10 16:16:06 -0700125%parse-param {glcpp_parser_t *parser}
Carl Worth0293b2e2010-05-19 10:05:40 -0700126%lex-param {glcpp_parser_t *parser}
Carl Worth38aa8352010-05-10 11:52:29 -0700127
Carl Worth8fed1cd2010-05-26 09:32:12 -0700128%token DEFINED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF IDENTIFIER INTEGER NEWLINE OTHER SPACE
129%token PASTE
130%type <ival> expression INTEGER punctuator SPACE
Carl Worthe9397862010-05-25 17:08:07 -0700131%type <str> IDENTIFIER OTHER
Carl Worthb1854fd2010-05-25 16:28:26 -0700132%type <string_list> identifier_list
Carl Worth808401f2010-05-25 14:52:43 -0700133%type <token> preprocessing_token
134%type <token_list> pp_tokens replacement_list text_line
Carl Worth8fed1cd2010-05-26 09:32:12 -0700135%left OR
136%left AND
137%left '|'
138%left '^'
139%left '&'
140%left EQUAL NOT_EQUAL
141%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL
142%left LEFT_SHIFT RIGHT_SHIFT
143%left '+' '-'
144%left '*' '/' '%'
145%right UNARY
Carl Worth3a37b872010-05-10 11:44:09 -0700146
147%%
148
Carl Worth33cc4002010-05-12 12:17:10 -0700149input:
Carl Worth3ff81672010-05-25 13:09:03 -0700150 /* empty */
Carl Worthae6517f2010-05-25 15:24:59 -0700151| input line {
Carl Worth8fed1cd2010-05-26 09:32:12 -0700152 if (parser->skip_stack == NULL ||
153 parser->skip_stack->type == SKIP_NO_SKIP)
154 {
155 printf ("\n");
156 }
Carl Worthae6517f2010-05-25 15:24:59 -0700157 }
Carl Worth3a37b872010-05-10 11:44:09 -0700158;
159
Carl Worth3ff81672010-05-25 13:09:03 -0700160line:
161 control_line
Carl Worth808401f2010-05-25 14:52:43 -0700162| text_line {
Carl Worth8fed1cd2010-05-26 09:32:12 -0700163 if (parser->skip_stack == NULL ||
164 parser->skip_stack->type == SKIP_NO_SKIP)
165 {
166 _glcpp_parser_print_expanded_token_list (parser, $1);
167 }
Carl Worth808401f2010-05-25 14:52:43 -0700168 talloc_free ($1);
169 }
Carl Worth3ff81672010-05-25 13:09:03 -0700170| HASH non_directive
Carl Worthcd27e642010-05-12 13:11:50 -0700171;
172
Carl Worth3ff81672010-05-25 13:09:03 -0700173control_line:
Carl Worthf34a0002010-05-25 16:59:02 -0700174 HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
Carl Worthae6517f2010-05-25 15:24:59 -0700175 _define_object_macro (parser, $2, $3);
176 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700177| HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
178 _define_function_macro (parser, $2, NULL, $5);
179 }
180| HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
181 _define_function_macro (parser, $2, $4, $6);
182 }
Carl Worthe6fb7822010-05-25 15:28:58 -0700183| HASH_UNDEF IDENTIFIER NEWLINE {
184 string_list_t *macro = hash_table_find (parser->defines, $2);
185 if (macro) {
186 /* XXX: Need hash table to support a real way
187 * to remove an element rather than prefixing
188 * a new node with data of NULL like this. */
189 hash_table_insert (parser->defines, NULL, $2);
190 talloc_free (macro);
191 }
192 talloc_free ($2);
193 }
Carl Worth8fed1cd2010-05-26 09:32:12 -0700194| HASH_IF expression NEWLINE {
195 _glcpp_parser_skip_stack_push_if (parser, $2);
196 }
197| HASH_IFDEF IDENTIFIER NEWLINE {
198 string_list_t *macro = hash_table_find (parser->defines, $2);
199 talloc_free ($2);
200 _glcpp_parser_skip_stack_push_if (parser, macro != NULL);
201 }
202| HASH_IFNDEF IDENTIFIER NEWLINE {
203 string_list_t *macro = hash_table_find (parser->defines, $2);
204 talloc_free ($2);
205 _glcpp_parser_skip_stack_push_if (parser, macro == NULL);
206 }
207| HASH_ELIF expression NEWLINE {
208 _glcpp_parser_skip_stack_change_if (parser, "#elif", $2);
209 }
210| HASH_ELSE NEWLINE {
211 _glcpp_parser_skip_stack_change_if (parser, "else", 1);
212 }
213| HASH_ENDIF NEWLINE {
214 _glcpp_parser_skip_stack_pop (parser);
215 }
Carl Worth3ff81672010-05-25 13:09:03 -0700216| HASH NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700217;
218
Carl Worth8fed1cd2010-05-26 09:32:12 -0700219expression:
220 INTEGER {
221 $$ = $1;
222 }
223| expression OR expression {
224 $$ = $1 || $3;
225 }
226| expression AND expression {
227 $$ = $1 && $3;
228 }
229| expression '|' expression {
230 $$ = $1 | $3;
231 }
232| expression '^' expression {
233 $$ = $1 ^ $3;
234 }
235| expression '&' expression {
236 $$ = $1 & $3;
237 }
238| expression NOT_EQUAL expression {
239 $$ = $1 != $3;
240 }
241| expression EQUAL expression {
242 $$ = $1 == $3;
243 }
244| expression GREATER_OR_EQUAL expression {
245 $$ = $1 >= $3;
246 }
247| expression LESS_OR_EQUAL expression {
248 $$ = $1 <= $3;
249 }
250| expression '>' expression {
251 $$ = $1 > $3;
252 }
253| expression '<' expression {
254 $$ = $1 < $3;
255 }
256| expression RIGHT_SHIFT expression {
257 $$ = $1 >> $3;
258 }
259| expression LEFT_SHIFT expression {
260 $$ = $1 << $3;
261 }
262| expression '-' expression {
263 $$ = $1 - $3;
264 }
265| expression '+' expression {
266 $$ = $1 + $3;
267 }
268| expression '%' expression {
269 $$ = $1 % $3;
270 }
271| expression '/' expression {
272 $$ = $1 / $3;
273 }
274| expression '*' expression {
275 $$ = $1 * $3;
276 }
277| '!' expression %prec UNARY {
278 $$ = ! $2;
279 }
280| '~' expression %prec UNARY {
281 $$ = ~ $2;
282 }
283| '-' expression %prec UNARY {
284 $$ = - $2;
285 }
286| '+' expression %prec UNARY {
287 $$ = + $2;
288 }
289| DEFINED IDENTIFIER %prec UNARY {
290 string_list_t *macro = hash_table_find (parser->defines, $2);
291 talloc_free ($2);
292 if (macro)
293 $$ = 1;
294 else
295 $$ = 0;
296 }
297| '(' expression ')' {
298 $$ = $2;
299 }
300;
301
Carl Worth3ff81672010-05-25 13:09:03 -0700302identifier_list:
Carl Worthb1854fd2010-05-25 16:28:26 -0700303 IDENTIFIER {
304 $$ = _string_list_create (parser);
305 _string_list_append_item ($$, $1);
306 talloc_steal ($$, $1);
307 }
308| identifier_list ',' IDENTIFIER {
309 $$ = $1;
310 _string_list_append_item ($$, $3);
311 talloc_steal ($$, $3);
312 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700313;
314
Carl Worth3ff81672010-05-25 13:09:03 -0700315text_line:
Carl Worth808401f2010-05-25 14:52:43 -0700316 NEWLINE { $$ = NULL; }
Carl Worth3ff81672010-05-25 13:09:03 -0700317| pp_tokens NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700318;
319
Carl Worth3ff81672010-05-25 13:09:03 -0700320non_directive:
321 pp_tokens NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700322;
323
Carl Worthaaa9acb2010-05-19 13:28:24 -0700324replacement_list:
Carl Worth808401f2010-05-25 14:52:43 -0700325 /* empty */ { $$ = NULL; }
Carl Worth3ff81672010-05-25 13:09:03 -0700326| pp_tokens
Carl Worthaaa9acb2010-05-19 13:28:24 -0700327;
328
Carl Worthaaa9acb2010-05-19 13:28:24 -0700329pp_tokens:
Carl Worth808401f2010-05-25 14:52:43 -0700330 preprocessing_token {
Carl Worthf34a0002010-05-25 16:59:02 -0700331 parser->space_tokens = 1;
Carl Worth808401f2010-05-25 14:52:43 -0700332 $$ = _token_list_create (parser);
333 _token_list_append ($$, $1);
334 talloc_unlink (parser, $1);
335 }
336| pp_tokens preprocessing_token {
337 $$ = $1;
338 _token_list_append ($$, $2);
339 talloc_unlink (parser, $2);
340 }
Carl Worthaaa9acb2010-05-19 13:28:24 -0700341;
342
Carl Worth3ff81672010-05-25 13:09:03 -0700343preprocessing_token:
Carl Worth808401f2010-05-25 14:52:43 -0700344 IDENTIFIER {
345 $$ = _token_create_str (parser, IDENTIFIER, $1);
346 }
Carl Worth8fed1cd2010-05-26 09:32:12 -0700347| INTEGER {
348 $$ = _token_create_ival (parser, INTEGER, $1);
349 }
Carl Worth808401f2010-05-25 14:52:43 -0700350| punctuator {
351 $$ = _token_create_ival (parser, $1, $1);
352 }
353| OTHER {
354 $$ = _token_create_str (parser, OTHER, $1);
355 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700356| SPACE {
Carl Worthe9397862010-05-25 17:08:07 -0700357 $$ = _token_create_ival (parser, SPACE, SPACE);
Carl Worthb1854fd2010-05-25 16:28:26 -0700358 }
Carl Worth3ff81672010-05-25 13:09:03 -0700359;
360
361punctuator:
Carl Worth808401f2010-05-25 14:52:43 -0700362 '[' { $$ = '['; }
363| ']' { $$ = ']'; }
364| '(' { $$ = '('; }
365| ')' { $$ = ')'; }
366| '{' { $$ = '{'; }
367| '}' { $$ = '}'; }
368| '.' { $$ = '.'; }
369| '&' { $$ = '&'; }
370| '*' { $$ = '*'; }
371| '+' { $$ = '+'; }
372| '-' { $$ = '-'; }
373| '~' { $$ = '~'; }
374| '!' { $$ = '!'; }
375| '/' { $$ = '/'; }
376| '%' { $$ = '%'; }
377| LEFT_SHIFT { $$ = LEFT_SHIFT; }
378| RIGHT_SHIFT { $$ = RIGHT_SHIFT; }
379| '<' { $$ = '<'; }
380| '>' { $$ = '>'; }
381| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; }
382| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; }
383| EQUAL { $$ = EQUAL; }
384| NOT_EQUAL { $$ = NOT_EQUAL; }
385| '^' { $$ = '^'; }
386| '|' { $$ = '|'; }
387| AND { $$ = AND; }
388| OR { $$ = OR; }
389| ';' { $$ = ';'; }
390| ',' { $$ = ','; }
391| PASTE { $$ = PASTE; }
Carl Worth3ff81672010-05-25 13:09:03 -0700392;
393
Carl Worth33cc4002010-05-12 12:17:10 -0700394%%
395
Carl Worth610053b2010-05-14 10:05:11 -0700396string_list_t *
397_string_list_create (void *ctx)
Carl Worth33cc4002010-05-12 12:17:10 -0700398{
Carl Worth610053b2010-05-14 10:05:11 -0700399 string_list_t *list;
Carl Worth33cc4002010-05-12 12:17:10 -0700400
Carl Worth610053b2010-05-14 10:05:11 -0700401 list = xtalloc (ctx, string_list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700402 list->head = NULL;
403 list->tail = NULL;
404
405 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700406}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700407
Carl Worth33cc4002010-05-12 12:17:10 -0700408void
Carl Worth610053b2010-05-14 10:05:11 -0700409_string_list_append_list (string_list_t *list, string_list_t *tail)
Carl Worthfcbbb462010-05-13 09:36:23 -0700410{
411 if (list->head == NULL) {
412 list->head = tail->head;
413 } else {
414 list->tail->next = tail->head;
415 }
416
417 list->tail = tail->tail;
418}
419
420void
Carl Worth610053b2010-05-14 10:05:11 -0700421_string_list_append_item (string_list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700422{
Carl Worth610053b2010-05-14 10:05:11 -0700423 string_node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700424
Carl Worth610053b2010-05-14 10:05:11 -0700425 node = xtalloc (list, string_node_t);
Carl Worth5070a202010-05-12 12:45:33 -0700426 node->str = xtalloc_strdup (node, str);
Carl Worth80dc60b2010-05-25 14:42:00 -0700427
Carl Worth33cc4002010-05-12 12:17:10 -0700428 node->next = NULL;
429
430 if (list->head == NULL) {
431 list->head = node;
432 } else {
433 list->tail->next = node;
434 }
435
436 list->tail = node;
437}
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700438
Carl Worthae6517f2010-05-25 15:24:59 -0700439void
440_string_list_push (string_list_t *list, const char *str)
441{
442 string_node_t *node;
443
444 node = xtalloc (list, string_node_t);
445 node->str = xtalloc_strdup (node, str);
446 node->next = list->head;
447
448 if (list->tail == NULL) {
449 list->tail = node;
450 }
451 list->head = node;
452}
453
454void
455_string_list_pop (string_list_t *list)
456{
457 string_node_t *node;
458
459 node = list->head;
460
461 if (node == NULL) {
462 fprintf (stderr, "Internal error: _string_list_pop called on an empty list.\n");
463 exit (1);
464 }
465
466 list->head = node->next;
467 if (list->tail == node) {
468 assert (node->next == NULL);
469 list->tail = NULL;
470 }
471
472 talloc_free (node);
473}
474
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700475int
Carl Worth610053b2010-05-14 10:05:11 -0700476_string_list_contains (string_list_t *list, const char *member, int *index)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700477{
Carl Worth610053b2010-05-14 10:05:11 -0700478 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700479 int i;
480
481 if (list == NULL)
482 return 0;
483
484 for (i = 0, node = list->head; node; i++, node = node->next) {
485 if (strcmp (node->str, member) == 0) {
Carl Worth420d05a2010-05-17 10:15:23 -0700486 if (index)
487 *index = i;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700488 return 1;
489 }
490 }
491
492 return 0;
493}
494
495int
Carl Worth610053b2010-05-14 10:05:11 -0700496_string_list_length (string_list_t *list)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700497{
498 int length = 0;
Carl Worth610053b2010-05-14 10:05:11 -0700499 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700500
501 if (list == NULL)
502 return 0;
503
504 for (node = list->head; node; node = node->next)
505 length++;
506
507 return length;
508}
509
Carl Worth8f6a8282010-05-14 10:44:19 -0700510argument_list_t *
511_argument_list_create (void *ctx)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700512{
Carl Worth8f6a8282010-05-14 10:44:19 -0700513 argument_list_t *list;
514
515 list = xtalloc (ctx, argument_list_t);
516 list->head = NULL;
517 list->tail = NULL;
518
519 return list;
520}
521
522void
Carl Worth47252442010-05-19 13:54:37 -0700523_argument_list_append (argument_list_t *list, token_list_t *argument)
Carl Worth8f6a8282010-05-14 10:44:19 -0700524{
525 argument_node_t *node;
526
Carl Worth8f6a8282010-05-14 10:44:19 -0700527 node = xtalloc (list, argument_node_t);
528 node->argument = argument;
529
530 node->next = NULL;
531
532 if (list->head == NULL) {
533 list->head = node;
534 } else {
535 list->tail->next = node;
536 }
537
538 list->tail = node;
539}
540
541int
542_argument_list_length (argument_list_t *list)
543{
544 int length = 0;
545 argument_node_t *node;
546
547 if (list == NULL)
548 return 0;
549
550 for (node = list->head; node; node = node->next)
551 length++;
552
553 return length;
554}
555
Carl Worth47252442010-05-19 13:54:37 -0700556token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -0700557_argument_list_member_at (argument_list_t *list, int index)
558{
559 argument_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700560 int i;
561
562 if (list == NULL)
563 return NULL;
564
565 node = list->head;
566 for (i = 0; i < index; i++) {
567 node = node->next;
568 if (node == NULL)
569 break;
570 }
571
572 if (node)
Carl Worth8f6a8282010-05-14 10:44:19 -0700573 return node->argument;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700574
575 return NULL;
576}
Carl Worth47252442010-05-19 13:54:37 -0700577
Carl Worth808401f2010-05-25 14:52:43 -0700578/* Note: This function talloc_steal()s the str pointer. */
579token_t *
580_token_create_str (void *ctx, int type, char *str)
581{
582 token_t *token;
583
584 token = xtalloc (ctx, token_t);
585 token->type = type;
586 token->value.str = talloc_steal (token, str);
587
588 return token;
589}
590
591token_t *
592_token_create_ival (void *ctx, int type, int ival)
593{
594 token_t *token;
595
596 token = xtalloc (ctx, token_t);
597 token->type = type;
598 token->value.ival = ival;
599
600 return token;
601}
602
Carl Worth47252442010-05-19 13:54:37 -0700603token_list_t *
604_token_list_create (void *ctx)
605{
606 token_list_t *list;
607
608 list = xtalloc (ctx, token_list_t);
609 list->head = NULL;
610 list->tail = NULL;
Carl Worth10ae4382010-05-25 20:35:01 -0700611 list->non_space_tail = NULL;
Carl Worth47252442010-05-19 13:54:37 -0700612
613 return list;
614}
615
616void
Carl Worth808401f2010-05-25 14:52:43 -0700617_token_list_append (token_list_t *list, token_t *token)
Carl Worth47252442010-05-19 13:54:37 -0700618{
619 token_node_t *node;
620
621 node = xtalloc (list, token_node_t);
Carl Worth808401f2010-05-25 14:52:43 -0700622 node->token = xtalloc_reference (list, token);
Carl Worth47252442010-05-19 13:54:37 -0700623
624 node->next = NULL;
625
626 if (list->head == NULL) {
627 list->head = node;
628 } else {
629 list->tail->next = node;
630 }
631
632 list->tail = node;
Carl Worth10ae4382010-05-25 20:35:01 -0700633 if (token->type != SPACE)
634 list->non_space_tail = node;
Carl Worth47252442010-05-19 13:54:37 -0700635}
636
637void
638_token_list_append_list (token_list_t *list, token_list_t *tail)
639{
640 if (list->head == NULL) {
641 list->head = tail->head;
642 } else {
643 list->tail->next = tail->head;
644 }
645
646 list->tail = tail->tail;
Carl Worth10ae4382010-05-25 20:35:01 -0700647 list->non_space_tail = tail->non_space_tail;
648}
649
650void
651_token_list_trim_trailing_space (token_list_t *list)
652{
653 token_node_t *tail, *next;
654
655 if (list->non_space_tail) {
656 tail = list->non_space_tail->next;
657 list->non_space_tail->next = NULL;
658 list->tail = list->non_space_tail;
659
660 while (tail) {
661 next = tail->next;
662 talloc_free (tail);
663 tail = next;
664 }
665 }
Carl Worth47252442010-05-19 13:54:37 -0700666}
Carl Worth80dc60b2010-05-25 14:42:00 -0700667
Carl Worth0197e9b2010-05-26 08:05:19 -0700668static void
669_token_print (token_t *token)
670{
671 if (token->type < 256) {
672 printf ("%c", token->type);
673 return;
674 }
675
676 switch (token->type) {
Carl Worth8fed1cd2010-05-26 09:32:12 -0700677 case INTEGER:
678 printf ("%" PRIxMAX, token->value.ival);
679 break;
Carl Worth0197e9b2010-05-26 08:05:19 -0700680 case IDENTIFIER:
681 case OTHER:
682 printf ("%s", token->value.str);
683 break;
684 case SPACE:
685 printf (" ");
686 break;
687 case LEFT_SHIFT:
688 printf ("<<");
689 break;
690 case RIGHT_SHIFT:
691 printf (">>");
692 break;
693 case LESS_OR_EQUAL:
694 printf ("<=");
695 break;
696 case GREATER_OR_EQUAL:
697 printf (">=");
698 break;
699 case EQUAL:
700 printf ("==");
701 break;
702 case NOT_EQUAL:
703 printf ("!=");
704 break;
705 case AND:
706 printf ("&&");
707 break;
708 case OR:
709 printf ("||");
710 break;
711 case PASTE:
712 printf ("##");
713 break;
714 default:
715 fprintf (stderr, "Error: Don't know how to print token type %d\n", token->type);
716 break;
717 }
718}
719
Carl Worthad0dee62010-05-26 09:04:50 -0700720/* Change 'token' into a new token formed by pasting 'other'. */
721static void
722_token_paste (token_t *token, token_t *other)
723{
724 /* A very few single-character punctuators can be combined
725 * with another to form a multi-character punctuator. */
726 switch (token->type) {
727 case '<':
728 if (other->type == '<') {
729 token->type = LEFT_SHIFT;
730 token->value.ival = LEFT_SHIFT;
731 return;
732 } else if (other->type == '=') {
733 token->type = LESS_OR_EQUAL;
734 token->value.ival = LESS_OR_EQUAL;
735 return;
736 }
737 break;
738 case '>':
739 if (other->type == '>') {
740 token->type = RIGHT_SHIFT;
741 token->value.ival = RIGHT_SHIFT;
742 return;
743 } else if (other->type == '=') {
744 token->type = GREATER_OR_EQUAL;
745 token->value.ival = GREATER_OR_EQUAL;
746 return;
747 }
748 break;
749 case '=':
750 if (other->type == '=') {
751 token->type = EQUAL;
752 token->value.ival = EQUAL;
753 return;
754 }
755 break;
756 case '!':
757 if (other->type == '=') {
758 token->type = NOT_EQUAL;
759 token->value.ival = NOT_EQUAL;
760 return;
761 }
762 break;
763 case '&':
764 if (other->type == '&') {
765 token->type = AND;
766 token->value.ival = AND;
767 return;
768 }
769 break;
770 case '|':
771 if (other->type == '|') {
772 token->type = OR;
773 token->value.ival = OR;
774 return;
775 }
776 break;
777 }
778
779 /* Two string-valued tokens can usually just be mashed
780 * together.
781 *
782 * XXX: Since our 'OTHER' case is currently so loose, this may
783 * allow some things thruogh that should be treated as
784 * errors. */
785 if ((token->type == IDENTIFIER || token->type == OTHER) &&
786 (other->type == IDENTIFIER || other->type == OTHER))
787 {
788 token->value.str = talloc_strdup_append (token->value.str,
789 other->value.str);
790 return;
791 }
792
793 printf ("Error: Pasting \"");
794 _token_print (token);
795 printf ("\" and \"");
796 _token_print (other);
797 printf ("\" does not give a valid preprocessing token.\n");
798}
799
Carl Worth0197e9b2010-05-26 08:05:19 -0700800static void
801_token_list_print (token_list_t *list)
802{
803 token_node_t *node;
804
805 if (list == NULL)
806 return;
807
808 for (node = list->head; node; node = node->next)
809 _token_print (node->token);
810}
811
Carl Worth3a37b872010-05-10 11:44:09 -0700812void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700813yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700814{
815 fprintf (stderr, "Parse error: %s\n", error);
816}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700817
Carl Worth33cc4002010-05-12 12:17:10 -0700818glcpp_parser_t *
819glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700820{
Carl Worth33cc4002010-05-12 12:17:10 -0700821 glcpp_parser_t *parser;
822
Carl Worth5070a202010-05-12 12:45:33 -0700823 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700824
Carl Worth8f38aff2010-05-19 10:01:29 -0700825 glcpp_lex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700826 parser->defines = hash_table_ctor (32, hash_table_string_hash,
827 hash_table_string_compare);
Carl Worthae6517f2010-05-25 15:24:59 -0700828 parser->active = _string_list_create (parser);
Carl Worthf34a0002010-05-25 16:59:02 -0700829 parser->space_tokens = 1;
Carl Worth5a6b9a22010-05-20 14:29:43 -0700830
Carl Worthb20d33c2010-05-20 22:27:07 -0700831 parser->skip_stack = NULL;
832
Carl Worth33cc4002010-05-12 12:17:10 -0700833 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700834}
835
836int
837glcpp_parser_parse (glcpp_parser_t *parser)
838{
839 return yyparse (parser);
840}
841
842void
Carl Worth33cc4002010-05-12 12:17:10 -0700843glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700844{
Carl Worthb20d33c2010-05-20 22:27:07 -0700845 if (parser->skip_stack)
846 fprintf (stderr, "Error: Unterminated #if\n");
Carl Worth8f38aff2010-05-19 10:01:29 -0700847 glcpp_lex_destroy (parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700848 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700849 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700850}
Carl Worthc6d5af32010-05-11 12:30:09 -0700851
Carl Worth0197e9b2010-05-26 08:05:19 -0700852/* Appends onto 'expansion' a non-macro token or the expansion of an
853 * object-like macro.
Carl Worthb1854fd2010-05-25 16:28:26 -0700854 *
Carl Worth0197e9b2010-05-26 08:05:19 -0700855 * Returns 0 if this token is completely processed.
Carl Worthb1854fd2010-05-25 16:28:26 -0700856 *
857 * Returns 1 in the case that 'token' is a function-like macro that
858 * needs further expansion.
859 */
860static int
Carl Worth0197e9b2010-05-26 08:05:19 -0700861_glcpp_parser_expand_token_onto (glcpp_parser_t *parser,
862 token_t *token,
863 token_list_t *result)
Carl Worthae6517f2010-05-25 15:24:59 -0700864{
865 const char *identifier;
866 macro_t *macro;
Carl Worth0197e9b2010-05-26 08:05:19 -0700867 token_list_t *expansion;
Carl Worthae6517f2010-05-25 15:24:59 -0700868
869 /* We only expand identifiers */
870 if (token->type != IDENTIFIER) {
Carl Worth0197e9b2010-05-26 08:05:19 -0700871 _token_list_append (result, token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700872 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700873 }
874
875 /* Look up this identifier in the hash table. */
876 identifier = token->value.str;
877 macro = hash_table_find (parser->defines, identifier);
878
Carl Worth0197e9b2010-05-26 08:05:19 -0700879 /* Not a macro, so just append. */
Carl Worthae6517f2010-05-25 15:24:59 -0700880 if (macro == NULL) {
Carl Worth0197e9b2010-05-26 08:05:19 -0700881 _token_list_append (result, token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700882 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700883 }
884
Carl Worthae6517f2010-05-25 15:24:59 -0700885 /* Finally, don't expand this macro if we're already actively
886 * expanding it, (to avoid infinite recursion). */
Carl Worthec4ada02010-05-26 08:15:49 -0700887 if (_string_list_contains (parser->active, identifier, NULL))
888 {
889 /* We change the token type here from IDENTIFIER to
890 * OTHER to prevent any future expansion of this
891 * unexpanded token. */
892 char *str;
893 token_t *new_token;
894
895 str = xtalloc_strdup (result, token->value.str);
896 new_token = _token_create_str (result, OTHER, str);
897 _token_list_append (result, new_token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700898 return 0;
899 }
900
Carl Worthc0607d52010-05-26 08:01:42 -0700901 /* For function-like macros return 1 for further processing. */
902 if (macro->is_function) {
903 return 1;
904 }
905
Carl Worthb1854fd2010-05-25 16:28:26 -0700906 _string_list_push (parser->active, identifier);
Carl Worth0197e9b2010-05-26 08:05:19 -0700907 _glcpp_parser_expand_token_list_onto (parser,
908 macro->replacements,
909 result);
Carl Worthb1854fd2010-05-25 16:28:26 -0700910 _string_list_pop (parser->active);
911
912 return 0;
913}
914
915typedef enum function_status
916{
917 FUNCTION_STATUS_SUCCESS,
918 FUNCTION_NOT_A_FUNCTION,
919 FUNCTION_UNBALANCED_PARENTHESES
920} function_status_t;
921
922/* Find a set of function-like macro arguments by looking for a
923 * balanced set of parentheses. Upon return *node will be the last
924 * consumed node, such that further processing can continue with
925 * node->next.
926 *
927 * Return values:
928 *
929 * FUNCTION_STATUS_SUCCESS:
930 *
931 * Successfully parsed a set of function arguments.
932 *
933 * FUNCTION_NOT_A_FUNCTION:
934 *
935 * Macro name not followed by a '('. This is not an error, but
936 * simply that the macro name should be treated as a non-macro.
937 *
938 * FUNCTION_UNBLANCED_PARENTHESES
939 *
940 * Macro name is not followed by a balanced set of parentheses.
941 */
942static function_status_t
Carl Worth9ce18cf2010-05-25 17:32:21 -0700943_arguments_parse (argument_list_t *arguments, token_node_t **node_ret)
Carl Worthb1854fd2010-05-25 16:28:26 -0700944{
Carl Worth9ce18cf2010-05-25 17:32:21 -0700945 token_list_t *argument;
Carl Worthb1854fd2010-05-25 16:28:26 -0700946 token_node_t *node = *node_ret, *last;
947 int paren_count;
Carl Worthb1854fd2010-05-25 16:28:26 -0700948
949 last = node;
950 node = node->next;
951
952 /* Ignore whitespace before first parenthesis. */
953 while (node && node->token->type == SPACE)
954 node = node->next;
955
956 if (node == NULL || node->token->type != '(')
957 return FUNCTION_NOT_A_FUNCTION;
958
Carl Worth652fa272010-05-25 17:45:22 -0700959 last = node;
960 node = node->next;
961
Carl Worth9ce18cf2010-05-25 17:32:21 -0700962 argument = NULL;
963
Carl Worth652fa272010-05-25 17:45:22 -0700964 for (paren_count = 1; node; last = node, node = node->next) {
Carl Worthb1854fd2010-05-25 16:28:26 -0700965 if (node->token->type == '(')
966 {
967 paren_count++;
968 }
969 else if (node->token->type == ')')
970 {
971 paren_count--;
Carl Worthc7581c22010-05-25 17:41:07 -0700972 if (paren_count == 0) {
973 last = node;
974 node = node->next;
975 break;
976 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700977 }
Carl Worth652fa272010-05-25 17:45:22 -0700978
979 if (node->token->type == ',' &&
Carl Worthb1854fd2010-05-25 16:28:26 -0700980 paren_count == 1)
981 {
Carl Worth10ae4382010-05-25 20:35:01 -0700982 if (argument)
983 _token_list_trim_trailing_space (argument);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700984 argument = NULL;
985 }
986 else {
987 if (argument == NULL) {
Carl Worthc7581c22010-05-25 17:41:07 -0700988 /* Don't treat initial whitespace as
989 * part of the arguement. */
990 if (node->token->type == SPACE)
991 continue;
Carl Worth9ce18cf2010-05-25 17:32:21 -0700992 argument = _token_list_create (arguments);
993 _argument_list_append (arguments, argument);
994 }
995 _token_list_append (argument, node->token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700996 }
Carl Worthc7581c22010-05-25 17:41:07 -0700997 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700998
999 if (node && paren_count)
1000 return FUNCTION_UNBALANCED_PARENTHESES;
1001
1002 *node_ret = last;
1003
1004 return FUNCTION_STATUS_SUCCESS;
1005}
1006
1007/* Prints the expansion of *node (consuming further tokens from the
1008 * list as necessary). Upon return *node will be the last consumed
1009 * node, such that further processing can continue with node->next. */
1010static void
Carl Worth0197e9b2010-05-26 08:05:19 -07001011_glcpp_parser_expand_function_onto (glcpp_parser_t *parser,
1012 token_node_t **node_ret,
1013 token_list_t *result)
Carl Worthb1854fd2010-05-25 16:28:26 -07001014{
1015 macro_t *macro;
1016 token_node_t *node;
1017 const char *identifier;
1018 argument_list_t *arguments;
1019 function_status_t status;
Carl Worth0197e9b2010-05-26 08:05:19 -07001020 token_list_t *substituted;
Carl Worth9ce18cf2010-05-25 17:32:21 -07001021 int parameter_index;
Carl Worthb1854fd2010-05-25 16:28:26 -07001022
1023 node = *node_ret;
1024 identifier = node->token->value.str;
1025
1026 macro = hash_table_find (parser->defines, identifier);
1027
1028 assert (macro->is_function);
1029
Carl Worth9ce18cf2010-05-25 17:32:21 -07001030 arguments = _argument_list_create (parser);
1031 status = _arguments_parse (arguments, node_ret);
Carl Worthb1854fd2010-05-25 16:28:26 -07001032
1033 switch (status) {
1034 case FUNCTION_STATUS_SUCCESS:
1035 break;
1036 case FUNCTION_NOT_A_FUNCTION:
Carl Worth0197e9b2010-05-26 08:05:19 -07001037 _token_list_append (result, node->token);
Carl Worthae6517f2010-05-25 15:24:59 -07001038 return;
Carl Worthb1854fd2010-05-25 16:28:26 -07001039 case FUNCTION_UNBALANCED_PARENTHESES:
1040 fprintf (stderr, "Error: Macro %s call has unbalanced parentheses\n",
1041 identifier);
1042 exit (1);
Carl Worthae6517f2010-05-25 15:24:59 -07001043 }
1044
Carl Worth9ce18cf2010-05-25 17:32:21 -07001045 if (macro->replacements == NULL) {
1046 talloc_free (arguments);
1047 return;
1048 }
1049
Carl Worth9ce18cf2010-05-25 17:32:21 -07001050 if (_argument_list_length (arguments) !=
1051 _string_list_length (macro->parameters))
1052 {
1053 fprintf (stderr,
1054 "Error: macro %s invoked with %d arguments (expected %d)\n",
1055 identifier,
1056 _argument_list_length (arguments),
1057 _string_list_length (macro->parameters));
1058 return;
1059 }
1060
Carl Worth0197e9b2010-05-26 08:05:19 -07001061 /* Perform argument substitution on the replacement list. */
1062 substituted = _token_list_create (arguments);
Carl Worth9ce18cf2010-05-25 17:32:21 -07001063
Carl Worthce540f22010-05-26 08:25:44 -07001064 for (node = macro->replacements->head; node; node = node->next)
1065 {
1066 if (node->token->type == IDENTIFIER &&
Carl Worth9ce18cf2010-05-25 17:32:21 -07001067 _string_list_contains (macro->parameters,
Carl Worthce540f22010-05-26 08:25:44 -07001068 node->token->value.str,
Carl Worth9ce18cf2010-05-25 17:32:21 -07001069 &parameter_index))
1070 {
1071 token_list_t *argument;
1072 argument = _argument_list_member_at (arguments,
1073 parameter_index);
Carl Worthd5cd4032010-05-26 08:09:29 -07001074 /* Before substituting, we expand the argument
1075 * tokens. */
1076 _glcpp_parser_expand_token_list_onto (parser,
1077 argument,
1078 substituted);
Carl Worth9ce18cf2010-05-25 17:32:21 -07001079 } else {
Carl Worthce540f22010-05-26 08:25:44 -07001080 _token_list_append (substituted, node->token);
Carl Worth9ce18cf2010-05-25 17:32:21 -07001081 }
1082 }
1083
Carl Worthad0dee62010-05-26 09:04:50 -07001084 /* After argument substitution, and before further expansion
1085 * below, implement token pasting. */
1086
1087 node = substituted->head;
1088 while (node)
1089 {
1090 token_node_t *next_non_space;
1091
1092 /* Look ahead for a PASTE token, skipping space. */
1093 next_non_space = node->next;
1094 while (next_non_space && next_non_space->token->type == SPACE)
1095 next_non_space = next_non_space->next;
1096
1097 if (next_non_space == NULL)
1098 break;
1099
1100 if (next_non_space->token->type != PASTE) {
1101 node = next_non_space;
1102 continue;
1103 }
1104
1105 /* Now find the next non-space token after the PASTE. */
1106 next_non_space = next_non_space->next;
1107 while (next_non_space && next_non_space->token->type == SPACE)
1108 next_non_space = next_non_space->next;
1109
1110 if (next_non_space == NULL) {
1111 fprintf (stderr, "Error: '##' cannot appear at either end of a macro expansion\n");
1112 exit (1);
1113 }
1114
1115 _token_paste (node->token, next_non_space->token);
1116 node->next = next_non_space->next;
1117
1118 node = node->next;
1119 }
1120
Carl Worthae6517f2010-05-25 15:24:59 -07001121 _string_list_push (parser->active, identifier);
Carl Worth0197e9b2010-05-26 08:05:19 -07001122 _glcpp_parser_expand_token_list_onto (parser, substituted, result);
Carl Worthae6517f2010-05-25 15:24:59 -07001123 _string_list_pop (parser->active);
Carl Worth9ce18cf2010-05-25 17:32:21 -07001124
1125 talloc_free (arguments);
Carl Worthae6517f2010-05-25 15:24:59 -07001126}
1127
Carl Worth0197e9b2010-05-26 08:05:19 -07001128static void
1129_glcpp_parser_expand_token_list_onto (glcpp_parser_t *parser,
1130 token_list_t *list,
1131 token_list_t *result)
1132{
1133 token_node_t *node;
1134
1135 if (list == NULL)
1136 return;
1137
1138 for (node = list->head; node; node = node->next)
1139 {
1140 if (_glcpp_parser_expand_token_onto (parser, node->token,
1141 result))
1142 {
1143 _glcpp_parser_expand_function_onto (parser, &node,
1144 result);
1145 }
1146 }
1147}
1148
Carl Worthae6517f2010-05-25 15:24:59 -07001149void
1150_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
1151 token_list_t *list)
1152{
Carl Worth0197e9b2010-05-26 08:05:19 -07001153 token_list_t *expanded;
Carl Worthae6517f2010-05-25 15:24:59 -07001154 token_node_t *node;
Carl Worthb1854fd2010-05-25 16:28:26 -07001155 function_status_t function_status;
Carl Worthae6517f2010-05-25 15:24:59 -07001156
1157 if (list == NULL)
1158 return;
1159
Carl Worth0197e9b2010-05-26 08:05:19 -07001160 expanded = _token_list_create (parser);
Carl Worth10ae4382010-05-25 20:35:01 -07001161
Carl Worth0197e9b2010-05-26 08:05:19 -07001162 _glcpp_parser_expand_token_list_onto (parser, list, expanded);
1163
1164 _token_list_trim_trailing_space (expanded);
1165
1166 _token_list_print (expanded);
1167
1168 talloc_free (expanded);
Carl Worthae6517f2010-05-25 15:24:59 -07001169}
1170
1171void
Carl Worthfcbbb462010-05-13 09:36:23 -07001172_define_object_macro (glcpp_parser_t *parser,
1173 const char *identifier,
Carl Worth47252442010-05-19 13:54:37 -07001174 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -07001175{
1176 macro_t *macro;
1177
1178 macro = xtalloc (parser, macro_t);
1179
1180 macro->is_function = 0;
Carl Worthc5e98552010-05-14 10:12:21 -07001181 macro->parameters = NULL;
Carl Wortha807fb72010-05-18 22:10:04 -07001182 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -07001183 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -07001184
1185 hash_table_insert (parser->defines, macro, identifier);
1186}
1187
1188void
1189_define_function_macro (glcpp_parser_t *parser,
1190 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -07001191 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -07001192 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -07001193{
1194 macro_t *macro;
1195
1196 macro = xtalloc (parser, macro_t);
1197
1198 macro->is_function = 1;
Carl Worthc5e98552010-05-14 10:12:21 -07001199 macro->parameters = talloc_steal (macro, parameters);
Carl Wortha807fb72010-05-18 22:10:04 -07001200 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -07001201 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -07001202
1203 hash_table_insert (parser->defines, macro, identifier);
1204}
1205
Carl Worth8f38aff2010-05-19 10:01:29 -07001206static int
Carl Worth0293b2e2010-05-19 10:05:40 -07001207glcpp_parser_lex (glcpp_parser_t *parser)
Carl Worth8f38aff2010-05-19 10:01:29 -07001208{
Carl Worth5aa7ea02010-05-25 18:39:43 -07001209 return glcpp_lex (parser->scanner);
Carl Worth8f38aff2010-05-19 10:01:29 -07001210}
Carl Worthb20d33c2010-05-20 22:27:07 -07001211
1212static void
1213_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition)
1214{
1215 skip_type_t current = SKIP_NO_SKIP;
1216 skip_node_t *node;
1217
1218 if (parser->skip_stack)
1219 current = parser->skip_stack->type;
1220
1221 node = xtalloc (parser, skip_node_t);
1222
1223 if (current == SKIP_NO_SKIP) {
1224 if (condition)
1225 node->type = SKIP_NO_SKIP;
1226 else
1227 node->type = SKIP_TO_ELSE;
1228 } else {
1229 node->type = SKIP_TO_ENDIF;
1230 }
1231
1232 node->next = parser->skip_stack;
1233 parser->skip_stack = node;
1234}
1235
1236static void
1237_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
1238 int condition)
1239{
1240 if (parser->skip_stack == NULL) {
1241 fprintf (stderr, "Error: %s without #if\n", type);
1242 exit (1);
1243 }
1244
1245 if (parser->skip_stack->type == SKIP_TO_ELSE) {
1246 if (condition)
1247 parser->skip_stack->type = SKIP_NO_SKIP;
1248 } else {
1249 parser->skip_stack->type = SKIP_TO_ENDIF;
1250 }
1251}
Carl Worth80dc60b2010-05-25 14:42:00 -07001252
Carl Worthb20d33c2010-05-20 22:27:07 -07001253static void
1254_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser)
1255{
1256 skip_node_t *node;
1257
1258 if (parser->skip_stack == NULL) {
1259 fprintf (stderr, "Error: #endif without #if\n");
1260 exit (1);
1261 }
1262
1263 node = parser->skip_stack;
1264 parser->skip_stack = node->next;
1265 talloc_free (node);
1266}