blob: ec104330631b4d650bb93c6967ab6a54856da9ca [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
Carl Worth3ff81672010-05-25 13:09:03 -0700135 /* Stale stuff just to allow code to compile. */
136%token IDENTIFIER_FINALIZED FUNC_MACRO OBJ_MACRO
Carl Worth796e1f02010-05-17 12:45:16 -0700137
Carl Worth3a37b872010-05-10 11:44:09 -0700138%%
139
Carl Worth33cc4002010-05-12 12:17:10 -0700140input:
Carl Worth3ff81672010-05-25 13:09:03 -0700141 /* empty */
Carl Worthae6517f2010-05-25 15:24:59 -0700142| input line {
143 printf ("\n");
144 }
Carl Worth3a37b872010-05-10 11:44:09 -0700145;
146
Carl Worth3ff81672010-05-25 13:09:03 -0700147line:
148 control_line
Carl Worth808401f2010-05-25 14:52:43 -0700149| text_line {
Carl Worthae6517f2010-05-25 15:24:59 -0700150 _glcpp_parser_print_expanded_token_list (parser, $1);
Carl Worth808401f2010-05-25 14:52:43 -0700151 talloc_free ($1);
152 }
Carl Worth3ff81672010-05-25 13:09:03 -0700153| HASH non_directive
Carl Worthcd27e642010-05-12 13:11:50 -0700154;
155
Carl Worth3ff81672010-05-25 13:09:03 -0700156control_line:
Carl Worthf34a0002010-05-25 16:59:02 -0700157 HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
Carl Worthae6517f2010-05-25 15:24:59 -0700158 _define_object_macro (parser, $2, $3);
159 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700160| HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
161 _define_function_macro (parser, $2, NULL, $5);
162 }
163| HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
164 _define_function_macro (parser, $2, $4, $6);
165 }
Carl Worthe6fb7822010-05-25 15:28:58 -0700166| HASH_UNDEF IDENTIFIER NEWLINE {
167 string_list_t *macro = hash_table_find (parser->defines, $2);
168 if (macro) {
169 /* XXX: Need hash table to support a real way
170 * to remove an element rather than prefixing
171 * a new node with data of NULL like this. */
172 hash_table_insert (parser->defines, NULL, $2);
173 talloc_free (macro);
174 }
175 talloc_free ($2);
176 }
Carl Worth3ff81672010-05-25 13:09:03 -0700177| HASH NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700178;
179
Carl Worth3ff81672010-05-25 13:09:03 -0700180identifier_list:
Carl Worthb1854fd2010-05-25 16:28:26 -0700181 IDENTIFIER {
182 $$ = _string_list_create (parser);
183 _string_list_append_item ($$, $1);
184 talloc_steal ($$, $1);
185 }
186| identifier_list ',' IDENTIFIER {
187 $$ = $1;
188 _string_list_append_item ($$, $3);
189 talloc_steal ($$, $3);
190 }
Carl Worthfcbbb462010-05-13 09:36:23 -0700191;
192
Carl Worth3ff81672010-05-25 13:09:03 -0700193text_line:
Carl Worth808401f2010-05-25 14:52:43 -0700194 NEWLINE { $$ = NULL; }
Carl Worth3ff81672010-05-25 13:09:03 -0700195| pp_tokens NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700196;
197
Carl Worth3ff81672010-05-25 13:09:03 -0700198non_directive:
199 pp_tokens NEWLINE
Carl Worthfcbbb462010-05-13 09:36:23 -0700200;
201
Carl Worthaaa9acb2010-05-19 13:28:24 -0700202replacement_list:
Carl Worth808401f2010-05-25 14:52:43 -0700203 /* empty */ { $$ = NULL; }
Carl Worth3ff81672010-05-25 13:09:03 -0700204| pp_tokens
Carl Worthaaa9acb2010-05-19 13:28:24 -0700205;
206
Carl Worthaaa9acb2010-05-19 13:28:24 -0700207pp_tokens:
Carl Worth808401f2010-05-25 14:52:43 -0700208 preprocessing_token {
Carl Worthf34a0002010-05-25 16:59:02 -0700209 parser->space_tokens = 1;
Carl Worth808401f2010-05-25 14:52:43 -0700210 $$ = _token_list_create (parser);
211 _token_list_append ($$, $1);
212 talloc_unlink (parser, $1);
213 }
214| pp_tokens preprocessing_token {
215 $$ = $1;
216 _token_list_append ($$, $2);
217 talloc_unlink (parser, $2);
218 }
Carl Worthaaa9acb2010-05-19 13:28:24 -0700219;
220
Carl Worth3ff81672010-05-25 13:09:03 -0700221preprocessing_token:
Carl Worth808401f2010-05-25 14:52:43 -0700222 IDENTIFIER {
223 $$ = _token_create_str (parser, IDENTIFIER, $1);
224 }
225| punctuator {
226 $$ = _token_create_ival (parser, $1, $1);
227 }
228| OTHER {
229 $$ = _token_create_str (parser, OTHER, $1);
230 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700231| SPACE {
Carl Worthe9397862010-05-25 17:08:07 -0700232 $$ = _token_create_ival (parser, SPACE, SPACE);
Carl Worthb1854fd2010-05-25 16:28:26 -0700233 }
Carl Worth3ff81672010-05-25 13:09:03 -0700234;
235
236punctuator:
Carl Worth808401f2010-05-25 14:52:43 -0700237 '[' { $$ = '['; }
238| ']' { $$ = ']'; }
239| '(' { $$ = '('; }
240| ')' { $$ = ')'; }
241| '{' { $$ = '{'; }
242| '}' { $$ = '}'; }
243| '.' { $$ = '.'; }
244| '&' { $$ = '&'; }
245| '*' { $$ = '*'; }
246| '+' { $$ = '+'; }
247| '-' { $$ = '-'; }
248| '~' { $$ = '~'; }
249| '!' { $$ = '!'; }
250| '/' { $$ = '/'; }
251| '%' { $$ = '%'; }
252| LEFT_SHIFT { $$ = LEFT_SHIFT; }
253| RIGHT_SHIFT { $$ = RIGHT_SHIFT; }
254| '<' { $$ = '<'; }
255| '>' { $$ = '>'; }
256| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; }
257| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; }
258| EQUAL { $$ = EQUAL; }
259| NOT_EQUAL { $$ = NOT_EQUAL; }
260| '^' { $$ = '^'; }
261| '|' { $$ = '|'; }
262| AND { $$ = AND; }
263| OR { $$ = OR; }
264| ';' { $$ = ';'; }
265| ',' { $$ = ','; }
266| PASTE { $$ = PASTE; }
Carl Worth3ff81672010-05-25 13:09:03 -0700267;
268
Carl Worth33cc4002010-05-12 12:17:10 -0700269%%
270
Carl Worth610053b2010-05-14 10:05:11 -0700271string_list_t *
272_string_list_create (void *ctx)
Carl Worth33cc4002010-05-12 12:17:10 -0700273{
Carl Worth610053b2010-05-14 10:05:11 -0700274 string_list_t *list;
Carl Worth33cc4002010-05-12 12:17:10 -0700275
Carl Worth610053b2010-05-14 10:05:11 -0700276 list = xtalloc (ctx, string_list_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700277 list->head = NULL;
278 list->tail = NULL;
279
280 return list;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700281}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700282
Carl Worth33cc4002010-05-12 12:17:10 -0700283void
Carl Worth610053b2010-05-14 10:05:11 -0700284_string_list_append_list (string_list_t *list, string_list_t *tail)
Carl Worthfcbbb462010-05-13 09:36:23 -0700285{
286 if (list->head == NULL) {
287 list->head = tail->head;
288 } else {
289 list->tail->next = tail->head;
290 }
291
292 list->tail = tail->tail;
293}
294
295void
Carl Worth610053b2010-05-14 10:05:11 -0700296_string_list_append_item (string_list_t *list, const char *str)
Carl Worth33cc4002010-05-12 12:17:10 -0700297{
Carl Worth610053b2010-05-14 10:05:11 -0700298 string_node_t *node;
Carl Worth3a37b872010-05-10 11:44:09 -0700299
Carl Worth610053b2010-05-14 10:05:11 -0700300 node = xtalloc (list, string_node_t);
Carl Worth5070a202010-05-12 12:45:33 -0700301 node->str = xtalloc_strdup (node, str);
Carl Worth80dc60b2010-05-25 14:42:00 -0700302
Carl Worth33cc4002010-05-12 12:17:10 -0700303 node->next = NULL;
304
305 if (list->head == NULL) {
306 list->head = node;
307 } else {
308 list->tail->next = node;
309 }
310
311 list->tail = node;
312}
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700313
Carl Worthae6517f2010-05-25 15:24:59 -0700314void
315_string_list_push (string_list_t *list, const char *str)
316{
317 string_node_t *node;
318
319 node = xtalloc (list, string_node_t);
320 node->str = xtalloc_strdup (node, str);
321 node->next = list->head;
322
323 if (list->tail == NULL) {
324 list->tail = node;
325 }
326 list->head = node;
327}
328
329void
330_string_list_pop (string_list_t *list)
331{
332 string_node_t *node;
333
334 node = list->head;
335
336 if (node == NULL) {
337 fprintf (stderr, "Internal error: _string_list_pop called on an empty list.\n");
338 exit (1);
339 }
340
341 list->head = node->next;
342 if (list->tail == node) {
343 assert (node->next == NULL);
344 list->tail = NULL;
345 }
346
347 talloc_free (node);
348}
349
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700350int
Carl Worth610053b2010-05-14 10:05:11 -0700351_string_list_contains (string_list_t *list, const char *member, int *index)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700352{
Carl Worth610053b2010-05-14 10:05:11 -0700353 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700354 int i;
355
356 if (list == NULL)
357 return 0;
358
359 for (i = 0, node = list->head; node; i++, node = node->next) {
360 if (strcmp (node->str, member) == 0) {
Carl Worth420d05a2010-05-17 10:15:23 -0700361 if (index)
362 *index = i;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700363 return 1;
364 }
365 }
366
367 return 0;
368}
369
370int
Carl Worth610053b2010-05-14 10:05:11 -0700371_string_list_length (string_list_t *list)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700372{
373 int length = 0;
Carl Worth610053b2010-05-14 10:05:11 -0700374 string_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700375
376 if (list == NULL)
377 return 0;
378
379 for (node = list->head; node; node = node->next)
380 length++;
381
382 return length;
383}
384
Carl Worth8f6a8282010-05-14 10:44:19 -0700385argument_list_t *
386_argument_list_create (void *ctx)
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700387{
Carl Worth8f6a8282010-05-14 10:44:19 -0700388 argument_list_t *list;
389
390 list = xtalloc (ctx, argument_list_t);
391 list->head = NULL;
392 list->tail = NULL;
393
394 return list;
395}
396
397void
Carl Worth47252442010-05-19 13:54:37 -0700398_argument_list_append (argument_list_t *list, token_list_t *argument)
Carl Worth8f6a8282010-05-14 10:44:19 -0700399{
400 argument_node_t *node;
401
Carl Worth8f6a8282010-05-14 10:44:19 -0700402 node = xtalloc (list, argument_node_t);
403 node->argument = argument;
404
405 node->next = NULL;
406
407 if (list->head == NULL) {
408 list->head = node;
409 } else {
410 list->tail->next = node;
411 }
412
413 list->tail = node;
414}
415
416int
417_argument_list_length (argument_list_t *list)
418{
419 int length = 0;
420 argument_node_t *node;
421
422 if (list == NULL)
423 return 0;
424
425 for (node = list->head; node; node = node->next)
426 length++;
427
428 return length;
429}
430
Carl Worth47252442010-05-19 13:54:37 -0700431token_list_t *
Carl Worth8f6a8282010-05-14 10:44:19 -0700432_argument_list_member_at (argument_list_t *list, int index)
433{
434 argument_node_t *node;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700435 int i;
436
437 if (list == NULL)
438 return NULL;
439
440 node = list->head;
441 for (i = 0; i < index; i++) {
442 node = node->next;
443 if (node == NULL)
444 break;
445 }
446
447 if (node)
Carl Worth8f6a8282010-05-14 10:44:19 -0700448 return node->argument;
Carl Worthdcc2ecd2010-05-13 12:56:42 -0700449
450 return NULL;
451}
Carl Worth47252442010-05-19 13:54:37 -0700452
Carl Worth808401f2010-05-25 14:52:43 -0700453/* Note: This function talloc_steal()s the str pointer. */
454token_t *
455_token_create_str (void *ctx, int type, char *str)
456{
457 token_t *token;
458
459 token = xtalloc (ctx, token_t);
460 token->type = type;
461 token->value.str = talloc_steal (token, str);
462
463 return token;
464}
465
466token_t *
467_token_create_ival (void *ctx, int type, int ival)
468{
469 token_t *token;
470
471 token = xtalloc (ctx, token_t);
472 token->type = type;
473 token->value.ival = ival;
474
475 return token;
476}
477
Carl Worth47252442010-05-19 13:54:37 -0700478token_list_t *
479_token_list_create (void *ctx)
480{
481 token_list_t *list;
482
483 list = xtalloc (ctx, token_list_t);
484 list->head = NULL;
485 list->tail = NULL;
Carl Worth10ae4382010-05-25 20:35:01 -0700486 list->non_space_tail = NULL;
Carl Worth47252442010-05-19 13:54:37 -0700487
488 return list;
489}
490
491void
Carl Worth808401f2010-05-25 14:52:43 -0700492_token_list_append (token_list_t *list, token_t *token)
Carl Worth47252442010-05-19 13:54:37 -0700493{
494 token_node_t *node;
495
496 node = xtalloc (list, token_node_t);
Carl Worth808401f2010-05-25 14:52:43 -0700497 node->token = xtalloc_reference (list, token);
Carl Worth47252442010-05-19 13:54:37 -0700498
499 node->next = NULL;
500
501 if (list->head == NULL) {
502 list->head = node;
503 } else {
504 list->tail->next = node;
505 }
506
507 list->tail = node;
Carl Worth10ae4382010-05-25 20:35:01 -0700508 if (token->type != SPACE)
509 list->non_space_tail = node;
Carl Worth47252442010-05-19 13:54:37 -0700510}
511
512void
513_token_list_append_list (token_list_t *list, token_list_t *tail)
514{
515 if (list->head == NULL) {
516 list->head = tail->head;
517 } else {
518 list->tail->next = tail->head;
519 }
520
521 list->tail = tail->tail;
Carl Worth10ae4382010-05-25 20:35:01 -0700522 list->non_space_tail = tail->non_space_tail;
523}
524
525void
526_token_list_trim_trailing_space (token_list_t *list)
527{
528 token_node_t *tail, *next;
529
530 if (list->non_space_tail) {
531 tail = list->non_space_tail->next;
532 list->non_space_tail->next = NULL;
533 list->tail = list->non_space_tail;
534
535 while (tail) {
536 next = tail->next;
537 talloc_free (tail);
538 tail = next;
539 }
540 }
Carl Worth47252442010-05-19 13:54:37 -0700541}
Carl Worth80dc60b2010-05-25 14:42:00 -0700542
Carl Worth0197e9b2010-05-26 08:05:19 -0700543static void
544_token_print (token_t *token)
545{
546 if (token->type < 256) {
547 printf ("%c", token->type);
548 return;
549 }
550
551 switch (token->type) {
552 case IDENTIFIER:
553 case OTHER:
554 printf ("%s", token->value.str);
555 break;
556 case SPACE:
557 printf (" ");
558 break;
559 case LEFT_SHIFT:
560 printf ("<<");
561 break;
562 case RIGHT_SHIFT:
563 printf (">>");
564 break;
565 case LESS_OR_EQUAL:
566 printf ("<=");
567 break;
568 case GREATER_OR_EQUAL:
569 printf (">=");
570 break;
571 case EQUAL:
572 printf ("==");
573 break;
574 case NOT_EQUAL:
575 printf ("!=");
576 break;
577 case AND:
578 printf ("&&");
579 break;
580 case OR:
581 printf ("||");
582 break;
583 case PASTE:
584 printf ("##");
585 break;
586 default:
587 fprintf (stderr, "Error: Don't know how to print token type %d\n", token->type);
588 break;
589 }
590}
591
592static void
593_token_list_print (token_list_t *list)
594{
595 token_node_t *node;
596
597 if (list == NULL)
598 return;
599
600 for (node = list->head; node; node = node->next)
601 _token_print (node->token);
602}
603
Carl Worth3a37b872010-05-10 11:44:09 -0700604void
Carl Wortha1e32bc2010-05-10 13:17:25 -0700605yyerror (void *scanner, const char *error)
Carl Worth3a37b872010-05-10 11:44:09 -0700606{
607 fprintf (stderr, "Parse error: %s\n", error);
608}
Carl Worth0b27b5f2010-05-10 16:16:06 -0700609
Carl Worth33cc4002010-05-12 12:17:10 -0700610glcpp_parser_t *
611glcpp_parser_create (void)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700612{
Carl Worth33cc4002010-05-12 12:17:10 -0700613 glcpp_parser_t *parser;
614
Carl Worth5070a202010-05-12 12:45:33 -0700615 parser = xtalloc (NULL, glcpp_parser_t);
Carl Worth33cc4002010-05-12 12:17:10 -0700616
Carl Worth8f38aff2010-05-19 10:01:29 -0700617 glcpp_lex_init_extra (parser, &parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700618 parser->defines = hash_table_ctor (32, hash_table_string_hash,
619 hash_table_string_compare);
Carl Worthae6517f2010-05-25 15:24:59 -0700620 parser->active = _string_list_create (parser);
Carl Worthf34a0002010-05-25 16:59:02 -0700621 parser->space_tokens = 1;
Carl Worth5a6b9a22010-05-20 14:29:43 -0700622
Carl Worthb20d33c2010-05-20 22:27:07 -0700623 parser->skip_stack = NULL;
624
Carl Worth33cc4002010-05-12 12:17:10 -0700625 return parser;
Carl Worth0b27b5f2010-05-10 16:16:06 -0700626}
627
628int
629glcpp_parser_parse (glcpp_parser_t *parser)
630{
631 return yyparse (parser);
632}
633
634void
Carl Worth33cc4002010-05-12 12:17:10 -0700635glcpp_parser_destroy (glcpp_parser_t *parser)
Carl Worth0b27b5f2010-05-10 16:16:06 -0700636{
Carl Worthb20d33c2010-05-20 22:27:07 -0700637 if (parser->skip_stack)
638 fprintf (stderr, "Error: Unterminated #if\n");
Carl Worth8f38aff2010-05-19 10:01:29 -0700639 glcpp_lex_destroy (parser->scanner);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700640 hash_table_dtor (parser->defines);
Carl Worth33cc4002010-05-12 12:17:10 -0700641 talloc_free (parser);
Carl Worth0b27b5f2010-05-10 16:16:06 -0700642}
Carl Worthc6d5af32010-05-11 12:30:09 -0700643
Carl Worth0197e9b2010-05-26 08:05:19 -0700644/* Appends onto 'expansion' a non-macro token or the expansion of an
645 * object-like macro.
Carl Worthb1854fd2010-05-25 16:28:26 -0700646 *
Carl Worth0197e9b2010-05-26 08:05:19 -0700647 * Returns 0 if this token is completely processed.
Carl Worthb1854fd2010-05-25 16:28:26 -0700648 *
649 * Returns 1 in the case that 'token' is a function-like macro that
650 * needs further expansion.
651 */
652static int
Carl Worth0197e9b2010-05-26 08:05:19 -0700653_glcpp_parser_expand_token_onto (glcpp_parser_t *parser,
654 token_t *token,
655 token_list_t *result)
Carl Worthae6517f2010-05-25 15:24:59 -0700656{
657 const char *identifier;
658 macro_t *macro;
Carl Worth0197e9b2010-05-26 08:05:19 -0700659 token_list_t *expansion;
Carl Worthae6517f2010-05-25 15:24:59 -0700660
661 /* We only expand identifiers */
662 if (token->type != IDENTIFIER) {
Carl Worth0197e9b2010-05-26 08:05:19 -0700663 _token_list_append (result, token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700664 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700665 }
666
667 /* Look up this identifier in the hash table. */
668 identifier = token->value.str;
669 macro = hash_table_find (parser->defines, identifier);
670
Carl Worth0197e9b2010-05-26 08:05:19 -0700671 /* Not a macro, so just append. */
Carl Worthae6517f2010-05-25 15:24:59 -0700672 if (macro == NULL) {
Carl Worth0197e9b2010-05-26 08:05:19 -0700673 _token_list_append (result, token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700674 return 0;
Carl Worthae6517f2010-05-25 15:24:59 -0700675 }
676
Carl Worthae6517f2010-05-25 15:24:59 -0700677 /* Finally, don't expand this macro if we're already actively
678 * expanding it, (to avoid infinite recursion). */
Carl Worthec4ada02010-05-26 08:15:49 -0700679 if (_string_list_contains (parser->active, identifier, NULL))
680 {
681 /* We change the token type here from IDENTIFIER to
682 * OTHER to prevent any future expansion of this
683 * unexpanded token. */
684 char *str;
685 token_t *new_token;
686
687 str = xtalloc_strdup (result, token->value.str);
688 new_token = _token_create_str (result, OTHER, str);
689 _token_list_append (result, new_token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700690 return 0;
691 }
692
Carl Worthc0607d52010-05-26 08:01:42 -0700693 /* For function-like macros return 1 for further processing. */
694 if (macro->is_function) {
695 return 1;
696 }
697
Carl Worthb1854fd2010-05-25 16:28:26 -0700698 _string_list_push (parser->active, identifier);
Carl Worth0197e9b2010-05-26 08:05:19 -0700699 _glcpp_parser_expand_token_list_onto (parser,
700 macro->replacements,
701 result);
Carl Worthb1854fd2010-05-25 16:28:26 -0700702 _string_list_pop (parser->active);
703
704 return 0;
705}
706
707typedef enum function_status
708{
709 FUNCTION_STATUS_SUCCESS,
710 FUNCTION_NOT_A_FUNCTION,
711 FUNCTION_UNBALANCED_PARENTHESES
712} function_status_t;
713
714/* Find a set of function-like macro arguments by looking for a
715 * balanced set of parentheses. Upon return *node will be the last
716 * consumed node, such that further processing can continue with
717 * node->next.
718 *
719 * Return values:
720 *
721 * FUNCTION_STATUS_SUCCESS:
722 *
723 * Successfully parsed a set of function arguments.
724 *
725 * FUNCTION_NOT_A_FUNCTION:
726 *
727 * Macro name not followed by a '('. This is not an error, but
728 * simply that the macro name should be treated as a non-macro.
729 *
730 * FUNCTION_UNBLANCED_PARENTHESES
731 *
732 * Macro name is not followed by a balanced set of parentheses.
733 */
734static function_status_t
Carl Worth9ce18cf2010-05-25 17:32:21 -0700735_arguments_parse (argument_list_t *arguments, token_node_t **node_ret)
Carl Worthb1854fd2010-05-25 16:28:26 -0700736{
Carl Worth9ce18cf2010-05-25 17:32:21 -0700737 token_list_t *argument;
Carl Worthb1854fd2010-05-25 16:28:26 -0700738 token_node_t *node = *node_ret, *last;
739 int paren_count;
Carl Worthb1854fd2010-05-25 16:28:26 -0700740
741 last = node;
742 node = node->next;
743
744 /* Ignore whitespace before first parenthesis. */
745 while (node && node->token->type == SPACE)
746 node = node->next;
747
748 if (node == NULL || node->token->type != '(')
749 return FUNCTION_NOT_A_FUNCTION;
750
Carl Worth652fa272010-05-25 17:45:22 -0700751 last = node;
752 node = node->next;
753
Carl Worth9ce18cf2010-05-25 17:32:21 -0700754 argument = NULL;
755
Carl Worth652fa272010-05-25 17:45:22 -0700756 for (paren_count = 1; node; last = node, node = node->next) {
Carl Worthb1854fd2010-05-25 16:28:26 -0700757 if (node->token->type == '(')
758 {
759 paren_count++;
760 }
761 else if (node->token->type == ')')
762 {
763 paren_count--;
Carl Worthc7581c22010-05-25 17:41:07 -0700764 if (paren_count == 0) {
765 last = node;
766 node = node->next;
767 break;
768 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700769 }
Carl Worth652fa272010-05-25 17:45:22 -0700770
771 if (node->token->type == ',' &&
Carl Worthb1854fd2010-05-25 16:28:26 -0700772 paren_count == 1)
773 {
Carl Worth10ae4382010-05-25 20:35:01 -0700774 if (argument)
775 _token_list_trim_trailing_space (argument);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700776 argument = NULL;
777 }
778 else {
779 if (argument == NULL) {
Carl Worthc7581c22010-05-25 17:41:07 -0700780 /* Don't treat initial whitespace as
781 * part of the arguement. */
782 if (node->token->type == SPACE)
783 continue;
Carl Worth9ce18cf2010-05-25 17:32:21 -0700784 argument = _token_list_create (arguments);
785 _argument_list_append (arguments, argument);
786 }
787 _token_list_append (argument, node->token);
Carl Worthb1854fd2010-05-25 16:28:26 -0700788 }
Carl Worthc7581c22010-05-25 17:41:07 -0700789 }
Carl Worthb1854fd2010-05-25 16:28:26 -0700790
791 if (node && paren_count)
792 return FUNCTION_UNBALANCED_PARENTHESES;
793
794 *node_ret = last;
795
796 return FUNCTION_STATUS_SUCCESS;
797}
798
799/* Prints the expansion of *node (consuming further tokens from the
800 * list as necessary). Upon return *node will be the last consumed
801 * node, such that further processing can continue with node->next. */
802static void
Carl Worth0197e9b2010-05-26 08:05:19 -0700803_glcpp_parser_expand_function_onto (glcpp_parser_t *parser,
804 token_node_t **node_ret,
805 token_list_t *result)
Carl Worthb1854fd2010-05-25 16:28:26 -0700806{
807 macro_t *macro;
808 token_node_t *node;
809 const char *identifier;
810 argument_list_t *arguments;
811 function_status_t status;
Carl Worth0197e9b2010-05-26 08:05:19 -0700812 token_list_t *substituted;
Carl Worth9ce18cf2010-05-25 17:32:21 -0700813 token_node_t *i, *j;
814 int parameter_index;
Carl Worthb1854fd2010-05-25 16:28:26 -0700815
816 node = *node_ret;
817 identifier = node->token->value.str;
818
819 macro = hash_table_find (parser->defines, identifier);
820
821 assert (macro->is_function);
822
Carl Worth9ce18cf2010-05-25 17:32:21 -0700823 arguments = _argument_list_create (parser);
824 status = _arguments_parse (arguments, node_ret);
Carl Worthb1854fd2010-05-25 16:28:26 -0700825
826 switch (status) {
827 case FUNCTION_STATUS_SUCCESS:
828 break;
829 case FUNCTION_NOT_A_FUNCTION:
Carl Worth0197e9b2010-05-26 08:05:19 -0700830 _token_list_append (result, node->token);
Carl Worthae6517f2010-05-25 15:24:59 -0700831 return;
Carl Worthb1854fd2010-05-25 16:28:26 -0700832 case FUNCTION_UNBALANCED_PARENTHESES:
833 fprintf (stderr, "Error: Macro %s call has unbalanced parentheses\n",
834 identifier);
835 exit (1);
Carl Worthae6517f2010-05-25 15:24:59 -0700836 }
837
Carl Worth9ce18cf2010-05-25 17:32:21 -0700838 if (macro->replacements == NULL) {
839 talloc_free (arguments);
840 return;
841 }
842
Carl Worth9ce18cf2010-05-25 17:32:21 -0700843 if (_argument_list_length (arguments) !=
844 _string_list_length (macro->parameters))
845 {
846 fprintf (stderr,
847 "Error: macro %s invoked with %d arguments (expected %d)\n",
848 identifier,
849 _argument_list_length (arguments),
850 _string_list_length (macro->parameters));
851 return;
852 }
853
Carl Worth0197e9b2010-05-26 08:05:19 -0700854 /* Perform argument substitution on the replacement list. */
855 substituted = _token_list_create (arguments);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700856
857 for (i = macro->replacements->head; i; i = i->next) {
858 if (i->token->type == IDENTIFIER &&
859 _string_list_contains (macro->parameters,
860 i->token->value.str,
861 &parameter_index))
862 {
863 token_list_t *argument;
864 argument = _argument_list_member_at (arguments,
865 parameter_index);
Carl Worthd5cd4032010-05-26 08:09:29 -0700866 /* Before substituting, we expand the argument
867 * tokens. */
868 _glcpp_parser_expand_token_list_onto (parser,
869 argument,
870 substituted);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700871 } else {
Carl Worth0197e9b2010-05-26 08:05:19 -0700872 _token_list_append (substituted, i->token);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700873 }
874 }
875
Carl Worthae6517f2010-05-25 15:24:59 -0700876 _string_list_push (parser->active, identifier);
Carl Worth0197e9b2010-05-26 08:05:19 -0700877 _glcpp_parser_expand_token_list_onto (parser, substituted, result);
Carl Worthae6517f2010-05-25 15:24:59 -0700878 _string_list_pop (parser->active);
Carl Worth9ce18cf2010-05-25 17:32:21 -0700879
880 talloc_free (arguments);
Carl Worthae6517f2010-05-25 15:24:59 -0700881}
882
Carl Worth0197e9b2010-05-26 08:05:19 -0700883static void
884_glcpp_parser_expand_token_list_onto (glcpp_parser_t *parser,
885 token_list_t *list,
886 token_list_t *result)
887{
888 token_node_t *node;
889
890 if (list == NULL)
891 return;
892
893 for (node = list->head; node; node = node->next)
894 {
895 if (_glcpp_parser_expand_token_onto (parser, node->token,
896 result))
897 {
898 _glcpp_parser_expand_function_onto (parser, &node,
899 result);
900 }
901 }
902}
903
Carl Worthae6517f2010-05-25 15:24:59 -0700904void
905_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
906 token_list_t *list)
907{
Carl Worth0197e9b2010-05-26 08:05:19 -0700908 token_list_t *expanded;
Carl Worthae6517f2010-05-25 15:24:59 -0700909 token_node_t *node;
Carl Worthb1854fd2010-05-25 16:28:26 -0700910 function_status_t function_status;
Carl Worthae6517f2010-05-25 15:24:59 -0700911
912 if (list == NULL)
913 return;
914
Carl Worth0197e9b2010-05-26 08:05:19 -0700915 expanded = _token_list_create (parser);
Carl Worth10ae4382010-05-25 20:35:01 -0700916
Carl Worth0197e9b2010-05-26 08:05:19 -0700917 _glcpp_parser_expand_token_list_onto (parser, list, expanded);
918
919 _token_list_trim_trailing_space (expanded);
920
921 _token_list_print (expanded);
922
923 talloc_free (expanded);
Carl Worthae6517f2010-05-25 15:24:59 -0700924}
925
926void
Carl Worthfcbbb462010-05-13 09:36:23 -0700927_define_object_macro (glcpp_parser_t *parser,
928 const char *identifier,
Carl Worth47252442010-05-19 13:54:37 -0700929 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700930{
931 macro_t *macro;
932
933 macro = xtalloc (parser, macro_t);
934
935 macro->is_function = 0;
Carl Worthc5e98552010-05-14 10:12:21 -0700936 macro->parameters = NULL;
Carl Wortha807fb72010-05-18 22:10:04 -0700937 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700938 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700939
940 hash_table_insert (parser->defines, macro, identifier);
941}
942
943void
944_define_function_macro (glcpp_parser_t *parser,
945 const char *identifier,
Carl Worthc5e98552010-05-14 10:12:21 -0700946 string_list_t *parameters,
Carl Worth47252442010-05-19 13:54:37 -0700947 token_list_t *replacements)
Carl Worthfcbbb462010-05-13 09:36:23 -0700948{
949 macro_t *macro;
950
951 macro = xtalloc (parser, macro_t);
952
953 macro->is_function = 1;
Carl Worthc5e98552010-05-14 10:12:21 -0700954 macro->parameters = talloc_steal (macro, parameters);
Carl Wortha807fb72010-05-18 22:10:04 -0700955 macro->identifier = talloc_strdup (macro, identifier);
Carl Worthaaa9acb2010-05-19 13:28:24 -0700956 macro->replacements = talloc_steal (macro, replacements);
Carl Worthfcbbb462010-05-13 09:36:23 -0700957
958 hash_table_insert (parser->defines, macro, identifier);
959}
960
Carl Worth8f38aff2010-05-19 10:01:29 -0700961static int
Carl Worth0293b2e2010-05-19 10:05:40 -0700962glcpp_parser_lex (glcpp_parser_t *parser)
Carl Worth8f38aff2010-05-19 10:01:29 -0700963{
Carl Worth5aa7ea02010-05-25 18:39:43 -0700964 return glcpp_lex (parser->scanner);
Carl Worth8f38aff2010-05-19 10:01:29 -0700965}
Carl Worthb20d33c2010-05-20 22:27:07 -0700966
967static void
968_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition)
969{
970 skip_type_t current = SKIP_NO_SKIP;
971 skip_node_t *node;
972
973 if (parser->skip_stack)
974 current = parser->skip_stack->type;
975
976 node = xtalloc (parser, skip_node_t);
977
978 if (current == SKIP_NO_SKIP) {
979 if (condition)
980 node->type = SKIP_NO_SKIP;
981 else
982 node->type = SKIP_TO_ELSE;
983 } else {
984 node->type = SKIP_TO_ENDIF;
985 }
986
987 node->next = parser->skip_stack;
988 parser->skip_stack = node;
989}
990
991static void
992_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type,
993 int condition)
994{
995 if (parser->skip_stack == NULL) {
996 fprintf (stderr, "Error: %s without #if\n", type);
997 exit (1);
998 }
999
1000 if (parser->skip_stack->type == SKIP_TO_ELSE) {
1001 if (condition)
1002 parser->skip_stack->type = SKIP_NO_SKIP;
1003 } else {
1004 parser->skip_stack->type = SKIP_TO_ENDIF;
1005 }
1006}
Carl Worth80dc60b2010-05-25 14:42:00 -07001007
Carl Worthb20d33c2010-05-20 22:27:07 -07001008static void
1009_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser)
1010{
1011 skip_node_t *node;
1012
1013 if (parser->skip_stack == NULL) {
1014 fprintf (stderr, "Error: #endif without #if\n");
1015 exit (1);
1016 }
1017
1018 node = parser->skip_stack;
1019 parser->skip_stack = node->next;
1020 talloc_free (node);
1021}