3 * Copyright © 2010 Intel Corporation
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:
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
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.
32 #include "main/core.h" /* for struct gl_extensions */
33 #include "main/mtypes.h" /* for gl_api enum */
36 yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
39 _define_object_macro (glcpp_parser_t *parser,
42 token_list_t *replacements);
45 _define_function_macro (glcpp_parser_t *parser,
48 string_list_t *parameters,
49 token_list_t *replacements);
51 static string_list_t *
52 _string_list_create (void *ctx);
55 _string_list_append_item (string_list_t *list, const char *str);
58 _string_list_contains (string_list_t *list, const char *member, int *index);
61 _string_list_has_duplicate (string_list_t *list);
64 _string_list_length (string_list_t *list);
67 _string_list_equal (string_list_t *a, string_list_t *b);
69 static argument_list_t *
70 _argument_list_create (void *ctx);
73 _argument_list_append (argument_list_t *list, token_list_t *argument);
76 _argument_list_length (argument_list_t *list);
79 _argument_list_member_at (argument_list_t *list, int index);
81 /* Note: This function ralloc_steal()s the str pointer. */
83 _token_create_str (void *ctx, int type, char *str);
86 _token_create_ival (void *ctx, int type, int ival);
89 _token_list_create (void *ctx);
92 _token_list_append (token_list_t *list, token_t *token);
95 _token_list_append_list (token_list_t *list, token_list_t *tail);
98 _token_list_equal_ignoring_space (token_list_t *a, token_list_t *b);
101 _parser_active_list_push (glcpp_parser_t *parser,
102 const char *identifier,
103 token_node_t *marker);
106 _parser_active_list_pop (glcpp_parser_t *parser);
109 _parser_active_list_contains (glcpp_parser_t *parser, const char *identifier);
112 EXPANSION_MODE_IGNORE_DEFINED,
113 EXPANSION_MODE_EVALUATE_DEFINED
116 /* Expand list, and begin lexing from the result (after first
117 * prefixing a token of type 'head_token_type').
120 _glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser,
123 expansion_mode_t mode);
125 /* Perform macro expansion in-place on the given list. */
127 _glcpp_parser_expand_token_list (glcpp_parser_t *parser,
129 expansion_mode_t mode);
132 _glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
136 _glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
140 _glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
141 const char *type, int condition);
144 _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
147 _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version,
148 const char *ident, bool explicitly_set);
151 glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
154 glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
157 add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
173 %parse-param {glcpp_parser_t *parser}
174 %lex-param {glcpp_parser_t *parser}
178 /* We use HASH_TOKEN, DEFINE_TOKEN and VERSION_TOKEN (as opposed to
179 * HASH, DEFINE, and VERSION) to avoid conflicts with other symbols,
180 * (such as the <HASH> and <DEFINE> start conditions in the lexer). */
181 %token DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN FUNC_IDENTIFIER OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR_TOKEN IF IFDEF IFNDEF LINE PRAGMA UNDEF VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS MINUS_MINUS
183 %type <ival> INTEGER operator SPACE integer_constant
184 %type <expression_value> expression
185 %type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA
186 %type <string_list> identifier_list
187 %type <token> preprocessing_token
188 %type <token_list> pp_tokens replacement_list text_line
194 %left EQUAL NOT_EQUAL
195 %left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL
196 %left LEFT_SHIFT RIGHT_SHIFT
214 _glcpp_parser_print_expanded_token_list (parser, $1);
215 ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n");
222 IF_EXPANDED expression NEWLINE {
223 if (parser->is_gles && $2.undefined_macro)
224 glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $2.undefined_macro);
225 _glcpp_parser_skip_stack_push_if (parser, & @1, $2.value);
227 | ELIF_EXPANDED expression NEWLINE {
228 if (parser->is_gles && $2.undefined_macro)
229 glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $2.undefined_macro);
230 _glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2.value);
232 | LINE_EXPANDED integer_constant NEWLINE {
233 parser->has_new_line_number = 1;
234 parser->new_line_number = $2;
235 ralloc_asprintf_rewrite_tail (&parser->output,
236 &parser->output_length,
237 "#line %" PRIiMAX "\n",
240 | LINE_EXPANDED integer_constant integer_constant NEWLINE {
241 parser->has_new_line_number = 1;
242 parser->new_line_number = $2;
243 parser->has_new_source_number = 1;
244 parser->new_source_number = $3;
245 ralloc_asprintf_rewrite_tail (&parser->output,
246 &parser->output_length,
247 "#line %" PRIiMAX " %" PRIiMAX "\n",
253 OBJ_IDENTIFIER replacement_list NEWLINE {
254 _define_object_macro (parser, & @1, $1, $2);
256 | FUNC_IDENTIFIER '(' ')' replacement_list NEWLINE {
257 _define_function_macro (parser, & @1, $1, NULL, $4);
259 | FUNC_IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
260 _define_function_macro (parser, & @1, $1, $3, $5);
265 control_line_success {
266 ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n");
270 glcpp_parser_resolve_implicit_version(parser);
271 } pp_tokens NEWLINE {
273 if (parser->skip_stack == NULL ||
274 parser->skip_stack->type == SKIP_NO_SKIP)
276 _glcpp_parser_expand_and_lex_from (parser,
278 EXPANSION_MODE_IGNORE_DEFINED);
283 control_line_success:
284 HASH_TOKEN DEFINE_TOKEN {
285 glcpp_parser_resolve_implicit_version(parser);
288 glcpp_parser_resolve_implicit_version(parser);
289 } IDENTIFIER NEWLINE {
291 if (strcmp("__LINE__", $4) == 0
292 || strcmp("__FILE__", $4) == 0
293 || strcmp("__VERSION__", $4) == 0
294 || strncmp("GL_", $4, 3) == 0)
295 glcpp_error(& @1, parser, "Built-in (pre-defined)"
296 " macro names cannot be undefined.");
298 macro = hash_table_find (parser->defines, $4);
300 hash_table_remove (parser->defines, $4);
306 glcpp_parser_resolve_implicit_version(parser);
307 } pp_tokens NEWLINE {
308 /* Be careful to only evaluate the 'if' expression if
309 * we are not skipping. When we are skipping, we
310 * simply push a new 0-valued 'if' onto the skip
313 * This avoids generating diagnostics for invalid
314 * expressions that are being skipped. */
315 if (parser->skip_stack == NULL ||
316 parser->skip_stack->type == SKIP_NO_SKIP)
318 _glcpp_parser_expand_and_lex_from (parser,
320 EXPANSION_MODE_EVALUATE_DEFINED);
324 _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
325 parser->skip_stack->type = SKIP_TO_ENDIF;
328 | HASH_TOKEN IF NEWLINE {
329 /* #if without an expression is only an error if we
330 * are not skipping */
331 if (parser->skip_stack == NULL ||
332 parser->skip_stack->type == SKIP_NO_SKIP)
334 glcpp_error(& @1, parser, "#if with no expression");
336 _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
339 glcpp_parser_resolve_implicit_version(parser);
340 } IDENTIFIER junk NEWLINE {
341 macro_t *macro = hash_table_find (parser->defines, $4);
343 _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL);
345 | HASH_TOKEN IFNDEF {
346 glcpp_parser_resolve_implicit_version(parser);
347 } IDENTIFIER junk NEWLINE {
348 macro_t *macro = hash_table_find (parser->defines, $4);
350 _glcpp_parser_skip_stack_push_if (parser, & @3, macro == NULL);
352 | HASH_TOKEN ELIF pp_tokens NEWLINE {
353 /* Be careful to only evaluate the 'elif' expression
354 * if we are not skipping. When we are skipping, we
355 * simply change to a 0-valued 'elif' on the skip
358 * This avoids generating diagnostics for invalid
359 * expressions that are being skipped. */
360 if (parser->skip_stack &&
361 parser->skip_stack->type == SKIP_TO_ELSE)
363 _glcpp_parser_expand_and_lex_from (parser,
365 EXPANSION_MODE_EVALUATE_DEFINED);
367 else if (parser->skip_stack &&
368 parser->skip_stack->has_else)
370 glcpp_error(& @1, parser, "#elif after #else");
374 _glcpp_parser_skip_stack_change_if (parser, & @1,
378 | HASH_TOKEN ELIF NEWLINE {
379 /* #elif without an expression is an error unless we
381 if (parser->skip_stack &&
382 parser->skip_stack->type == SKIP_TO_ELSE)
384 glcpp_error(& @1, parser, "#elif with no expression");
386 else if (parser->skip_stack &&
387 parser->skip_stack->has_else)
389 glcpp_error(& @1, parser, "#elif after #else");
393 _glcpp_parser_skip_stack_change_if (parser, & @1,
395 glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
398 | HASH_TOKEN ELSE { parser->lexing_directive = 1; } NEWLINE {
399 if (parser->skip_stack &&
400 parser->skip_stack->has_else)
402 glcpp_error(& @1, parser, "multiple #else");
406 _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
407 if (parser->skip_stack)
408 parser->skip_stack->has_else = true;
412 _glcpp_parser_skip_stack_pop (parser, & @1);
414 | HASH_TOKEN VERSION_TOKEN integer_constant NEWLINE {
415 if (parser->version_resolved) {
416 glcpp_error(& @1, parser, "#version must appear on the first line");
418 _glcpp_parser_handle_version_declaration(parser, $3, NULL, true);
420 | HASH_TOKEN VERSION_TOKEN integer_constant IDENTIFIER NEWLINE {
421 if (parser->version_resolved) {
422 glcpp_error(& @1, parser, "#version must appear on the first line");
424 _glcpp_parser_handle_version_declaration(parser, $3, $4, true);
426 | HASH_TOKEN NEWLINE {
427 glcpp_parser_resolve_implicit_version(parser);
429 | HASH_TOKEN PRAGMA NEWLINE {
430 ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "#%s", $2);
435 HASH_TOKEN ERROR_TOKEN NEWLINE {
436 glcpp_error(& @1, parser, "#%s", $2);
438 | HASH_TOKEN DEFINE_TOKEN NEWLINE {
439 glcpp_error (& @1, parser, "#define without macro name");
441 | HASH_TOKEN GARBAGE pp_tokens NEWLINE {
442 glcpp_error (& @1, parser, "Illegal non-directive after #");
448 if (strlen ($1) >= 3 && strncmp ($1, "0x", 2) == 0) {
449 $$ = strtoll ($1 + 2, NULL, 16);
450 } else if ($1[0] == '0') {
451 $$ = strtoll ($1, NULL, 8);
453 $$ = strtoll ($1, NULL, 10);
463 $$.undefined_macro = NULL;
468 $$.undefined_macro = ralloc_strdup (parser, $1);
470 $$.undefined_macro = NULL;
472 | expression OR expression {
473 $$.value = $1.value || $3.value;
475 /* Short-circuit: Only flag undefined from right side
476 * if left side evaluates to false.
478 if ($1.undefined_macro)
479 $$.undefined_macro = $1.undefined_macro;
481 $$.undefined_macro = $3.undefined_macro;
483 | expression AND expression {
484 $$.value = $1.value && $3.value;
486 /* Short-circuit: Only flag undefined from right-side
487 * if left side evaluates to true.
489 if ($1.undefined_macro)
490 $$.undefined_macro = $1.undefined_macro;
492 $$.undefined_macro = $3.undefined_macro;
494 | expression '|' expression {
495 $$.value = $1.value | $3.value;
496 if ($1.undefined_macro)
497 $$.undefined_macro = $1.undefined_macro;
499 $$.undefined_macro = $3.undefined_macro;
501 | expression '^' expression {
502 $$.value = $1.value ^ $3.value;
503 if ($1.undefined_macro)
504 $$.undefined_macro = $1.undefined_macro;
506 $$.undefined_macro = $3.undefined_macro;
508 | expression '&' expression {
509 $$.value = $1.value & $3.value;
510 if ($1.undefined_macro)
511 $$.undefined_macro = $1.undefined_macro;
513 $$.undefined_macro = $3.undefined_macro;
515 | expression NOT_EQUAL expression {
516 $$.value = $1.value != $3.value;
517 if ($1.undefined_macro)
518 $$.undefined_macro = $1.undefined_macro;
520 $$.undefined_macro = $3.undefined_macro;
522 | expression EQUAL expression {
523 $$.value = $1.value == $3.value;
524 if ($1.undefined_macro)
525 $$.undefined_macro = $1.undefined_macro;
527 $$.undefined_macro = $3.undefined_macro;
529 | expression GREATER_OR_EQUAL expression {
530 $$.value = $1.value >= $3.value;
531 if ($1.undefined_macro)
532 $$.undefined_macro = $1.undefined_macro;
534 $$.undefined_macro = $3.undefined_macro;
536 | expression LESS_OR_EQUAL expression {
537 $$.value = $1.value <= $3.value;
538 if ($1.undefined_macro)
539 $$.undefined_macro = $1.undefined_macro;
541 $$.undefined_macro = $3.undefined_macro;
543 | expression '>' expression {
544 $$.value = $1.value > $3.value;
545 if ($1.undefined_macro)
546 $$.undefined_macro = $1.undefined_macro;
548 $$.undefined_macro = $3.undefined_macro;
550 | expression '<' expression {
551 $$.value = $1.value < $3.value;
552 if ($1.undefined_macro)
553 $$.undefined_macro = $1.undefined_macro;
555 $$.undefined_macro = $3.undefined_macro;
557 | expression RIGHT_SHIFT expression {
558 $$.value = $1.value >> $3.value;
559 if ($1.undefined_macro)
560 $$.undefined_macro = $1.undefined_macro;
562 $$.undefined_macro = $3.undefined_macro;
564 | expression LEFT_SHIFT expression {
565 $$.value = $1.value << $3.value;
566 if ($1.undefined_macro)
567 $$.undefined_macro = $1.undefined_macro;
569 $$.undefined_macro = $3.undefined_macro;
571 | expression '-' expression {
572 $$.value = $1.value - $3.value;
573 if ($1.undefined_macro)
574 $$.undefined_macro = $1.undefined_macro;
576 $$.undefined_macro = $3.undefined_macro;
578 | expression '+' expression {
579 $$.value = $1.value + $3.value;
580 if ($1.undefined_macro)
581 $$.undefined_macro = $1.undefined_macro;
583 $$.undefined_macro = $3.undefined_macro;
585 | expression '%' expression {
587 yyerror (& @1, parser,
588 "zero modulus in preprocessor directive");
590 $$.value = $1.value % $3.value;
592 if ($1.undefined_macro)
593 $$.undefined_macro = $1.undefined_macro;
595 $$.undefined_macro = $3.undefined_macro;
597 | expression '/' expression {
599 yyerror (& @1, parser,
600 "division by 0 in preprocessor directive");
602 $$.value = $1.value / $3.value;
604 if ($1.undefined_macro)
605 $$.undefined_macro = $1.undefined_macro;
607 $$.undefined_macro = $3.undefined_macro;
609 | expression '*' expression {
610 $$.value = $1.value * $3.value;
611 if ($1.undefined_macro)
612 $$.undefined_macro = $1.undefined_macro;
614 $$.undefined_macro = $3.undefined_macro;
616 | '!' expression %prec UNARY {
617 $$.value = ! $2.value;
618 $$.undefined_macro = $2.undefined_macro;
620 | '~' expression %prec UNARY {
621 $$.value = ~ $2.value;
622 $$.undefined_macro = $2.undefined_macro;
624 | '-' expression %prec UNARY {
625 $$.value = - $2.value;
626 $$.undefined_macro = $2.undefined_macro;
628 | '+' expression %prec UNARY {
629 $$.value = + $2.value;
630 $$.undefined_macro = $2.undefined_macro;
632 | '(' expression ')' {
639 $$ = _string_list_create (parser);
640 _string_list_append_item ($$, $1);
641 ralloc_steal ($$, $1);
643 | identifier_list ',' IDENTIFIER {
645 _string_list_append_item ($$, $3);
646 ralloc_steal ($$, $3);
651 NEWLINE { $$ = NULL; }
656 /* empty */ { $$ = NULL; }
663 glcpp_error(&@1, parser, "extra tokens at end of directive");
668 preprocessing_token {
669 parser->space_tokens = 1;
670 $$ = _token_list_create (parser);
671 _token_list_append ($$, $1);
673 | pp_tokens preprocessing_token {
675 _token_list_append ($$, $2);
681 $$ = _token_create_str (parser, IDENTIFIER, $1);
682 $$->location = yylloc;
685 $$ = _token_create_str (parser, INTEGER_STRING, $1);
686 $$->location = yylloc;
689 $$ = _token_create_ival (parser, $1, $1);
690 $$->location = yylloc;
693 $$ = _token_create_ival (parser, DEFINED, DEFINED);
694 $$->location = yylloc;
697 $$ = _token_create_str (parser, OTHER, $1);
698 $$->location = yylloc;
701 $$ = _token_create_ival (parser, SPACE, SPACE);
702 $$->location = yylloc;
722 | LEFT_SHIFT { $$ = LEFT_SHIFT; }
723 | RIGHT_SHIFT { $$ = RIGHT_SHIFT; }
726 | LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; }
727 | GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; }
728 | EQUAL { $$ = EQUAL; }
729 | NOT_EQUAL { $$ = NOT_EQUAL; }
737 | PASTE { $$ = PASTE; }
738 | PLUS_PLUS { $$ = PLUS_PLUS; }
739 | MINUS_MINUS { $$ = MINUS_MINUS; }
745 _string_list_create (void *ctx)
749 list = ralloc (ctx, string_list_t);
757 _string_list_append_item (string_list_t *list, const char *str)
761 node = ralloc (list, string_node_t);
762 node->str = ralloc_strdup (node, str);
766 if (list->head == NULL) {
769 list->tail->next = node;
776 _string_list_contains (string_list_t *list, const char *member, int *index)
784 for (i = 0, node = list->head; node; i++, node = node->next) {
785 if (strcmp (node->str, member) == 0) {
795 /* Return duplicate string in list (if any), NULL otherwise. */
797 _string_list_has_duplicate (string_list_t *list)
799 string_node_t *node, *dup;
804 for (node = list->head; node; node = node->next) {
805 for (dup = node->next; dup; dup = dup->next) {
806 if (strcmp (node->str, dup->str) == 0)
815 _string_list_length (string_list_t *list)
823 for (node = list->head; node; node = node->next)
830 _string_list_equal (string_list_t *a, string_list_t *b)
832 string_node_t *node_a, *node_b;
834 if (a == NULL && b == NULL)
837 if (a == NULL || b == NULL)
840 for (node_a = a->head, node_b = b->head;
842 node_a = node_a->next, node_b = node_b->next)
844 if (strcmp (node_a->str, node_b->str))
848 /* Catch the case of lists being different lengths, (which
849 * would cause the loop above to terminate after the shorter
851 return node_a == node_b;
855 _argument_list_create (void *ctx)
857 argument_list_t *list;
859 list = ralloc (ctx, argument_list_t);
867 _argument_list_append (argument_list_t *list, token_list_t *argument)
869 argument_node_t *node;
871 node = ralloc (list, argument_node_t);
872 node->argument = argument;
876 if (list->head == NULL) {
879 list->tail->next = node;
886 _argument_list_length (argument_list_t *list)
889 argument_node_t *node;
894 for (node = list->head; node; node = node->next)
901 _argument_list_member_at (argument_list_t *list, int index)
903 argument_node_t *node;
910 for (i = 0; i < index; i++) {
917 return node->argument;
922 /* Note: This function ralloc_steal()s the str pointer. */
924 _token_create_str (void *ctx, int type, char *str)
928 token = ralloc (ctx, token_t);
930 token->value.str = str;
932 ralloc_steal (token, str);
938 _token_create_ival (void *ctx, int type, int ival)
942 token = ralloc (ctx, token_t);
944 token->value.ival = ival;
950 _token_list_create (void *ctx)
954 list = ralloc (ctx, token_list_t);
957 list->non_space_tail = NULL;
963 _token_list_append (token_list_t *list, token_t *token)
967 node = ralloc (list, token_node_t);
971 if (list->head == NULL) {
974 list->tail->next = node;
978 if (token->type != SPACE)
979 list->non_space_tail = node;
983 _token_list_append_list (token_list_t *list, token_list_t *tail)
985 if (tail == NULL || tail->head == NULL)
988 if (list->head == NULL) {
989 list->head = tail->head;
991 list->tail->next = tail->head;
994 list->tail = tail->tail;
995 list->non_space_tail = tail->non_space_tail;
998 static token_list_t *
999 _token_list_copy (void *ctx, token_list_t *other)
1007 copy = _token_list_create (ctx);
1008 for (node = other->head; node; node = node->next) {
1009 token_t *new_token = ralloc (copy, token_t);
1010 *new_token = *node->token;
1011 _token_list_append (copy, new_token);
1018 _token_list_trim_trailing_space (token_list_t *list)
1020 token_node_t *tail, *next;
1022 if (list->non_space_tail) {
1023 tail = list->non_space_tail->next;
1024 list->non_space_tail->next = NULL;
1025 list->tail = list->non_space_tail;
1036 _token_list_is_empty_ignoring_space (token_list_t *l)
1044 while (n != NULL && n->token->type == SPACE)
1051 _token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
1053 token_node_t *node_a, *node_b;
1055 if (a == NULL || b == NULL) {
1056 int a_empty = _token_list_is_empty_ignoring_space(a);
1057 int b_empty = _token_list_is_empty_ignoring_space(b);
1058 return a_empty == b_empty;
1066 if (node_a == NULL && node_b == NULL)
1069 if (node_a == NULL || node_b == NULL)
1071 /* Make sure whitespace appears in the same places in both.
1072 * It need not be exactly the same amount of whitespace,
1075 if (node_a->token->type == SPACE
1076 && node_b->token->type == SPACE) {
1077 while (node_a && node_a->token->type == SPACE)
1078 node_a = node_a->next;
1079 while (node_b && node_b->token->type == SPACE)
1080 node_b = node_b->next;
1084 if (node_a->token->type != node_b->token->type)
1087 switch (node_a->token->type) {
1089 if (node_a->token->value.ival !=
1090 node_b->token->value.ival)
1096 case INTEGER_STRING:
1098 if (strcmp (node_a->token->value.str,
1099 node_b->token->value.str))
1106 node_a = node_a->next;
1107 node_b = node_b->next;
1114 _token_print (char **out, size_t *len, token_t *token)
1116 if (token->type < 256) {
1117 ralloc_asprintf_rewrite_tail (out, len, "%c", token->type);
1121 switch (token->type) {
1123 ralloc_asprintf_rewrite_tail (out, len, "%" PRIiMAX, token->value.ival);
1126 case INTEGER_STRING:
1128 ralloc_asprintf_rewrite_tail (out, len, "%s", token->value.str);
1131 ralloc_asprintf_rewrite_tail (out, len, " ");
1134 ralloc_asprintf_rewrite_tail (out, len, "<<");
1137 ralloc_asprintf_rewrite_tail (out, len, ">>");
1140 ralloc_asprintf_rewrite_tail (out, len, "<=");
1142 case GREATER_OR_EQUAL:
1143 ralloc_asprintf_rewrite_tail (out, len, ">=");
1146 ralloc_asprintf_rewrite_tail (out, len, "==");
1149 ralloc_asprintf_rewrite_tail (out, len, "!=");
1152 ralloc_asprintf_rewrite_tail (out, len, "&&");
1155 ralloc_asprintf_rewrite_tail (out, len, "||");
1158 ralloc_asprintf_rewrite_tail (out, len, "##");
1161 ralloc_asprintf_rewrite_tail (out, len, "++");
1164 ralloc_asprintf_rewrite_tail (out, len, "--");
1167 ralloc_asprintf_rewrite_tail (out, len, "defined");
1170 /* Nothing to print. */
1173 assert(!"Error: Don't know how to print token.");
1179 /* Return a new token (ralloc()ed off of 'token') formed by pasting
1180 * 'token' and 'other'. Note that this function may return 'token' or
1181 * 'other' directly rather than allocating anything new.
1183 * Caution: Only very cursory error-checking is performed to see if
1184 * the final result is a valid single token. */
1186 _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
1188 token_t *combined = NULL;
1190 /* Pasting a placeholder onto anything makes no change. */
1191 if (other->type == PLACEHOLDER)
1194 /* When 'token' is a placeholder, just return 'other'. */
1195 if (token->type == PLACEHOLDER)
1198 /* A very few single-character punctuators can be combined
1199 * with another to form a multi-character punctuator. */
1200 switch (token->type) {
1202 if (other->type == '<')
1203 combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT);
1204 else if (other->type == '=')
1205 combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL);
1208 if (other->type == '>')
1209 combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT);
1210 else if (other->type == '=')
1211 combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
1214 if (other->type == '=')
1215 combined = _token_create_ival (token, EQUAL, EQUAL);
1218 if (other->type == '=')
1219 combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL);
1222 if (other->type == '&')
1223 combined = _token_create_ival (token, AND, AND);
1226 if (other->type == '|')
1227 combined = _token_create_ival (token, OR, OR);
1231 if (combined != NULL) {
1232 /* Inherit the location from the first token */
1233 combined->location = token->location;
1237 /* Two string-valued (or integer) tokens can usually just be
1238 * mashed together. (We also handle a string followed by an
1239 * integer here as well.)
1241 * There are some exceptions here. Notably, if the first token
1242 * is an integer (or a string representing an integer), then
1243 * the second token must also be an integer or must be a
1244 * string representing an integer that begins with a digit.
1246 if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING || token->type == INTEGER) &&
1247 (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING || other->type == INTEGER))
1252 /* Check that pasting onto an integer doesn't create a
1253 * non-integer, (that is, only digits can be
1255 if (token->type == INTEGER_STRING || token->type == INTEGER)
1257 switch (other->type) {
1258 case INTEGER_STRING:
1259 if (other->value.str[0] < '0' ||
1260 other->value.str[0] > '9')
1264 if (other->value.ival < 0)
1272 if (token->type == INTEGER)
1273 str = ralloc_asprintf (token, "%" PRIiMAX,
1276 str = ralloc_strdup (token, token->value.str);
1279 if (other->type == INTEGER)
1280 ralloc_asprintf_append (&str, "%" PRIiMAX,
1283 ralloc_strcat (&str, other->value.str);
1285 /* New token is same type as original token, unless we
1286 * started with an integer, in which case we will be
1287 * creating an integer-string. */
1288 combined_type = token->type;
1289 if (combined_type == INTEGER)
1290 combined_type = INTEGER_STRING;
1292 combined = _token_create_str (token, combined_type, str);
1293 combined->location = token->location;
1298 glcpp_error (&token->location, parser, "");
1299 ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "Pasting \"");
1300 _token_print (&parser->info_log, &parser->info_log_length, token);
1301 ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "\" and \"");
1302 _token_print (&parser->info_log, &parser->info_log_length, other);
1303 ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "\" does not give a valid preprocessing token.\n");
1309 _token_list_print (glcpp_parser_t *parser, token_list_t *list)
1316 for (node = list->head; node; node = node->next)
1317 _token_print (&parser->output, &parser->output_length, node->token);
1321 yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
1323 glcpp_error(locp, parser, "%s", error);
1326 static void add_builtin_define(glcpp_parser_t *parser,
1327 const char *name, int value)
1332 tok = _token_create_ival (parser, INTEGER, value);
1334 list = _token_list_create(parser);
1335 _token_list_append(list, tok);
1336 _define_object_macro(parser, NULL, name, list);
1340 glcpp_parser_create (const struct gl_extensions *extensions, gl_api api)
1342 glcpp_parser_t *parser;
1344 parser = ralloc (NULL, glcpp_parser_t);
1346 glcpp_lex_init_extra (parser, &parser->scanner);
1347 parser->defines = hash_table_ctor (32, hash_table_string_hash,
1348 hash_table_string_compare);
1349 parser->active = NULL;
1350 parser->lexing_directive = 0;
1351 parser->space_tokens = 1;
1352 parser->last_token_was_newline = 0;
1353 parser->last_token_was_space = 0;
1354 parser->first_non_space_token_this_line = 1;
1355 parser->newline_as_space = 0;
1356 parser->in_control_line = 0;
1357 parser->paren_count = 0;
1358 parser->commented_newlines = 0;
1360 parser->skip_stack = NULL;
1361 parser->skipping = 0;
1363 parser->lex_from_list = NULL;
1364 parser->lex_from_node = NULL;
1366 parser->output = ralloc_strdup(parser, "");
1367 parser->output_length = 0;
1368 parser->info_log = ralloc_strdup(parser, "");
1369 parser->info_log_length = 0;
1372 parser->extensions = extensions;
1374 parser->version_resolved = false;
1376 parser->has_new_line_number = 0;
1377 parser->new_line_number = 1;
1378 parser->has_new_source_number = 0;
1379 parser->new_source_number = 0;
1385 glcpp_parser_destroy (glcpp_parser_t *parser)
1387 glcpp_lex_destroy (parser->scanner);
1388 hash_table_dtor (parser->defines);
1389 ralloc_free (parser);
1392 typedef enum function_status
1394 FUNCTION_STATUS_SUCCESS,
1395 FUNCTION_NOT_A_FUNCTION,
1396 FUNCTION_UNBALANCED_PARENTHESES
1397 } function_status_t;
1399 /* Find a set of function-like macro arguments by looking for a
1400 * balanced set of parentheses.
1402 * When called, 'node' should be the opening-parenthesis token, (or
1403 * perhaps preceeding SPACE tokens). Upon successful return *last will
1404 * be the last consumed node, (corresponding to the closing right
1409 * FUNCTION_STATUS_SUCCESS:
1411 * Successfully parsed a set of function arguments.
1413 * FUNCTION_NOT_A_FUNCTION:
1415 * Macro name not followed by a '('. This is not an error, but
1416 * simply that the macro name should be treated as a non-macro.
1418 * FUNCTION_UNBALANCED_PARENTHESES
1420 * Macro name is not followed by a balanced set of parentheses.
1422 static function_status_t
1423 _arguments_parse (argument_list_t *arguments,
1425 token_node_t **last)
1427 token_list_t *argument;
1432 /* Ignore whitespace before first parenthesis. */
1433 while (node && node->token->type == SPACE)
1436 if (node == NULL || node->token->type != '(')
1437 return FUNCTION_NOT_A_FUNCTION;
1441 argument = _token_list_create (arguments);
1442 _argument_list_append (arguments, argument);
1444 for (paren_count = 1; node; node = node->next) {
1445 if (node->token->type == '(')
1449 else if (node->token->type == ')')
1452 if (paren_count == 0)
1456 if (node->token->type == ',' &&
1459 _token_list_trim_trailing_space (argument);
1460 argument = _token_list_create (arguments);
1461 _argument_list_append (arguments, argument);
1464 if (argument->head == NULL) {
1465 /* Don't treat initial whitespace as
1466 * part of the argument. */
1467 if (node->token->type == SPACE)
1470 _token_list_append (argument, node->token);
1475 return FUNCTION_UNBALANCED_PARENTHESES;
1479 return FUNCTION_STATUS_SUCCESS;
1482 static token_list_t *
1483 _token_list_create_with_one_ival (void *ctx, int type, int ival)
1488 list = _token_list_create (ctx);
1489 node = _token_create_ival (list, type, ival);
1490 _token_list_append (list, node);
1495 static token_list_t *
1496 _token_list_create_with_one_space (void *ctx)
1498 return _token_list_create_with_one_ival (ctx, SPACE, SPACE);
1501 static token_list_t *
1502 _token_list_create_with_one_integer (void *ctx, int ival)
1504 return _token_list_create_with_one_ival (ctx, INTEGER, ival);
1507 /* Evaluate a DEFINED token node (based on subsequent tokens in the list).
1509 * Note: This function must only be called when "node" is a DEFINED token,
1510 * (and will abort with an assertion failure otherwise).
1512 * If "node" is followed, (ignoring any SPACE tokens), by an IDENTIFIER token
1513 * (optionally preceded and followed by '(' and ')' tokens) then the following
1516 * If the identifier is a defined macro, this function returns 1.
1518 * If the identifier is not a defined macro, this function returns 0.
1520 * In either case, *last will be updated to the last node in the list
1521 * consumed by the evaluation, (either the token of the identifier or the
1522 * token of the closing parenthesis).
1524 * In all other cases, (such as "node is the final node of the list", or
1525 * "missing closing parenthesis", etc.), this function generates a
1526 * preprocessor error, returns -1 and *last will not be set.
1529 _glcpp_parser_evaluate_defined (glcpp_parser_t *parser,
1531 token_node_t **last)
1533 token_node_t *argument, *defined = node;
1535 assert (node->token->type == DEFINED);
1539 /* Ignore whitespace after DEFINED token. */
1540 while (node && node->token->type == SPACE)
1546 if (node->token->type == IDENTIFIER || node->token->type == OTHER) {
1548 } else if (node->token->type == '(') {
1551 /* Ignore whitespace after '(' token. */
1552 while (node && node->token->type == SPACE)
1555 if (node == NULL || (node->token->type != IDENTIFIER &&
1556 node->token->type != OTHER))
1565 /* Ignore whitespace after identifier, before ')' token. */
1566 while (node && node->token->type == SPACE)
1569 if (node == NULL || node->token->type != ')')
1577 return hash_table_find (parser->defines,
1578 argument->token->value.str) ? 1 : 0;
1581 glcpp_error (&defined->token->location, parser,
1582 "\"defined\" not followed by an identifier");
1586 /* Evaluate all DEFINED nodes in a given list, modifying the list in place.
1589 _glcpp_parser_evaluate_defined_in_list (glcpp_parser_t *parser,
1592 token_node_t *node, *node_prev, *replacement, *last = NULL;
1603 if (node->token->type != DEFINED)
1606 value = _glcpp_parser_evaluate_defined (parser, node, &last);
1610 replacement = ralloc (list, token_node_t);
1611 replacement->token = _token_create_ival (list, INTEGER, value);
1613 /* Splice replacement node into list, replacing from "node"
1614 * through "last". */
1616 node_prev->next = replacement;
1618 list->head = replacement;
1619 replacement->next = last->next;
1620 if (last == list->tail)
1621 list->tail = replacement;
1631 /* Perform macro expansion on 'list', placing the resulting tokens
1632 * into a new list which is initialized with a first token of type
1633 * 'head_token_type'. Then begin lexing from the resulting list,
1634 * (return to the current lexing source when this list is exhausted).
1636 * See the documentation of _glcpp_parser_expand_token_list for a description
1637 * of the "mode" parameter.
1640 _glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser,
1641 int head_token_type,
1643 expansion_mode_t mode)
1645 token_list_t *expanded;
1648 expanded = _token_list_create (parser);
1649 token = _token_create_ival (parser, head_token_type, head_token_type);
1650 _token_list_append (expanded, token);
1651 _glcpp_parser_expand_token_list (parser, list, mode);
1652 _token_list_append_list (expanded, list);
1653 glcpp_parser_lex_from (parser, expanded);
1657 _glcpp_parser_apply_pastes (glcpp_parser_t *parser, token_list_t *list)
1664 token_node_t *next_non_space;
1666 /* Look ahead for a PASTE token, skipping space. */
1667 next_non_space = node->next;
1668 while (next_non_space && next_non_space->token->type == SPACE)
1669 next_non_space = next_non_space->next;
1671 if (next_non_space == NULL)
1674 if (next_non_space->token->type != PASTE) {
1675 node = next_non_space;
1679 /* Now find the next non-space token after the PASTE. */
1680 next_non_space = next_non_space->next;
1681 while (next_non_space && next_non_space->token->type == SPACE)
1682 next_non_space = next_non_space->next;
1684 if (next_non_space == NULL) {
1685 yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
1689 node->token = _token_paste (parser, node->token, next_non_space->token);
1690 node->next = next_non_space->next;
1691 if (next_non_space == list->tail)
1695 list->non_space_tail = list->tail;
1698 /* This is a helper function that's essentially part of the
1699 * implementation of _glcpp_parser_expand_node. It shouldn't be called
1700 * except for by that function.
1702 * Returns NULL if node is a simple token with no expansion, (that is,
1703 * although 'node' corresponds to an identifier defined as a
1704 * function-like macro, it is not followed with a parenthesized
1707 * Compute the complete expansion of node (which is a function-like
1708 * macro) and subsequent nodes which are arguments.
1710 * Returns the token list that results from the expansion and sets
1711 * *last to the last node in the list that was consumed by the
1712 * expansion. Specifically, *last will be set as follows: as the
1713 * token of the closing right parenthesis.
1715 * See the documentation of _glcpp_parser_expand_token_list for a description
1716 * of the "mode" parameter.
1718 static token_list_t *
1719 _glcpp_parser_expand_function (glcpp_parser_t *parser,
1721 token_node_t **last,
1722 expansion_mode_t mode)
1725 const char *identifier;
1726 argument_list_t *arguments;
1727 function_status_t status;
1728 token_list_t *substituted;
1729 int parameter_index;
1731 identifier = node->token->value.str;
1733 macro = hash_table_find (parser->defines, identifier);
1735 assert (macro->is_function);
1737 arguments = _argument_list_create (parser);
1738 status = _arguments_parse (arguments, node, last);
1741 case FUNCTION_STATUS_SUCCESS:
1743 case FUNCTION_NOT_A_FUNCTION:
1745 case FUNCTION_UNBALANCED_PARENTHESES:
1746 glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
1750 /* Replace a macro defined as empty with a SPACE token. */
1751 if (macro->replacements == NULL) {
1752 ralloc_free (arguments);
1753 return _token_list_create_with_one_space (parser);
1756 if (! ((_argument_list_length (arguments) ==
1757 _string_list_length (macro->parameters)) ||
1758 (_string_list_length (macro->parameters) == 0 &&
1759 _argument_list_length (arguments) == 1 &&
1760 arguments->head->argument->head == NULL)))
1762 glcpp_error (&node->token->location, parser,
1763 "Error: macro %s invoked with %d arguments (expected %d)\n",
1765 _argument_list_length (arguments),
1766 _string_list_length (macro->parameters));
1770 /* Perform argument substitution on the replacement list. */
1771 substituted = _token_list_create (arguments);
1773 for (node = macro->replacements->head; node; node = node->next)
1775 if (node->token->type == IDENTIFIER &&
1776 _string_list_contains (macro->parameters,
1777 node->token->value.str,
1780 token_list_t *argument;
1781 argument = _argument_list_member_at (arguments,
1783 /* Before substituting, we expand the argument
1784 * tokens, or append a placeholder token for
1785 * an empty argument. */
1786 if (argument->head) {
1787 token_list_t *expanded_argument;
1788 expanded_argument = _token_list_copy (parser,
1790 _glcpp_parser_expand_token_list (parser,
1793 _token_list_append_list (substituted,
1798 new_token = _token_create_ival (substituted,
1801 _token_list_append (substituted, new_token);
1804 _token_list_append (substituted, node->token);
1808 /* After argument substitution, and before further expansion
1809 * below, implement token pasting. */
1811 _token_list_trim_trailing_space (substituted);
1813 _glcpp_parser_apply_pastes (parser, substituted);
1818 /* Compute the complete expansion of node, (and subsequent nodes after
1819 * 'node' in the case that 'node' is a function-like macro and
1820 * subsequent nodes are arguments).
1822 * Returns NULL if node is a simple token with no expansion.
1824 * Otherwise, returns the token list that results from the expansion
1825 * and sets *last to the last node in the list that was consumed by
1826 * the expansion. Specifically, *last will be set as follows:
1828 * As 'node' in the case of object-like macro expansion.
1830 * As the token of the closing right parenthesis in the case of
1831 * function-like macro expansion.
1833 * See the documentation of _glcpp_parser_expand_token_list for a description
1834 * of the "mode" parameter.
1836 static token_list_t *
1837 _glcpp_parser_expand_node (glcpp_parser_t *parser,
1839 token_node_t **last,
1840 expansion_mode_t mode)
1842 token_t *token = node->token;
1843 const char *identifier;
1846 /* We only expand identifiers */
1847 if (token->type != IDENTIFIER) {
1852 identifier = token->value.str;
1854 /* Special handling for __LINE__ and __FILE__, (not through
1855 * the hash table). */
1856 if (strcmp(identifier, "__LINE__") == 0)
1857 return _token_list_create_with_one_integer (parser, node->token->location.first_line);
1859 if (strcmp(identifier, "__FILE__") == 0)
1860 return _token_list_create_with_one_integer (parser, node->token->location.source);
1862 /* Look up this identifier in the hash table. */
1863 macro = hash_table_find (parser->defines, identifier);
1865 /* Not a macro, so no expansion needed. */
1869 /* Finally, don't expand this macro if we're already actively
1870 * expanding it, (to avoid infinite recursion). */
1871 if (_parser_active_list_contains (parser, identifier)) {
1872 /* We change the token type here from IDENTIFIER to
1873 * OTHER to prevent any future expansion of this
1874 * unexpanded token. */
1876 token_list_t *expansion;
1879 str = ralloc_strdup (parser, token->value.str);
1880 final = _token_create_str (parser, OTHER, str);
1881 expansion = _token_list_create (parser);
1882 _token_list_append (expansion, final);
1886 if (! macro->is_function)
1888 token_list_t *replacement;
1890 /* Replace a macro defined as empty with a SPACE token. */
1891 if (macro->replacements == NULL)
1892 return _token_list_create_with_one_space (parser);
1894 replacement = _token_list_copy (parser, macro->replacements);
1895 _glcpp_parser_apply_pastes (parser, replacement);
1899 return _glcpp_parser_expand_function (parser, node, last, mode);
1902 /* Push a new identifier onto the parser's active list.
1904 * Here, 'marker' is the token node that appears in the list after the
1905 * expansion of 'identifier'. That is, when the list iterator begins
1906 * examining 'marker', then it is time to pop this node from the
1910 _parser_active_list_push (glcpp_parser_t *parser,
1911 const char *identifier,
1912 token_node_t *marker)
1914 active_list_t *node;
1916 node = ralloc (parser->active, active_list_t);
1917 node->identifier = ralloc_strdup (node, identifier);
1918 node->marker = marker;
1919 node->next = parser->active;
1921 parser->active = node;
1925 _parser_active_list_pop (glcpp_parser_t *parser)
1927 active_list_t *node = parser->active;
1930 parser->active = NULL;
1934 node = parser->active->next;
1935 ralloc_free (parser->active);
1937 parser->active = node;
1941 _parser_active_list_contains (glcpp_parser_t *parser, const char *identifier)
1943 active_list_t *node;
1945 if (parser->active == NULL)
1948 for (node = parser->active; node; node = node->next)
1949 if (strcmp (node->identifier, identifier) == 0)
1955 /* Walk over the token list replacing nodes with their expansion.
1956 * Whenever nodes are expanded the walking will walk over the new
1957 * nodes, continuing to expand as necessary. The results are placed in
1960 * The "mode" argument controls the handling of any DEFINED tokens that
1961 * result from expansion as follows:
1963 * EXPANSION_MODE_IGNORE_DEFINED: Any resulting DEFINED tokens will be
1964 * left in the final list, unevaluated. This is the correct mode
1965 * for expanding any list in any context other than a
1966 * preprocessor conditional, (#if or #elif).
1968 * EXPANSION_MODE_EVALUATE_DEFINED: Any resulting DEFINED tokens will be
1969 * evaluated to 0 or 1 tokens depending on whether the following
1970 * token is the name of a defined macro. If the DEFINED token is
1971 * not followed by an (optionally parenthesized) identifier, then
1972 * an error will be generated. This the correct mode for
1973 * expanding any list in the context of a preprocessor
1974 * conditional, (#if or #elif).
1977 _glcpp_parser_expand_token_list (glcpp_parser_t *parser,
1979 expansion_mode_t mode)
1981 token_node_t *node_prev;
1982 token_node_t *node, *last = NULL;
1983 token_list_t *expansion;
1984 active_list_t *active_initial = parser->active;
1989 _token_list_trim_trailing_space (list);
1994 if (mode == EXPANSION_MODE_EVALUATE_DEFINED)
1995 _glcpp_parser_evaluate_defined_in_list (parser, list);
1999 while (parser->active && parser->active->marker == node)
2000 _parser_active_list_pop (parser);
2002 expansion = _glcpp_parser_expand_node (parser, node, &last, mode);
2006 if (mode == EXPANSION_MODE_EVALUATE_DEFINED) {
2007 _glcpp_parser_evaluate_defined_in_list (parser,
2011 for (n = node; n != last->next; n = n->next)
2012 while (parser->active &&
2013 parser->active->marker == n)
2015 _parser_active_list_pop (parser);
2018 _parser_active_list_push (parser,
2019 node->token->value.str,
2022 /* Splice expansion into list, supporting a
2023 * simple deletion if the expansion is
2025 if (expansion->head) {
2027 node_prev->next = expansion->head;
2029 list->head = expansion->head;
2030 expansion->tail->next = last->next;
2031 if (last == list->tail)
2032 list->tail = expansion->tail;
2035 node_prev->next = last->next;
2037 list->head = last->next;
2038 if (last == list->tail)
2044 node = node_prev ? node_prev->next : list->head;
2047 /* Remove any lingering effects of this invocation on the
2048 * active list. That is, pop until the list looks like it did
2049 * at the beginning of this function. */
2050 while (parser->active && parser->active != active_initial)
2051 _parser_active_list_pop (parser);
2053 list->non_space_tail = list->tail;
2057 _glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
2063 _glcpp_parser_expand_token_list (parser, list, EXPANSION_MODE_IGNORE_DEFINED);
2065 _token_list_trim_trailing_space (list);
2067 _token_list_print (parser, list);
2071 _check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
2072 const char *identifier)
2074 /* Section 3.3 (Preprocessor) of the GLSL 1.30 spec (and later) and
2075 * the GLSL ES spec (all versions) say:
2077 * "All macro names containing two consecutive underscores ( __ )
2078 * are reserved for future use as predefined macro names. All
2079 * macro names prefixed with "GL_" ("GL" followed by a single
2080 * underscore) are also reserved."
2082 * The intention is that names containing __ are reserved for internal
2083 * use by the implementation, and names prefixed with GL_ are reserved
2084 * for use by Khronos. Since every extension adds a name prefixed
2085 * with GL_ (i.e., the name of the extension), that should be an
2086 * error. Names simply containing __ are dangerous to use, but should
2089 * A future version of the GLSL specification will clarify this.
2091 if (strstr(identifier, "__")) {
2092 glcpp_warning(loc, parser,
2093 "Macro names containing \"__\" are reserved "
2094 "for use by the implementation.\n");
2096 if (strncmp(identifier, "GL_", 3) == 0) {
2097 glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
2099 if (strcmp(identifier, "defined") == 0) {
2100 glcpp_error (loc, parser, "\"defined\" cannot be used as a macro name");
2105 _macro_equal (macro_t *a, macro_t *b)
2107 if (a->is_function != b->is_function)
2110 if (a->is_function) {
2111 if (! _string_list_equal (a->parameters, b->parameters))
2115 return _token_list_equal_ignoring_space (a->replacements,
2120 _define_object_macro (glcpp_parser_t *parser,
2122 const char *identifier,
2123 token_list_t *replacements)
2125 macro_t *macro, *previous;
2127 /* We define pre-defined macros before we've started parsing the
2128 * actual file. So if there's no location defined yet, that's what
2129 * were doing and we don't want to generate an error for using the
2130 * reserved names. */
2132 _check_for_reserved_macro_name(parser, loc, identifier);
2134 macro = ralloc (parser, macro_t);
2136 macro->is_function = 0;
2137 macro->parameters = NULL;
2138 macro->identifier = ralloc_strdup (macro, identifier);
2139 macro->replacements = replacements;
2140 ralloc_steal (macro, replacements);
2142 previous = hash_table_find (parser->defines, identifier);
2144 if (_macro_equal (macro, previous)) {
2145 ralloc_free (macro);
2148 glcpp_error (loc, parser, "Redefinition of macro %s\n",
2152 hash_table_insert (parser->defines, macro, identifier);
2156 _define_function_macro (glcpp_parser_t *parser,
2158 const char *identifier,
2159 string_list_t *parameters,
2160 token_list_t *replacements)
2162 macro_t *macro, *previous;
2165 _check_for_reserved_macro_name(parser, loc, identifier);
2167 /* Check for any duplicate parameter names. */
2168 if ((dup = _string_list_has_duplicate (parameters)) != NULL) {
2169 glcpp_error (loc, parser, "Duplicate macro parameter \"%s\"",
2173 macro = ralloc (parser, macro_t);
2174 ralloc_steal (macro, parameters);
2175 ralloc_steal (macro, replacements);
2177 macro->is_function = 1;
2178 macro->parameters = parameters;
2179 macro->identifier = ralloc_strdup (macro, identifier);
2180 macro->replacements = replacements;
2181 previous = hash_table_find (parser->defines, identifier);
2183 if (_macro_equal (macro, previous)) {
2184 ralloc_free (macro);
2187 glcpp_error (loc, parser, "Redefinition of macro %s\n",
2191 hash_table_insert (parser->defines, macro, identifier);
2195 glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
2200 if (parser->lex_from_list == NULL) {
2201 ret = glcpp_lex (yylval, yylloc, parser->scanner);
2203 /* XXX: This ugly block of code exists for the sole
2204 * purpose of converting a NEWLINE token into a SPACE
2205 * token, but only in the case where we have seen a
2206 * function-like macro name, but have not yet seen its
2207 * closing parenthesis.
2209 * There's perhaps a more compact way to do this with
2210 * mid-rule actions in the grammar.
2212 * I'm definitely not pleased with the complexity of
2215 if (parser->newline_as_space)
2218 parser->paren_count++;
2219 } else if (ret == ')') {
2220 parser->paren_count--;
2221 if (parser->paren_count == 0)
2222 parser->newline_as_space = 0;
2223 } else if (ret == NEWLINE) {
2225 } else if (ret != SPACE) {
2226 if (parser->paren_count == 0)
2227 parser->newline_as_space = 0;
2230 else if (parser->in_control_line)
2233 parser->in_control_line = 0;
2235 else if (ret == DEFINE_TOKEN ||
2236 ret == UNDEF || ret == IF ||
2237 ret == IFDEF || ret == IFNDEF ||
2238 ret == ELIF || ret == ELSE ||
2239 ret == ENDIF || ret == HASH_TOKEN)
2241 parser->in_control_line = 1;
2243 else if (ret == IDENTIFIER)
2246 macro = hash_table_find (parser->defines,
2248 if (macro && macro->is_function) {
2249 parser->newline_as_space = 1;
2250 parser->paren_count = 0;
2257 node = parser->lex_from_node;
2260 ralloc_free (parser->lex_from_list);
2261 parser->lex_from_list = NULL;
2265 *yylval = node->token->value;
2266 ret = node->token->type;
2268 parser->lex_from_node = node->next;
2274 glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
2278 assert (parser->lex_from_list == NULL);
2280 /* Copy list, eliminating any space tokens. */
2281 parser->lex_from_list = _token_list_create (parser);
2283 for (node = list->head; node; node = node->next) {
2284 if (node->token->type == SPACE)
2286 _token_list_append (parser->lex_from_list, node->token);
2291 parser->lex_from_node = parser->lex_from_list->head;
2293 /* It's possible the list consisted of nothing but whitespace. */
2294 if (parser->lex_from_node == NULL) {
2295 ralloc_free (parser->lex_from_list);
2296 parser->lex_from_list = NULL;
2301 _glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
2304 skip_type_t current = SKIP_NO_SKIP;
2307 if (parser->skip_stack)
2308 current = parser->skip_stack->type;
2310 node = ralloc (parser, skip_node_t);
2313 if (current == SKIP_NO_SKIP) {
2315 node->type = SKIP_NO_SKIP;
2317 node->type = SKIP_TO_ELSE;
2319 node->type = SKIP_TO_ENDIF;
2322 node->has_else = false;
2323 node->next = parser->skip_stack;
2324 parser->skip_stack = node;
2328 _glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
2329 const char *type, int condition)
2331 if (parser->skip_stack == NULL) {
2332 glcpp_error (loc, parser, "#%s without #if\n", type);
2336 if (parser->skip_stack->type == SKIP_TO_ELSE) {
2338 parser->skip_stack->type = SKIP_NO_SKIP;
2340 parser->skip_stack->type = SKIP_TO_ENDIF;
2345 _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
2349 if (parser->skip_stack == NULL) {
2350 glcpp_error (loc, parser, "#endif without #if\n");
2354 node = parser->skip_stack;
2355 parser->skip_stack = node->next;
2360 _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version,
2361 const char *es_identifier,
2362 bool explicitly_set)
2364 const struct gl_extensions *extensions = parser->extensions;
2366 if (parser->version_resolved)
2369 parser->version_resolved = true;
2371 add_builtin_define (parser, "__VERSION__", version);
2373 parser->is_gles = (version == 100) ||
2375 (strcmp(es_identifier, "es") == 0));
2377 /* Add pre-defined macros. */
2378 if (parser->is_gles) {
2379 add_builtin_define(parser, "GL_ES", 1);
2380 add_builtin_define(parser, "GL_EXT_separate_shader_objects", 1);
2381 add_builtin_define(parser, "GL_EXT_draw_buffers", 1);
2383 if (extensions != NULL) {
2384 if (extensions->OES_EGL_image_external)
2385 add_builtin_define(parser, "GL_OES_EGL_image_external", 1);
2386 if (extensions->OES_standard_derivatives)
2387 add_builtin_define(parser, "GL_OES_standard_derivatives", 1);
2388 if (extensions->ARB_texture_multisample)
2389 add_builtin_define(parser, "GL_OES_texture_storage_multisample_2d_array", 1);
2390 if (extensions->ARB_blend_func_extended)
2391 add_builtin_define(parser, "GL_EXT_blend_func_extended", 1);
2393 if (version >= 310) {
2394 if (extensions->OES_geometry_shader) {
2395 add_builtin_define(parser, "GL_OES_geometry_point_size", 1);
2396 add_builtin_define(parser, "GL_OES_geometry_shader", 1);
2401 add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
2402 add_builtin_define(parser, "GL_ARB_enhanced_layouts", 1);
2403 add_builtin_define(parser, "GL_ARB_separate_shader_objects", 1);
2404 add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
2405 add_builtin_define(parser, "GL_AMD_shader_trinary_minmax", 1);
2408 if (extensions != NULL) {
2409 if (extensions->EXT_texture_array)
2410 add_builtin_define(parser, "GL_EXT_texture_array", 1);
2412 if (extensions->ARB_arrays_of_arrays)
2413 add_builtin_define(parser, "GL_ARB_arrays_of_arrays", 1);
2415 if (extensions->ARB_fragment_coord_conventions)
2416 add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
2419 if (extensions->ARB_fragment_layer_viewport)
2420 add_builtin_define(parser, "GL_ARB_fragment_layer_viewport", 1);
2422 if (extensions->ARB_explicit_attrib_location)
2423 add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
2425 if (extensions->ARB_explicit_uniform_location)
2426 add_builtin_define(parser, "GL_ARB_explicit_uniform_location", 1);
2428 if (extensions->ARB_shader_texture_lod)
2429 add_builtin_define(parser, "GL_ARB_shader_texture_lod", 1);
2431 if (extensions->ARB_draw_instanced)
2432 add_builtin_define(parser, "GL_ARB_draw_instanced", 1);
2434 if (extensions->ARB_conservative_depth) {
2435 add_builtin_define(parser, "GL_AMD_conservative_depth", 1);
2436 add_builtin_define(parser, "GL_ARB_conservative_depth", 1);
2439 if (extensions->ARB_shader_bit_encoding)
2440 add_builtin_define(parser, "GL_ARB_shader_bit_encoding", 1);
2442 if (extensions->ARB_shader_clock)
2443 add_builtin_define(parser, "GL_ARB_shader_clock", 1);
2445 if (extensions->ARB_uniform_buffer_object)
2446 add_builtin_define(parser, "GL_ARB_uniform_buffer_object", 1);
2448 if (extensions->ARB_texture_cube_map_array)
2449 add_builtin_define(parser, "GL_ARB_texture_cube_map_array", 1);
2451 if (extensions->ARB_shading_language_packing)
2452 add_builtin_define(parser, "GL_ARB_shading_language_packing", 1);
2454 if (extensions->ARB_texture_multisample)
2455 add_builtin_define(parser, "GL_ARB_texture_multisample", 1);
2457 if (extensions->ARB_texture_query_levels)
2458 add_builtin_define(parser, "GL_ARB_texture_query_levels", 1);
2460 if (extensions->ARB_texture_query_lod)
2461 add_builtin_define(parser, "GL_ARB_texture_query_lod", 1);
2463 if (extensions->ARB_gpu_shader5)
2464 add_builtin_define(parser, "GL_ARB_gpu_shader5", 1);
2466 if (extensions->ARB_gpu_shader_fp64)
2467 add_builtin_define(parser, "GL_ARB_gpu_shader_fp64", 1);
2469 if (extensions->ARB_vertex_attrib_64bit)
2470 add_builtin_define(parser, "GL_ARB_vertex_attrib_64bit", 1);
2472 if (extensions->AMD_vertex_shader_layer)
2473 add_builtin_define(parser, "GL_AMD_vertex_shader_layer", 1);
2475 if (extensions->AMD_vertex_shader_viewport_index)
2476 add_builtin_define(parser, "GL_AMD_vertex_shader_viewport_index", 1);
2478 if (extensions->ARB_shading_language_420pack)
2479 add_builtin_define(parser, "GL_ARB_shading_language_420pack", 1);
2481 if (extensions->ARB_sample_shading)
2482 add_builtin_define(parser, "GL_ARB_sample_shading", 1);
2484 if (extensions->ARB_texture_gather)
2485 add_builtin_define(parser, "GL_ARB_texture_gather", 1);
2487 if (extensions->ARB_shader_atomic_counters)
2488 add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1);
2490 if (extensions->ARB_viewport_array)
2491 add_builtin_define(parser, "GL_ARB_viewport_array", 1);
2493 if (extensions->ARB_compute_shader)
2494 add_builtin_define(parser, "GL_ARB_compute_shader", 1);
2496 if (extensions->ARB_shader_image_load_store)
2497 add_builtin_define(parser, "GL_ARB_shader_image_load_store", 1);
2499 if (extensions->ARB_shader_image_size)
2500 add_builtin_define(parser, "GL_ARB_shader_image_size", 1);
2502 if (extensions->ARB_shader_texture_image_samples)
2503 add_builtin_define(parser, "GL_ARB_shader_texture_image_samples", 1);
2505 if (extensions->ARB_derivative_control)
2506 add_builtin_define(parser, "GL_ARB_derivative_control", 1);
2508 if (extensions->ARB_shader_precision)
2509 add_builtin_define(parser, "GL_ARB_shader_precision", 1);
2511 if (extensions->ARB_shader_storage_buffer_object)
2512 add_builtin_define(parser, "GL_ARB_shader_storage_buffer_object", 1);
2514 if (extensions->ARB_tessellation_shader)
2515 add_builtin_define(parser, "GL_ARB_tessellation_shader", 1);
2517 if (extensions->ARB_shader_subroutine)
2518 add_builtin_define(parser, "GL_ARB_shader_subroutine", 1);
2520 if (extensions->ARB_shader_draw_parameters)
2521 add_builtin_define(parser, "GL_ARB_shader_draw_parameters", 1);
2525 if (extensions != NULL) {
2526 if (extensions->EXT_shader_integer_mix)
2527 add_builtin_define(parser, "GL_EXT_shader_integer_mix", 1);
2529 if (extensions->EXT_shader_samples_identical)
2530 add_builtin_define(parser, "GL_EXT_shader_samples_identical", 1);
2534 add_builtin_define(parser, "GL_core_profile", 1);
2536 /* Currently, all ES2/ES3 implementations support highp in the
2537 * fragment shader, so we always define this macro in ES2/ES3.
2538 * If we ever get a driver that doesn't support highp, we'll
2539 * need to add a flag to the gl_context and check that here.
2541 if (version >= 130 || parser->is_gles)
2542 add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
2544 if (explicitly_set) {
2545 ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length,
2546 "#version %" PRIiMAX "%s%s", version,
2547 es_identifier ? " " : "",
2548 es_identifier ? es_identifier : "");
2552 /* GLSL version if no version is explicitly specified. */
2553 #define IMPLICIT_GLSL_VERSION 110
2555 /* GLSL ES version if no version is explicitly specified. */
2556 #define IMPLICIT_GLSL_ES_VERSION 100
2559 glcpp_parser_resolve_implicit_version(glcpp_parser_t *parser)
2561 int language_version = parser->api == API_OPENGLES2 ?
2562 IMPLICIT_GLSL_ES_VERSION :
2563 IMPLICIT_GLSL_VERSION;
2565 _glcpp_parser_handle_version_declaration(parser, language_version,