blob: 5f59b5b006f388731e4faa246530236a350260a5 [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
589static void
590_token_list_print (token_list_t *list)
591{
592 token_node_t *node;
593
594 if (list == NULL)
595 return;
596
597 for (node = list->head; node; node = node->next)
598 _token_print (node->token);
599}
600
Carl Worth3a37b872010-05-10 11:44:09 -0700601void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700602yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700603{
604 fprintf (stderr, "Parse error: %s\n", error);
605}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700606
Carl Worth33cc4002010-05-12 12:17:10 -0700607glcpp_parser_t *
608glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700609{
Carl Worth33cc4002010-05-12 12:17:10 -0700610 glcpp_parser_t *parser;
611
Carl Worth5070a202010-05-12 12:45:33 -0700612 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700613
Carl Worth8f38aff2010-05-19 10:01:29 -0700614 glcpp_lex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700615 parser->defines = hash_table_ctor (32, hash_table_string_hash,
616 hash_table_string_compare);
Carl Worthae6517f2010-05-25 15:24:59 -0700617 parser->active = _string_list_create (parser);
Carl Worthf34a0002010-05-25 16:59:02 -0700618 parser->space_tokens = 1;
Carl Worth5a6b9a22010-05-20 14:29:43 -0700619
Carl Worthb20d33c2010-05-20 22:27:07 -0700620 parser->skip_stack = NULL;
621
Carl Worth33cc4002010-05-12 12:17:10 -0700622 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700623}
624
625int
626glcpp_parser_parse (glcpp_parser_t *parser)
627{
628 return yyparse (parser);
629}
630
631void
Carl Worth33cc4002010-05-12 12:17:10 -0700632glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700633{
Carl Worthb20d33c2010-05-20 22:27:07 -0700634 if (parser->skip_stack)
635 fprintf (stderr, "Error: Unterminated #if\n");
Carl Worth8f38aff2010-05-19 10:01:29 -0700636 glcpp_lex_destroy (parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700637 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700638 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700639}
Carl Worthc6d5af32010-05-11 12:30:09 -0700640
Carl Worth0197e9b2010-05-26 08:05:19 -0700641/* Appends onto 'expansion' a non-macro token or the expansion of an
642 * object-like macro.
Carl Worthb1854fd2010-05-25 16:28:26 -0700643 *
Carl Worth0197e9b2010-05-26 08:05:19 -0700644 * Returns 0 if this token is completely processed.
Carl Worthb1854fd2010-05-25 16:28:26 -0700645 *
646 * Returns 1 in the case that 'token' is a function-like macro that
647 * needs further expansion.
648 */
649static int
Carl Worth0197e9b2010-05-26 08:05:19 -0700650_glcpp_parser_expand_token_onto (glcpp_parser_t *parser,
651 token_t *token,
652 token_list_t *result)
Carl Worthae6517f2010-05-25 15:24:59 -0700653{
654 const char *identifier;
655 macro_t *macro;
Carl Worth0197e9b2010-05-26 08:05:19 -0700656 token_list_t *expansion;
Carl Worthae6517f2010-05-25 15:24:59 -0700657
658 /* We only expand identifiers */
659 if (token->type != IDENTIFIER) {
Carl Worth0197e9b2010-05-26 08:05:19 -0700660 _token_list_append (result, token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700661 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700662 }
663
664 /* Look up this identifier in the hash table. */
665 identifier = token->value.str;
666 macro = hash_table_find (parser->defines, identifier);
667
Carl Worth0197e9b2010-05-26 08:05:19 -0700668 /* Not a macro, so just append. */
Carl Worthae6517f2010-05-25 15:24:59 -0700669 if (macro == NULL) {
Carl Worth0197e9b2010-05-26 08:05:19 -0700670 _token_list_append (result, token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700671 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700672 }
673
Carl Worthae6517f2010-05-25 15:24:59 -0700674 /* Finally, don't expand this macro if we're already actively
675 * expanding it, (to avoid infinite recursion). */
Carl Worthec4ada02010-05-26 08:15:49 -0700676 if (_string_list_contains (parser->active, identifier, NULL))
677 {
678 /* We change the token type here from IDENTIFIER to
679 * OTHER to prevent any future expansion of this
680 * unexpanded token. */
681 char *str;
682 token_t *new_token;
683
684 str = xtalloc_strdup (result, token->value.str);
685 new_token = _token_create_str (result, OTHER, str);
686 _token_list_append (result, new_token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700687 return 0;
688 }
689
Carl Worthc0607d52010-05-26 08:01:42 -0700690 /* For function-like macros return 1 for further processing. */
691 if (macro->is_function) {
692 return 1;
693 }
694
Carl Worthb1854fd2010-05-25 16:28:26 -0700695 _string_list_push (parser->active, identifier);
Carl Worth0197e9b2010-05-26 08:05:19 -0700696 _glcpp_parser_expand_token_list_onto (parser,
697 macro->replacements,
698 result);
Carl Worthb1854fd2010-05-25 16:28:26 -0700699 _string_list_pop (parser->active);
700
701 return 0;
702}
703
704typedef enum function_status
705{
706 FUNCTION_STATUS_SUCCESS,
707 FUNCTION_NOT_A_FUNCTION,
708 FUNCTION_UNBALANCED_PARENTHESES
709} function_status_t;
710
711/* Find a set of function-like macro arguments by looking for a
712 * balanced set of parentheses. Upon return *node will be the last
713 * consumed node, such that further processing can continue with
714 * node->next.
715 *
716 * Return values:
717 *
718 * FUNCTION_STATUS_SUCCESS:
719 *
720 * Successfully parsed a set of function arguments.
721 *
722 * FUNCTION_NOT_A_FUNCTION:
723 *
724 * Macro name not followed by a '('. This is not an error, but
725 * simply that the macro name should be treated as a non-macro.
726 *
727 * FUNCTION_UNBLANCED_PARENTHESES
728 *
729 * Macro name is not followed by a balanced set of parentheses.
730 */
731static function_status_t
Carl Worth9ce18cf2010-05-25 17:32:21 -0700732_arguments_parse (argument_list_t *arguments, token_node_t **node_ret)
Carl Worthb1854fd2010-05-25 16:28:26 -0700733{
Carl Worth9ce18cf2010-05-25 17:32:21 -0700734 token_list_t *argument;
Carl Worthb1854fd2010-05-25 16:28:26 -0700735 token_node_t *node = *node_ret, *last;
736 int paren_count;
Carl Worthb1854fd2010-05-25 16:28:26 -0700737
738 last = node;
739 node = node->next;
740
741 /* Ignore whitespace before first parenthesis. */
742 while (node && node->token->type == SPACE)
743 node = node->next;
744
745 if (node == NULL || node->token->type != '(')
746 return FUNCTION_NOT_A_FUNCTION;
747
Carl Worth652fa272010-05-25 17:45:22 -0700748 last = node;
749 node = node->next;
750
Carl Worth9ce18cf2010-05-25 17:32:21 -0700751 argument = NULL;
752
Carl Worth652fa272010-05-25 17:45:22 -0700753 for (paren_count = 1; node; last = node, node = node->next) {
Carl Worthb1854fd2010-05-25 16:28:26 -0700754 if (node->token->type == '(')
755 {
756 paren_count++;
757 }
758 else if (node->token->type == ')')
759 {
760 paren_count--;
Carl Worthc7581c22010-05-25 17:41:07 -0700761 if (paren_count == 0) {
762 last = node;
763 node = node->next;
764 break;
765 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700766 }
Carl Worth652fa272010-05-25 17:45:22 -0700767
768 if (node->token->type == ',' &&
Carl Worthb1854fd2010-05-25 16:28:26 -0700769 paren_count == 1)
770 {
Carl Worth10ae4382010-05-25 20:35:01 -0700771 if (argument)
772 _token_list_trim_trailing_space (argument);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700773 argument = NULL;
774 }
775 else {
776 if (argument == NULL) {
Carl Worthc7581c22010-05-25 17:41:07 -0700777 /* Don't treat initial whitespace as
778 * part of the arguement. */
779 if (node->token->type == SPACE)
780 continue;
Carl Worth9ce18cf2010-05-25 17:32:21 -0700781 argument = _token_list_create (arguments);
782 _argument_list_append (arguments, argument);
783 }
784 _token_list_append (argument, node->token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700785 }
Carl Worthc7581c22010-05-25 17:41:07 -0700786 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700787
788 if (node && paren_count)
789 return FUNCTION_UNBALANCED_PARENTHESES;
790
791 *node_ret = last;
792
793 return FUNCTION_STATUS_SUCCESS;
794}
795
796/* Prints the expansion of *node (consuming further tokens from the
797 * list as necessary). Upon return *node will be the last consumed
798 * node, such that further processing can continue with node->next. */
799static void
Carl Worth0197e9b2010-05-26 08:05:19 -0700800_glcpp_parser_expand_function_onto (glcpp_parser_t *parser,
801 token_node_t **node_ret,
802 token_list_t *result)
Carl Worthb1854fd2010-05-25 16:28:26 -0700803{
804 macro_t *macro;
805 token_node_t *node;
806 const char *identifier;
807 argument_list_t *arguments;
808 function_status_t status;
Carl Worth0197e9b2010-05-26 08:05:19 -0700809 token_list_t *substituted;
Carl Worth9ce18cf2010-05-25 17:32:21 -0700810 int parameter_index;
Carl Worthb1854fd2010-05-25 16:28:26 -0700811
812 node = *node_ret;
813 identifier = node->token->value.str;
814
815 macro = hash_table_find (parser->defines, identifier);
816
817 assert (macro->is_function);
818
Carl Worth9ce18cf2010-05-25 17:32:21 -0700819 arguments = _argument_list_create (parser);
820 status = _arguments_parse (arguments, node_ret);
Carl Worthb1854fd2010-05-25 16:28:26 -0700821
822 switch (status) {
823 case FUNCTION_STATUS_SUCCESS:
824 break;
825 case FUNCTION_NOT_A_FUNCTION:
Carl Worth0197e9b2010-05-26 08:05:19 -0700826 _token_list_append (result, node->token);
Carl Worthae6517f2010-05-25 15:24:59 -0700827 return;
Carl Worthb1854fd2010-05-25 16:28:26 -0700828 case FUNCTION_UNBALANCED_PARENTHESES:
829 fprintf (stderr, "Error: Macro %s call has unbalanced parentheses\n",
830 identifier);
831 exit (1);
Carl Worthae6517f2010-05-25 15:24:59 -0700832 }
833
Carl Worth9ce18cf2010-05-25 17:32:21 -0700834 if (macro->replacements == NULL) {
835 talloc_free (arguments);
836 return;
837 }
838
Carl Worth9ce18cf2010-05-25 17:32:21 -0700839 if (_argument_list_length (arguments) !=
840 _string_list_length (macro->parameters))
841 {
842 fprintf (stderr,
843 "Error: macro %s invoked with %d arguments (expected %d)\n",
844 identifier,
845 _argument_list_length (arguments),
846 _string_list_length (macro->parameters));
847 return;
848 }
849
Carl Worth0197e9b2010-05-26 08:05:19 -0700850 /* Perform argument substitution on the replacement list. */
851 substituted = _token_list_create (arguments);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700852
Carl Worthce540f22010-05-26 08:25:44 -0700853 for (node = macro->replacements->head; node; node = node->next)
854 {
855 if (node->token->type == IDENTIFIER &&
Carl Worth9ce18cf2010-05-25 17:32:21 -0700856 _string_list_contains (macro->parameters,
Carl Worthce540f22010-05-26 08:25:44 -0700857 node->token->value.str,
Carl Worth9ce18cf2010-05-25 17:32:21 -0700858 &parameter_index))
859 {
860 token_list_t *argument;
861 argument = _argument_list_member_at (arguments,
862 parameter_index);
Carl Worthd5cd4032010-05-26 08:09:29 -0700863 /* Before substituting, we expand the argument
864 * tokens. */
865 _glcpp_parser_expand_token_list_onto (parser,
866 argument,
867 substituted);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700868 } else {
Carl Worthce540f22010-05-26 08:25:44 -0700869 _token_list_append (substituted, node->token);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700870 }
871 }
872
Carl Worthae6517f2010-05-25 15:24:59 -0700873 _string_list_push (parser->active, identifier);
Carl Worth0197e9b2010-05-26 08:05:19 -0700874 _glcpp_parser_expand_token_list_onto (parser, substituted, result);
Carl Worthae6517f2010-05-25 15:24:59 -0700875 _string_list_pop (parser->active);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700876
877 talloc_free (arguments);
Carl Worthae6517f2010-05-25 15:24:59 -0700878}
879
Carl Worth0197e9b2010-05-26 08:05:19 -0700880static void
881_glcpp_parser_expand_token_list_onto (glcpp_parser_t *parser,
882 token_list_t *list,
883 token_list_t *result)
884{
885 token_node_t *node;
886
887 if (list == NULL)
888 return;
889
890 for (node = list->head; node; node = node->next)
891 {
892 if (_glcpp_parser_expand_token_onto (parser, node->token,
893 result))
894 {
895 _glcpp_parser_expand_function_onto (parser, &node,
896 result);
897 }
898 }
899}
900
Carl Worthae6517f2010-05-25 15:24:59 -0700901void
902_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
903 token_list_t *list)
904{
Carl Worth0197e9b2010-05-26 08:05:19 -0700905 token_list_t *expanded;
Carl Worthae6517f2010-05-25 15:24:59 -0700906 token_node_t *node;
Carl Worthb1854fd2010-05-25 16:28:26 -0700907 function_status_t function_status;
Carl Worthae6517f2010-05-25 15:24:59 -0700908
909 if (list == NULL)
910 return;
911
Carl Worth0197e9b2010-05-26 08:05:19 -0700912 expanded = _token_list_create (parser);
Carl Worth10ae4382010-05-25 20:35:01 -0700913
Carl Worth0197e9b2010-05-26 08:05:19 -0700914 _glcpp_parser_expand_token_list_onto (parser, list, expanded);
915
916 _token_list_trim_trailing_space (expanded);
917
918 _token_list_print (expanded);
919
920 talloc_free (expanded);
Carl Worthae6517f2010-05-25 15:24:59 -0700921}
922
923void
Carl Worthfcbbb462010-05-13 09:36:23 -0700924_define_object_macro (glcpp_parser_t *parser,
925 const char *identifier,
Carl Worth47252442010-05-19 13:54:37 -0700926 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700927{
928 macro_t *macro;
929
930 macro = xtalloc (parser, macro_t);
931
932 macro->is_function = 0;
Carl Worthc5e98552010-05-14 10:12:21 -0700933 macro->parameters = NULL;
Carl Wortha807fb72010-05-18 22:10:04 -0700934 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700935 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700936
937 hash_table_insert (parser->defines, macro, identifier);
938}
939
940void
941_define_function_macro (glcpp_parser_t *parser,
942 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -0700943 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -0700944 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700945{
946 macro_t *macro;
947
948 macro = xtalloc (parser, macro_t);
949
950 macro->is_function = 1;
Carl Worthc5e98552010-05-14 10:12:21 -0700951 macro->parameters = talloc_steal (macro, parameters);
Carl Wortha807fb72010-05-18 22:10:04 -0700952 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700953 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700954
955 hash_table_insert (parser->defines, macro, identifier);
956}
957
Carl Worth8f38aff2010-05-19 10:01:29 -0700958static int
Carl Worth0293b2e2010-05-19 10:05:40 -0700959glcpp_parser_lex (glcpp_parser_t *parser)
Carl Worth8f38aff2010-05-19 10:01:29 -0700960{
Carl Worth5aa7ea02010-05-25 18:39:43 -0700961 return glcpp_lex (parser->scanner);
Carl Worth8f38aff2010-05-19 10:01:29 -0700962}
Carl Worthb20d33c2010-05-20 22:27:07 -0700963
964static void
965_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition)
966{
967 skip_type_t current = SKIP_NO_SKIP;
968 skip_node_t *node;
969
970 if (parser->skip_stack)
971 current = parser->skip_stack->type;
972
973 node = xtalloc (parser, skip_node_t);
974
975 if (current == SKIP_NO_SKIP) {
976 if (condition)
977 node->type = SKIP_NO_SKIP;
978 else
979 node->type = SKIP_TO_ELSE;
980 } else {
981 node->type = SKIP_TO_ENDIF;
982 }
983
984 node->next = parser->skip_stack;
985 parser->skip_stack = node;
986}
987
988static void
989_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
990 int condition)
991{
992 if (parser->skip_stack == NULL) {
993 fprintf (stderr, "Error: %s without #if\n", type);
994 exit (1);
995 }
996
997 if (parser->skip_stack->type == SKIP_TO_ELSE) {
998 if (condition)
999 parser->skip_stack->type = SKIP_NO_SKIP;
1000 } else {
1001 parser->skip_stack->type = SKIP_TO_ENDIF;
1002 }
1003}
Carl Worth80dc60b2010-05-25 14:42:00 -07001004
Carl Worthb20d33c2010-05-20 22:27:07 -07001005static void
1006_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser)
1007{
1008 skip_node_t *node;
1009
1010 if (parser->skip_stack == NULL) {
1011 fprintf (stderr, "Error: #endif without #if\n");
1012 exit (1);
1013 }
1014
1015 node = parser->skip_stack;
1016 parser->skip_stack = node->next;
1017 talloc_free (node);
1018}