glcpp-parse.y revision 01e04c3f
1%{ 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> 27#include <string.h> 28#include <assert.h> 29#include <inttypes.h> 30 31#include "glcpp.h" 32#include "main/mtypes.h" 33 34static void 35yyerror(YYLTYPE *locp, glcpp_parser_t *parser, const char *error); 36 37static void 38_define_object_macro(glcpp_parser_t *parser, 39 YYLTYPE *loc, 40 const char *macro, 41 token_list_t *replacements); 42 43static void 44_define_function_macro(glcpp_parser_t *parser, 45 YYLTYPE *loc, 46 const char *macro, 47 string_list_t *parameters, 48 token_list_t *replacements); 49 50static string_list_t * 51_string_list_create(glcpp_parser_t *parser); 52 53static void 54_string_list_append_item(glcpp_parser_t *parser, string_list_t *list, 55 const char *str); 56 57static int 58_string_list_contains(string_list_t *list, const char *member, int *index); 59 60static const char * 61_string_list_has_duplicate(string_list_t *list); 62 63static int 64_string_list_length(string_list_t *list); 65 66static int 67_string_list_equal(string_list_t *a, string_list_t *b); 68 69static argument_list_t * 70_argument_list_create(glcpp_parser_t *parser); 71 72static void 73_argument_list_append(glcpp_parser_t *parser, argument_list_t *list, 74 token_list_t *argument); 75 76static int 77_argument_list_length(argument_list_t *list); 78 79static token_list_t * 80_argument_list_member_at(argument_list_t *list, int index); 81 82static token_t * 83_token_create_str(glcpp_parser_t *parser, int type, char *str); 84 85static token_t * 86_token_create_ival(glcpp_parser_t *parser, int type, int ival); 87 88static token_list_t * 89_token_list_create(glcpp_parser_t *parser); 90 91static void 92_token_list_append(glcpp_parser_t *parser, token_list_t *list, token_t *token); 93 94static void 95_token_list_append_list(token_list_t *list, token_list_t *tail); 96 97static int 98_token_list_equal_ignoring_space(token_list_t *a, token_list_t *b); 99 100static void 101_parser_active_list_push(glcpp_parser_t *parser, const char *identifier, 102 token_node_t *marker); 103 104static void 105_parser_active_list_pop(glcpp_parser_t *parser); 106 107static int 108_parser_active_list_contains(glcpp_parser_t *parser, const char *identifier); 109 110typedef enum { 111 EXPANSION_MODE_IGNORE_DEFINED, 112 EXPANSION_MODE_EVALUATE_DEFINED 113} expansion_mode_t; 114 115/* Expand list, and begin lexing from the result (after first 116 * prefixing a token of type 'head_token_type'). 117 */ 118static void 119_glcpp_parser_expand_and_lex_from(glcpp_parser_t *parser, int head_token_type, 120 token_list_t *list, expansion_mode_t mode); 121 122/* Perform macro expansion in-place on the given list. */ 123static void 124_glcpp_parser_expand_token_list(glcpp_parser_t *parser, token_list_t *list, 125 expansion_mode_t mode); 126 127static void 128_glcpp_parser_print_expanded_token_list(glcpp_parser_t *parser, 129 token_list_t *list); 130 131static void 132_glcpp_parser_skip_stack_push_if(glcpp_parser_t *parser, YYLTYPE *loc, 133 int condition); 134 135static void 136_glcpp_parser_skip_stack_change_if(glcpp_parser_t *parser, YYLTYPE *loc, 137 const char *type, int condition); 138 139static void 140_glcpp_parser_skip_stack_pop(glcpp_parser_t *parser, YYLTYPE *loc); 141 142static void 143_glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version, 144 const char *ident, bool explicitly_set); 145 146static int 147glcpp_parser_lex(YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser); 148 149static void 150glcpp_parser_lex_from(glcpp_parser_t *parser, token_list_t *list); 151 152static void 153add_builtin_define(glcpp_parser_t *parser, const char *name, int value); 154 155%} 156 157%pure-parser 158%error-verbose 159 160%locations 161%initial-action { 162 @$.first_line = 1; 163 @$.first_column = 1; 164 @$.last_line = 1; 165 @$.last_column = 1; 166 @$.source = 0; 167} 168 169%parse-param {glcpp_parser_t *parser} 170%lex-param {glcpp_parser_t *parser} 171 172%expect 0 173 174 /* We use HASH_TOKEN, DEFINE_TOKEN and VERSION_TOKEN (as opposed to 175 * HASH, DEFINE, and VERSION) to avoid conflicts with other symbols, 176 * (such as the <HASH> and <DEFINE> start conditions in the lexer). */ 177%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 178%token PASTE 179%type <ival> INTEGER operator SPACE integer_constant version_constant 180%type <expression_value> expression 181%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA 182%type <string_list> identifier_list 183%type <token> preprocessing_token 184%type <token_list> pp_tokens replacement_list text_line 185%left OR 186%left AND 187%left '|' 188%left '^' 189%left '&' 190%left EQUAL NOT_EQUAL 191%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL 192%left LEFT_SHIFT RIGHT_SHIFT 193%left '+' '-' 194%left '*' '/' '%' 195%right UNARY 196 197%debug 198 199%% 200 201input: 202 /* empty */ 203| input line 204; 205 206line: 207 control_line 208| SPACE control_line 209| text_line { 210 _glcpp_parser_print_expanded_token_list (parser, $1); 211 _mesa_string_buffer_append_char(parser->output, '\n'); 212 } 213| expanded_line 214; 215 216expanded_line: 217 IF_EXPANDED expression NEWLINE { 218 if (parser->is_gles && $2.undefined_macro) 219 glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $2.undefined_macro); 220 _glcpp_parser_skip_stack_push_if (parser, & @1, $2.value); 221 } 222| ELIF_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_change_if (parser, & @1, "elif", $2.value); 226 } 227| LINE_EXPANDED integer_constant NEWLINE { 228 parser->has_new_line_number = 1; 229 parser->new_line_number = $2; 230 _mesa_string_buffer_printf(parser->output, "#line %" PRIiMAX "\n", $2); 231 } 232| LINE_EXPANDED integer_constant integer_constant NEWLINE { 233 parser->has_new_line_number = 1; 234 parser->new_line_number = $2; 235 parser->has_new_source_number = 1; 236 parser->new_source_number = $3; 237 _mesa_string_buffer_printf(parser->output, 238 "#line %" PRIiMAX " %" PRIiMAX "\n", 239 $2, $3); 240 } 241; 242 243define: 244 OBJ_IDENTIFIER replacement_list NEWLINE { 245 _define_object_macro (parser, & @1, $1, $2); 246 } 247| FUNC_IDENTIFIER '(' ')' replacement_list NEWLINE { 248 _define_function_macro (parser, & @1, $1, NULL, $4); 249 } 250| FUNC_IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE { 251 _define_function_macro (parser, & @1, $1, $3, $5); 252 } 253; 254 255control_line: 256 control_line_success { 257 _mesa_string_buffer_append_char(parser->output, '\n'); 258 } 259| control_line_error 260| HASH_TOKEN LINE pp_tokens NEWLINE { 261 262 if (parser->skip_stack == NULL || 263 parser->skip_stack->type == SKIP_NO_SKIP) 264 { 265 _glcpp_parser_expand_and_lex_from (parser, 266 LINE_EXPANDED, $3, 267 EXPANSION_MODE_IGNORE_DEFINED); 268 } 269 } 270; 271 272control_line_success: 273 HASH_TOKEN DEFINE_TOKEN define 274| HASH_TOKEN UNDEF IDENTIFIER NEWLINE { 275 struct hash_entry *entry; 276 277 /* Section 3.4 (Preprocessor) of the GLSL ES 3.00 spec says: 278 * 279 * It is an error to undefine or to redefine a built-in 280 * (pre-defined) macro name. 281 * 282 * The GLSL ES 1.00 spec does not contain this text, but 283 * dEQP's preprocess test in GLES2 checks for it. 284 * 285 * Section 3.3 (Preprocessor) revision 7, of the GLSL 4.50 286 * spec says: 287 * 288 * By convention, all macro names containing two consecutive 289 * underscores ( __ ) are reserved for use by underlying 290 * software layers. Defining or undefining such a name 291 * in a shader does not itself result in an error, but may 292 * result in unintended behaviors that stem from having 293 * multiple definitions of the same name. All macro names 294 * prefixed with "GL_" (...) are also reseved, and defining 295 * such a name results in a compile-time error. 296 * 297 * The code below implements the same checks as GLSLang. 298 */ 299 if (strncmp("GL_", $3, 3) == 0) 300 glcpp_error(& @1, parser, "Built-in (pre-defined)" 301 " names beginning with GL_ cannot be undefined."); 302 else if (strstr($3, "__") != NULL) { 303 if (parser->is_gles 304 && parser->version >= 300 305 && (strcmp("__LINE__", $3) == 0 306 || strcmp("__FILE__", $3) == 0 307 || strcmp("__VERSION__", $3) == 0)) { 308 glcpp_error(& @1, parser, "Built-in (pre-defined)" 309 " names cannot be undefined."); 310 } else if (parser->is_gles && parser->version <= 300) { 311 glcpp_error(& @1, parser, 312 " names containing consecutive underscores" 313 " are reserved."); 314 } else { 315 glcpp_warning(& @1, parser, 316 " names containing consecutive underscores" 317 " are reserved."); 318 } 319 } 320 321 entry = _mesa_hash_table_search (parser->defines, $3); 322 if (entry) { 323 _mesa_hash_table_remove (parser->defines, entry); 324 } 325 } 326| HASH_TOKEN IF pp_tokens NEWLINE { 327 /* Be careful to only evaluate the 'if' expression if 328 * we are not skipping. When we are skipping, we 329 * simply push a new 0-valued 'if' onto the skip 330 * stack. 331 * 332 * This avoids generating diagnostics for invalid 333 * expressions that are being skipped. */ 334 if (parser->skip_stack == NULL || 335 parser->skip_stack->type == SKIP_NO_SKIP) 336 { 337 _glcpp_parser_expand_and_lex_from (parser, 338 IF_EXPANDED, $3, 339 EXPANSION_MODE_EVALUATE_DEFINED); 340 } 341 else 342 { 343 _glcpp_parser_skip_stack_push_if (parser, & @1, 0); 344 parser->skip_stack->type = SKIP_TO_ENDIF; 345 } 346 } 347| HASH_TOKEN IF NEWLINE { 348 /* #if without an expression is only an error if we 349 * are not skipping */ 350 if (parser->skip_stack == NULL || 351 parser->skip_stack->type == SKIP_NO_SKIP) 352 { 353 glcpp_error(& @1, parser, "#if with no expression"); 354 } 355 _glcpp_parser_skip_stack_push_if (parser, & @1, 0); 356 } 357| HASH_TOKEN IFDEF IDENTIFIER junk NEWLINE { 358 struct hash_entry *entry = 359 _mesa_hash_table_search(parser->defines, $3); 360 macro_t *macro = entry ? entry->data : NULL; 361 _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL); 362 } 363| HASH_TOKEN IFNDEF IDENTIFIER junk NEWLINE { 364 struct hash_entry *entry = 365 _mesa_hash_table_search(parser->defines, $3); 366 macro_t *macro = entry ? entry->data : NULL; 367 _glcpp_parser_skip_stack_push_if (parser, & @3, macro == NULL); 368 } 369| HASH_TOKEN ELIF pp_tokens NEWLINE { 370 /* Be careful to only evaluate the 'elif' expression 371 * if we are not skipping. When we are skipping, we 372 * simply change to a 0-valued 'elif' on the skip 373 * stack. 374 * 375 * This avoids generating diagnostics for invalid 376 * expressions that are being skipped. */ 377 if (parser->skip_stack && 378 parser->skip_stack->type == SKIP_TO_ELSE) 379 { 380 _glcpp_parser_expand_and_lex_from (parser, 381 ELIF_EXPANDED, $3, 382 EXPANSION_MODE_EVALUATE_DEFINED); 383 } 384 else if (parser->skip_stack && 385 parser->skip_stack->has_else) 386 { 387 glcpp_error(& @1, parser, "#elif after #else"); 388 } 389 else 390 { 391 _glcpp_parser_skip_stack_change_if (parser, & @1, 392 "elif", 0); 393 } 394 } 395| HASH_TOKEN ELIF NEWLINE { 396 /* #elif without an expression is an error unless we 397 * are skipping. */ 398 if (parser->skip_stack && 399 parser->skip_stack->type == SKIP_TO_ELSE) 400 { 401 glcpp_error(& @1, parser, "#elif with no expression"); 402 } 403 else if (parser->skip_stack && 404 parser->skip_stack->has_else) 405 { 406 glcpp_error(& @1, parser, "#elif after #else"); 407 } 408 else 409 { 410 _glcpp_parser_skip_stack_change_if (parser, & @1, 411 "elif", 0); 412 glcpp_warning(& @1, parser, "ignoring illegal #elif without expression"); 413 } 414 } 415| HASH_TOKEN ELSE { parser->lexing_directive = 1; } NEWLINE { 416 if (parser->skip_stack && 417 parser->skip_stack->has_else) 418 { 419 glcpp_error(& @1, parser, "multiple #else"); 420 } 421 else 422 { 423 _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1); 424 if (parser->skip_stack) 425 parser->skip_stack->has_else = true; 426 } 427 } 428| HASH_TOKEN ENDIF { 429 _glcpp_parser_skip_stack_pop (parser, & @1); 430 } NEWLINE 431| HASH_TOKEN VERSION_TOKEN version_constant NEWLINE { 432 if (parser->version_set) { 433 glcpp_error(& @1, parser, "#version must appear on the first line"); 434 } 435 _glcpp_parser_handle_version_declaration(parser, $3, NULL, true); 436 } 437| HASH_TOKEN VERSION_TOKEN version_constant IDENTIFIER NEWLINE { 438 if (parser->version_set) { 439 glcpp_error(& @1, parser, "#version must appear on the first line"); 440 } 441 _glcpp_parser_handle_version_declaration(parser, $3, $4, true); 442 } 443| HASH_TOKEN NEWLINE { 444 glcpp_parser_resolve_implicit_version(parser); 445 } 446| HASH_TOKEN PRAGMA NEWLINE { 447 _mesa_string_buffer_printf(parser->output, "#%s", $2); 448 } 449; 450 451control_line_error: 452 HASH_TOKEN ERROR_TOKEN NEWLINE { 453 glcpp_error(& @1, parser, "#%s", $2); 454 } 455| HASH_TOKEN DEFINE_TOKEN NEWLINE { 456 glcpp_error (& @1, parser, "#define without macro name"); 457 } 458| HASH_TOKEN GARBAGE pp_tokens NEWLINE { 459 glcpp_error (& @1, parser, "Illegal non-directive after #"); 460 } 461; 462 463integer_constant: 464 INTEGER_STRING { 465 /* let strtoll detect the base */ 466 $$ = strtoll ($1, NULL, 0); 467 } 468| INTEGER { 469 $$ = $1; 470 } 471 472version_constant: 473 INTEGER_STRING { 474 /* Both octal and hexadecimal constants begin with 0. */ 475 if ($1[0] == '0' && $1[1] != '\0') { 476 glcpp_error(&@1, parser, "invalid #version \"%s\" (not a decimal constant)", $1); 477 $$ = 0; 478 } else { 479 $$ = strtoll($1, NULL, 10); 480 } 481 } 482 483expression: 484 integer_constant { 485 $$.value = $1; 486 $$.undefined_macro = NULL; 487 } 488| IDENTIFIER { 489 $$.value = 0; 490 if (parser->is_gles) 491 $$.undefined_macro = linear_strdup(parser->linalloc, $1); 492 else 493 $$.undefined_macro = NULL; 494 } 495| expression OR expression { 496 $$.value = $1.value || $3.value; 497 498 /* Short-circuit: Only flag undefined from right side 499 * if left side evaluates to false. 500 */ 501 if ($1.undefined_macro) 502 $$.undefined_macro = $1.undefined_macro; 503 else if (! $1.value) 504 $$.undefined_macro = $3.undefined_macro; 505 } 506| expression AND expression { 507 $$.value = $1.value && $3.value; 508 509 /* Short-circuit: Only flag undefined from right-side 510 * if left side evaluates to true. 511 */ 512 if ($1.undefined_macro) 513 $$.undefined_macro = $1.undefined_macro; 514 else if ($1.value) 515 $$.undefined_macro = $3.undefined_macro; 516 } 517| expression '|' expression { 518 $$.value = $1.value | $3.value; 519 if ($1.undefined_macro) 520 $$.undefined_macro = $1.undefined_macro; 521 else 522 $$.undefined_macro = $3.undefined_macro; 523 } 524| expression '^' expression { 525 $$.value = $1.value ^ $3.value; 526 if ($1.undefined_macro) 527 $$.undefined_macro = $1.undefined_macro; 528 else 529 $$.undefined_macro = $3.undefined_macro; 530 } 531| expression '&' expression { 532 $$.value = $1.value & $3.value; 533 if ($1.undefined_macro) 534 $$.undefined_macro = $1.undefined_macro; 535 else 536 $$.undefined_macro = $3.undefined_macro; 537 } 538| expression NOT_EQUAL expression { 539 $$.value = $1.value != $3.value; 540 if ($1.undefined_macro) 541 $$.undefined_macro = $1.undefined_macro; 542 else 543 $$.undefined_macro = $3.undefined_macro; 544 } 545| expression EQUAL expression { 546 $$.value = $1.value == $3.value; 547 if ($1.undefined_macro) 548 $$.undefined_macro = $1.undefined_macro; 549 else 550 $$.undefined_macro = $3.undefined_macro; 551 } 552| expression GREATER_OR_EQUAL expression { 553 $$.value = $1.value >= $3.value; 554 if ($1.undefined_macro) 555 $$.undefined_macro = $1.undefined_macro; 556 else 557 $$.undefined_macro = $3.undefined_macro; 558 } 559| expression LESS_OR_EQUAL expression { 560 $$.value = $1.value <= $3.value; 561 if ($1.undefined_macro) 562 $$.undefined_macro = $1.undefined_macro; 563 else 564 $$.undefined_macro = $3.undefined_macro; 565 } 566| expression '>' expression { 567 $$.value = $1.value > $3.value; 568 if ($1.undefined_macro) 569 $$.undefined_macro = $1.undefined_macro; 570 else 571 $$.undefined_macro = $3.undefined_macro; 572 } 573| expression '<' expression { 574 $$.value = $1.value < $3.value; 575 if ($1.undefined_macro) 576 $$.undefined_macro = $1.undefined_macro; 577 else 578 $$.undefined_macro = $3.undefined_macro; 579 } 580| expression RIGHT_SHIFT expression { 581 $$.value = $1.value >> $3.value; 582 if ($1.undefined_macro) 583 $$.undefined_macro = $1.undefined_macro; 584 else 585 $$.undefined_macro = $3.undefined_macro; 586 } 587| expression LEFT_SHIFT expression { 588 $$.value = $1.value << $3.value; 589 if ($1.undefined_macro) 590 $$.undefined_macro = $1.undefined_macro; 591 else 592 $$.undefined_macro = $3.undefined_macro; 593 } 594| expression '-' expression { 595 $$.value = $1.value - $3.value; 596 if ($1.undefined_macro) 597 $$.undefined_macro = $1.undefined_macro; 598 else 599 $$.undefined_macro = $3.undefined_macro; 600 } 601| expression '+' expression { 602 $$.value = $1.value + $3.value; 603 if ($1.undefined_macro) 604 $$.undefined_macro = $1.undefined_macro; 605 else 606 $$.undefined_macro = $3.undefined_macro; 607 } 608| expression '%' expression { 609 if ($3.value == 0) { 610 yyerror (& @1, parser, 611 "zero modulus in preprocessor directive"); 612 } else { 613 $$.value = $1.value % $3.value; 614 } 615 if ($1.undefined_macro) 616 $$.undefined_macro = $1.undefined_macro; 617 else 618 $$.undefined_macro = $3.undefined_macro; 619 } 620| expression '/' expression { 621 if ($3.value == 0) { 622 yyerror (& @1, parser, 623 "division by 0 in preprocessor directive"); 624 } else { 625 $$.value = $1.value / $3.value; 626 } 627 if ($1.undefined_macro) 628 $$.undefined_macro = $1.undefined_macro; 629 else 630 $$.undefined_macro = $3.undefined_macro; 631 } 632| expression '*' expression { 633 $$.value = $1.value * $3.value; 634 if ($1.undefined_macro) 635 $$.undefined_macro = $1.undefined_macro; 636 else 637 $$.undefined_macro = $3.undefined_macro; 638 } 639| '!' expression %prec UNARY { 640 $$.value = ! $2.value; 641 $$.undefined_macro = $2.undefined_macro; 642 } 643| '~' expression %prec UNARY { 644 $$.value = ~ $2.value; 645 $$.undefined_macro = $2.undefined_macro; 646 } 647| '-' expression %prec UNARY { 648 $$.value = - $2.value; 649 $$.undefined_macro = $2.undefined_macro; 650 } 651| '+' expression %prec UNARY { 652 $$.value = + $2.value; 653 $$.undefined_macro = $2.undefined_macro; 654 } 655| '(' expression ')' { 656 $$ = $2; 657 } 658; 659 660identifier_list: 661 IDENTIFIER { 662 $$ = _string_list_create (parser); 663 _string_list_append_item (parser, $$, $1); 664 } 665| identifier_list ',' IDENTIFIER { 666 $$ = $1; 667 _string_list_append_item (parser, $$, $3); 668 } 669; 670 671text_line: 672 NEWLINE { $$ = NULL; } 673| pp_tokens NEWLINE 674; 675 676replacement_list: 677 /* empty */ { $$ = NULL; } 678| pp_tokens 679; 680 681junk: 682 /* empty */ 683| pp_tokens { 684 glcpp_error(&@1, parser, "extra tokens at end of directive"); 685 } 686; 687 688pp_tokens: 689 preprocessing_token { 690 parser->space_tokens = 1; 691 $$ = _token_list_create (parser); 692 _token_list_append (parser, $$, $1); 693 } 694| pp_tokens preprocessing_token { 695 $$ = $1; 696 _token_list_append (parser, $$, $2); 697 } 698; 699 700preprocessing_token: 701 IDENTIFIER { 702 $$ = _token_create_str (parser, IDENTIFIER, $1); 703 $$->location = yylloc; 704 } 705| INTEGER_STRING { 706 $$ = _token_create_str (parser, INTEGER_STRING, $1); 707 $$->location = yylloc; 708 } 709| operator { 710 $$ = _token_create_ival (parser, $1, $1); 711 $$->location = yylloc; 712 } 713| DEFINED { 714 $$ = _token_create_ival (parser, DEFINED, DEFINED); 715 $$->location = yylloc; 716 } 717| OTHER { 718 $$ = _token_create_str (parser, OTHER, $1); 719 $$->location = yylloc; 720 } 721| SPACE { 722 $$ = _token_create_ival (parser, SPACE, SPACE); 723 $$->location = yylloc; 724 } 725; 726 727operator: 728 '[' { $$ = '['; } 729| ']' { $$ = ']'; } 730| '(' { $$ = '('; } 731| ')' { $$ = ')'; } 732| '{' { $$ = '{'; } 733| '}' { $$ = '}'; } 734| '.' { $$ = '.'; } 735| '&' { $$ = '&'; } 736| '*' { $$ = '*'; } 737| '+' { $$ = '+'; } 738| '-' { $$ = '-'; } 739| '~' { $$ = '~'; } 740| '!' { $$ = '!'; } 741| '/' { $$ = '/'; } 742| '%' { $$ = '%'; } 743| LEFT_SHIFT { $$ = LEFT_SHIFT; } 744| RIGHT_SHIFT { $$ = RIGHT_SHIFT; } 745| '<' { $$ = '<'; } 746| '>' { $$ = '>'; } 747| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; } 748| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; } 749| EQUAL { $$ = EQUAL; } 750| NOT_EQUAL { $$ = NOT_EQUAL; } 751| '^' { $$ = '^'; } 752| '|' { $$ = '|'; } 753| AND { $$ = AND; } 754| OR { $$ = OR; } 755| ';' { $$ = ';'; } 756| ',' { $$ = ','; } 757| '=' { $$ = '='; } 758| PASTE { $$ = PASTE; } 759| PLUS_PLUS { $$ = PLUS_PLUS; } 760| MINUS_MINUS { $$ = MINUS_MINUS; } 761; 762 763%% 764 765string_list_t * 766_string_list_create(glcpp_parser_t *parser) 767{ 768 string_list_t *list; 769 770 list = linear_alloc_child(parser->linalloc, sizeof(string_list_t)); 771 list->head = NULL; 772 list->tail = NULL; 773 774 return list; 775} 776 777void 778_string_list_append_item(glcpp_parser_t *parser, string_list_t *list, 779 const char *str) 780{ 781 string_node_t *node; 782 783 node = linear_alloc_child(parser->linalloc, sizeof(string_node_t)); 784 node->str = linear_strdup(parser->linalloc, str); 785 786 node->next = NULL; 787 788 if (list->head == NULL) { 789 list->head = node; 790 } else { 791 list->tail->next = node; 792 } 793 794 list->tail = node; 795} 796 797int 798_string_list_contains(string_list_t *list, const char *member, int *index) 799{ 800 string_node_t *node; 801 int i; 802 803 if (list == NULL) 804 return 0; 805 806 for (i = 0, node = list->head; node; i++, node = node->next) { 807 if (strcmp (node->str, member) == 0) { 808 if (index) 809 *index = i; 810 return 1; 811 } 812 } 813 814 return 0; 815} 816 817/* Return duplicate string in list (if any), NULL otherwise. */ 818const char * 819_string_list_has_duplicate(string_list_t *list) 820{ 821 string_node_t *node, *dup; 822 823 if (list == NULL) 824 return NULL; 825 826 for (node = list->head; node; node = node->next) { 827 for (dup = node->next; dup; dup = dup->next) { 828 if (strcmp (node->str, dup->str) == 0) 829 return node->str; 830 } 831 } 832 833 return NULL; 834} 835 836int 837_string_list_length(string_list_t *list) 838{ 839 int length = 0; 840 string_node_t *node; 841 842 if (list == NULL) 843 return 0; 844 845 for (node = list->head; node; node = node->next) 846 length++; 847 848 return length; 849} 850 851int 852_string_list_equal(string_list_t *a, string_list_t *b) 853{ 854 string_node_t *node_a, *node_b; 855 856 if (a == NULL && b == NULL) 857 return 1; 858 859 if (a == NULL || b == NULL) 860 return 0; 861 862 for (node_a = a->head, node_b = b->head; 863 node_a && node_b; 864 node_a = node_a->next, node_b = node_b->next) 865 { 866 if (strcmp (node_a->str, node_b->str)) 867 return 0; 868 } 869 870 /* Catch the case of lists being different lengths, (which 871 * would cause the loop above to terminate after the shorter 872 * list). */ 873 return node_a == node_b; 874} 875 876argument_list_t * 877_argument_list_create(glcpp_parser_t *parser) 878{ 879 argument_list_t *list; 880 881 list = linear_alloc_child(parser->linalloc, sizeof(argument_list_t)); 882 list->head = NULL; 883 list->tail = NULL; 884 885 return list; 886} 887 888void 889_argument_list_append(glcpp_parser_t *parser, 890 argument_list_t *list, token_list_t *argument) 891{ 892 argument_node_t *node; 893 894 node = linear_alloc_child(parser->linalloc, sizeof(argument_node_t)); 895 node->argument = argument; 896 897 node->next = NULL; 898 899 if (list->head == NULL) { 900 list->head = node; 901 } else { 902 list->tail->next = node; 903 } 904 905 list->tail = node; 906} 907 908int 909_argument_list_length(argument_list_t *list) 910{ 911 int length = 0; 912 argument_node_t *node; 913 914 if (list == NULL) 915 return 0; 916 917 for (node = list->head; node; node = node->next) 918 length++; 919 920 return length; 921} 922 923token_list_t * 924_argument_list_member_at(argument_list_t *list, int index) 925{ 926 argument_node_t *node; 927 int i; 928 929 if (list == NULL) 930 return NULL; 931 932 node = list->head; 933 for (i = 0; i < index; i++) { 934 node = node->next; 935 if (node == NULL) 936 break; 937 } 938 939 if (node) 940 return node->argument; 941 942 return NULL; 943} 944 945token_t * 946_token_create_str(glcpp_parser_t *parser, int type, char *str) 947{ 948 token_t *token; 949 950 token = linear_alloc_child(parser->linalloc, sizeof(token_t)); 951 token->type = type; 952 token->value.str = str; 953 954 return token; 955} 956 957token_t * 958_token_create_ival(glcpp_parser_t *parser, int type, int ival) 959{ 960 token_t *token; 961 962 token = linear_alloc_child(parser->linalloc, sizeof(token_t)); 963 token->type = type; 964 token->value.ival = ival; 965 966 return token; 967} 968 969token_list_t * 970_token_list_create(glcpp_parser_t *parser) 971{ 972 token_list_t *list; 973 974 list = linear_alloc_child(parser->linalloc, sizeof(token_list_t)); 975 list->head = NULL; 976 list->tail = NULL; 977 list->non_space_tail = NULL; 978 979 return list; 980} 981 982void 983_token_list_append(glcpp_parser_t *parser, token_list_t *list, token_t *token) 984{ 985 token_node_t *node; 986 987 node = linear_alloc_child(parser->linalloc, sizeof(token_node_t)); 988 node->token = token; 989 node->next = NULL; 990 991 if (list->head == NULL) { 992 list->head = node; 993 } else { 994 list->tail->next = node; 995 } 996 997 list->tail = node; 998 if (token->type != SPACE) 999 list->non_space_tail = node; 1000} 1001 1002void 1003_token_list_append_list(token_list_t *list, token_list_t *tail) 1004{ 1005 if (tail == NULL || tail->head == NULL) 1006 return; 1007 1008 if (list->head == NULL) { 1009 list->head = tail->head; 1010 } else { 1011 list->tail->next = tail->head; 1012 } 1013 1014 list->tail = tail->tail; 1015 list->non_space_tail = tail->non_space_tail; 1016} 1017 1018static token_list_t * 1019_token_list_copy(glcpp_parser_t *parser, token_list_t *other) 1020{ 1021 token_list_t *copy; 1022 token_node_t *node; 1023 1024 if (other == NULL) 1025 return NULL; 1026 1027 copy = _token_list_create (parser); 1028 for (node = other->head; node; node = node->next) { 1029 token_t *new_token = linear_alloc_child(parser->linalloc, sizeof(token_t)); 1030 *new_token = *node->token; 1031 _token_list_append (parser, copy, new_token); 1032 } 1033 1034 return copy; 1035} 1036 1037static void 1038_token_list_trim_trailing_space(token_list_t *list) 1039{ 1040 if (list->non_space_tail) { 1041 list->non_space_tail->next = NULL; 1042 list->tail = list->non_space_tail; 1043 } 1044} 1045 1046static int 1047_token_list_is_empty_ignoring_space(token_list_t *l) 1048{ 1049 token_node_t *n; 1050 1051 if (l == NULL) 1052 return 1; 1053 1054 n = l->head; 1055 while (n != NULL && n->token->type == SPACE) 1056 n = n->next; 1057 1058 return n == NULL; 1059} 1060 1061int 1062_token_list_equal_ignoring_space(token_list_t *a, token_list_t *b) 1063{ 1064 token_node_t *node_a, *node_b; 1065 1066 if (a == NULL || b == NULL) { 1067 int a_empty = _token_list_is_empty_ignoring_space(a); 1068 int b_empty = _token_list_is_empty_ignoring_space(b); 1069 return a_empty == b_empty; 1070 } 1071 1072 node_a = a->head; 1073 node_b = b->head; 1074 1075 while (1) 1076 { 1077 if (node_a == NULL && node_b == NULL) 1078 break; 1079 1080 /* Ignore trailing whitespace */ 1081 if (node_a == NULL && node_b->token->type == SPACE) { 1082 while (node_b && node_b->token->type == SPACE) 1083 node_b = node_b->next; 1084 } 1085 1086 if (node_b == NULL && node_a->token->type == SPACE) { 1087 while (node_a && node_a->token->type == SPACE) 1088 node_a = node_a->next; 1089 } 1090 1091 if (node_a == NULL && node_b == NULL) 1092 break; 1093 1094 if (node_a == NULL || node_b == NULL) 1095 return 0; 1096 /* Make sure whitespace appears in the same places in both. 1097 * It need not be exactly the same amount of whitespace, 1098 * though. 1099 */ 1100 if (node_a->token->type == SPACE && node_b->token->type == SPACE) { 1101 while (node_a && node_a->token->type == SPACE) 1102 node_a = node_a->next; 1103 while (node_b && node_b->token->type == SPACE) 1104 node_b = node_b->next; 1105 continue; 1106 } 1107 1108 if (node_a->token->type != node_b->token->type) 1109 return 0; 1110 1111 switch (node_a->token->type) { 1112 case INTEGER: 1113 if (node_a->token->value.ival != node_b->token->value.ival) { 1114 return 0; 1115 } 1116 break; 1117 case IDENTIFIER: 1118 case INTEGER_STRING: 1119 case OTHER: 1120 if (strcmp(node_a->token->value.str, node_b->token->value.str)) { 1121 return 0; 1122 } 1123 break; 1124 } 1125 1126 node_a = node_a->next; 1127 node_b = node_b->next; 1128 } 1129 1130 return 1; 1131} 1132 1133static void 1134_token_print(struct _mesa_string_buffer *out, token_t *token) 1135{ 1136 if (token->type < 256) { 1137 _mesa_string_buffer_append_char(out, token->type); 1138 return; 1139 } 1140 1141 switch (token->type) { 1142 case INTEGER: 1143 _mesa_string_buffer_printf(out, "%" PRIiMAX, token->value.ival); 1144 break; 1145 case IDENTIFIER: 1146 case INTEGER_STRING: 1147 case OTHER: 1148 _mesa_string_buffer_append(out, token->value.str); 1149 break; 1150 case SPACE: 1151 _mesa_string_buffer_append_char(out, ' '); 1152 break; 1153 case LEFT_SHIFT: 1154 _mesa_string_buffer_append(out, "<<"); 1155 break; 1156 case RIGHT_SHIFT: 1157 _mesa_string_buffer_append(out, ">>"); 1158 break; 1159 case LESS_OR_EQUAL: 1160 _mesa_string_buffer_append(out, "<="); 1161 break; 1162 case GREATER_OR_EQUAL: 1163 _mesa_string_buffer_append(out, ">="); 1164 break; 1165 case EQUAL: 1166 _mesa_string_buffer_append(out, "=="); 1167 break; 1168 case NOT_EQUAL: 1169 _mesa_string_buffer_append(out, "!="); 1170 break; 1171 case AND: 1172 _mesa_string_buffer_append(out, "&&"); 1173 break; 1174 case OR: 1175 _mesa_string_buffer_append(out, "||"); 1176 break; 1177 case PASTE: 1178 _mesa_string_buffer_append(out, "##"); 1179 break; 1180 case PLUS_PLUS: 1181 _mesa_string_buffer_append(out, "++"); 1182 break; 1183 case MINUS_MINUS: 1184 _mesa_string_buffer_append(out, "--"); 1185 break; 1186 case DEFINED: 1187 _mesa_string_buffer_append(out, "defined"); 1188 break; 1189 case PLACEHOLDER: 1190 /* Nothing to print. */ 1191 break; 1192 default: 1193 assert(!"Error: Don't know how to print token."); 1194 1195 break; 1196 } 1197} 1198 1199/* Return a new token formed by pasting 'token' and 'other'. Note that this 1200 * function may return 'token' or 'other' directly rather than allocating 1201 * anything new. 1202 * 1203 * Caution: Only very cursory error-checking is performed to see if 1204 * the final result is a valid single token. */ 1205static token_t * 1206_token_paste(glcpp_parser_t *parser, token_t *token, token_t *other) 1207{ 1208 token_t *combined = NULL; 1209 1210 /* Pasting a placeholder onto anything makes no change. */ 1211 if (other->type == PLACEHOLDER) 1212 return token; 1213 1214 /* When 'token' is a placeholder, just return 'other'. */ 1215 if (token->type == PLACEHOLDER) 1216 return other; 1217 1218 /* A very few single-character punctuators can be combined 1219 * with another to form a multi-character punctuator. */ 1220 switch (token->type) { 1221 case '<': 1222 if (other->type == '<') 1223 combined = _token_create_ival (parser, LEFT_SHIFT, LEFT_SHIFT); 1224 else if (other->type == '=') 1225 combined = _token_create_ival (parser, LESS_OR_EQUAL, LESS_OR_EQUAL); 1226 break; 1227 case '>': 1228 if (other->type == '>') 1229 combined = _token_create_ival (parser, RIGHT_SHIFT, RIGHT_SHIFT); 1230 else if (other->type == '=') 1231 combined = _token_create_ival (parser, GREATER_OR_EQUAL, GREATER_OR_EQUAL); 1232 break; 1233 case '=': 1234 if (other->type == '=') 1235 combined = _token_create_ival (parser, EQUAL, EQUAL); 1236 break; 1237 case '!': 1238 if (other->type == '=') 1239 combined = _token_create_ival (parser, NOT_EQUAL, NOT_EQUAL); 1240 break; 1241 case '&': 1242 if (other->type == '&') 1243 combined = _token_create_ival (parser, AND, AND); 1244 break; 1245 case '|': 1246 if (other->type == '|') 1247 combined = _token_create_ival (parser, OR, OR); 1248 break; 1249 } 1250 1251 if (combined != NULL) { 1252 /* Inherit the location from the first token */ 1253 combined->location = token->location; 1254 return combined; 1255 } 1256 1257 /* Two string-valued (or integer) tokens can usually just be 1258 * mashed together. (We also handle a string followed by an 1259 * integer here as well.) 1260 * 1261 * There are some exceptions here. Notably, if the first token 1262 * is an integer (or a string representing an integer), then 1263 * the second token must also be an integer or must be a 1264 * string representing an integer that begins with a digit. 1265 */ 1266 if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING || token->type == INTEGER) && 1267 (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING || other->type == INTEGER)) 1268 { 1269 char *str; 1270 int combined_type; 1271 1272 /* Check that pasting onto an integer doesn't create a 1273 * non-integer, (that is, only digits can be 1274 * pasted. */ 1275 if (token->type == INTEGER_STRING || token->type == INTEGER) { 1276 switch (other->type) { 1277 case INTEGER_STRING: 1278 if (other->value.str[0] < '0' || other->value.str[0] > '9') 1279 goto FAIL; 1280 break; 1281 case INTEGER: 1282 if (other->value.ival < 0) 1283 goto FAIL; 1284 break; 1285 default: 1286 goto FAIL; 1287 } 1288 } 1289 1290 if (token->type == INTEGER) 1291 str = linear_asprintf(parser->linalloc, "%" PRIiMAX, token->value.ival); 1292 else 1293 str = linear_strdup(parser->linalloc, token->value.str); 1294 1295 if (other->type == INTEGER) 1296 linear_asprintf_append(parser->linalloc, &str, "%" PRIiMAX, other->value.ival); 1297 else 1298 linear_strcat(parser->linalloc, &str, other->value.str); 1299 1300 /* New token is same type as original token, unless we 1301 * started with an integer, in which case we will be 1302 * creating an integer-string. */ 1303 combined_type = token->type; 1304 if (combined_type == INTEGER) 1305 combined_type = INTEGER_STRING; 1306 1307 combined = _token_create_str (parser, combined_type, str); 1308 combined->location = token->location; 1309 return combined; 1310 } 1311 1312 FAIL: 1313 glcpp_error (&token->location, parser, ""); 1314 _mesa_string_buffer_append(parser->info_log, "Pasting \""); 1315 _token_print(parser->info_log, token); 1316 _mesa_string_buffer_append(parser->info_log, "\" and \""); 1317 _token_print(parser->info_log, other); 1318 _mesa_string_buffer_append(parser->info_log, "\" does not give a valid preprocessing token.\n"); 1319 1320 return token; 1321} 1322 1323static void 1324_token_list_print(glcpp_parser_t *parser, token_list_t *list) 1325{ 1326 token_node_t *node; 1327 1328 if (list == NULL) 1329 return; 1330 1331 for (node = list->head; node; node = node->next) 1332 _token_print(parser->output, node->token); 1333} 1334 1335void 1336yyerror(YYLTYPE *locp, glcpp_parser_t *parser, const char *error) 1337{ 1338 glcpp_error(locp, parser, "%s", error); 1339} 1340 1341static void 1342add_builtin_define(glcpp_parser_t *parser, const char *name, int value) 1343{ 1344 token_t *tok; 1345 token_list_t *list; 1346 1347 tok = _token_create_ival (parser, INTEGER, value); 1348 1349 list = _token_list_create(parser); 1350 _token_list_append(parser, list, tok); 1351 _define_object_macro(parser, NULL, name, list); 1352} 1353 1354/* Initial output buffer size, 4096 minus ralloc() overhead. It was selected 1355 * to minimize total amount of allocated memory during shader-db run. 1356 */ 1357#define INITIAL_PP_OUTPUT_BUF_SIZE 4048 1358 1359glcpp_parser_t * 1360glcpp_parser_create(const struct gl_extensions *extension_list, 1361 glcpp_extension_iterator extensions, void *state, gl_api api) 1362{ 1363 glcpp_parser_t *parser; 1364 1365 parser = ralloc (NULL, glcpp_parser_t); 1366 1367 glcpp_lex_init_extra (parser, &parser->scanner); 1368 parser->defines = _mesa_hash_table_create(NULL, _mesa_key_hash_string, 1369 _mesa_key_string_equal); 1370 parser->linalloc = linear_alloc_parent(parser, 0); 1371 parser->active = NULL; 1372 parser->lexing_directive = 0; 1373 parser->lexing_version_directive = 0; 1374 parser->space_tokens = 1; 1375 parser->last_token_was_newline = 0; 1376 parser->last_token_was_space = 0; 1377 parser->first_non_space_token_this_line = 1; 1378 parser->newline_as_space = 0; 1379 parser->in_control_line = 0; 1380 parser->paren_count = 0; 1381 parser->commented_newlines = 0; 1382 1383 parser->skip_stack = NULL; 1384 parser->skipping = 0; 1385 1386 parser->lex_from_list = NULL; 1387 parser->lex_from_node = NULL; 1388 1389 parser->output = _mesa_string_buffer_create(parser, 1390 INITIAL_PP_OUTPUT_BUF_SIZE); 1391 parser->info_log = _mesa_string_buffer_create(parser, 1392 INITIAL_PP_OUTPUT_BUF_SIZE); 1393 parser->error = 0; 1394 1395 parser->extensions = extensions; 1396 parser->extension_list = extension_list; 1397 parser->state = state; 1398 parser->api = api; 1399 parser->version = 0; 1400 parser->version_set = false; 1401 1402 parser->has_new_line_number = 0; 1403 parser->new_line_number = 1; 1404 parser->has_new_source_number = 0; 1405 parser->new_source_number = 0; 1406 1407 parser->is_gles = false; 1408 1409 return parser; 1410} 1411 1412void 1413glcpp_parser_destroy(glcpp_parser_t *parser) 1414{ 1415 glcpp_lex_destroy (parser->scanner); 1416 _mesa_hash_table_destroy(parser->defines, NULL); 1417 ralloc_free (parser); 1418} 1419 1420typedef enum function_status 1421{ 1422 FUNCTION_STATUS_SUCCESS, 1423 FUNCTION_NOT_A_FUNCTION, 1424 FUNCTION_UNBALANCED_PARENTHESES 1425} function_status_t; 1426 1427/* Find a set of function-like macro arguments by looking for a 1428 * balanced set of parentheses. 1429 * 1430 * When called, 'node' should be the opening-parenthesis token, (or 1431 * perhaps preceeding SPACE tokens). Upon successful return *last will 1432 * be the last consumed node, (corresponding to the closing right 1433 * parenthesis). 1434 * 1435 * Return values: 1436 * 1437 * FUNCTION_STATUS_SUCCESS: 1438 * 1439 * Successfully parsed a set of function arguments. 1440 * 1441 * FUNCTION_NOT_A_FUNCTION: 1442 * 1443 * Macro name not followed by a '('. This is not an error, but 1444 * simply that the macro name should be treated as a non-macro. 1445 * 1446 * FUNCTION_UNBALANCED_PARENTHESES 1447 * 1448 * Macro name is not followed by a balanced set of parentheses. 1449 */ 1450static function_status_t 1451_arguments_parse(glcpp_parser_t *parser, 1452 argument_list_t *arguments, token_node_t *node, 1453 token_node_t **last) 1454{ 1455 token_list_t *argument; 1456 int paren_count; 1457 1458 node = node->next; 1459 1460 /* Ignore whitespace before first parenthesis. */ 1461 while (node && node->token->type == SPACE) 1462 node = node->next; 1463 1464 if (node == NULL || node->token->type != '(') 1465 return FUNCTION_NOT_A_FUNCTION; 1466 1467 node = node->next; 1468 1469 argument = _token_list_create (parser); 1470 _argument_list_append (parser, arguments, argument); 1471 1472 for (paren_count = 1; node; node = node->next) { 1473 if (node->token->type == '(') { 1474 paren_count++; 1475 } else if (node->token->type == ')') { 1476 paren_count--; 1477 if (paren_count == 0) 1478 break; 1479 } 1480 1481 if (node->token->type == ',' && paren_count == 1) { 1482 _token_list_trim_trailing_space (argument); 1483 argument = _token_list_create (parser); 1484 _argument_list_append (parser, arguments, argument); 1485 } else { 1486 if (argument->head == NULL) { 1487 /* Don't treat initial whitespace as part of the argument. */ 1488 if (node->token->type == SPACE) 1489 continue; 1490 } 1491 _token_list_append(parser, argument, node->token); 1492 } 1493 } 1494 1495 if (paren_count) 1496 return FUNCTION_UNBALANCED_PARENTHESES; 1497 1498 *last = node; 1499 1500 return FUNCTION_STATUS_SUCCESS; 1501} 1502 1503static token_list_t * 1504_token_list_create_with_one_ival(glcpp_parser_t *parser, int type, int ival) 1505{ 1506 token_list_t *list; 1507 token_t *node; 1508 1509 list = _token_list_create(parser); 1510 node = _token_create_ival(parser, type, ival); 1511 _token_list_append(parser, list, node); 1512 1513 return list; 1514} 1515 1516static token_list_t * 1517_token_list_create_with_one_space(glcpp_parser_t *parser) 1518{ 1519 return _token_list_create_with_one_ival(parser, SPACE, SPACE); 1520} 1521 1522static token_list_t * 1523_token_list_create_with_one_integer(glcpp_parser_t *parser, int ival) 1524{ 1525 return _token_list_create_with_one_ival(parser, INTEGER, ival); 1526} 1527 1528/* Evaluate a DEFINED token node (based on subsequent tokens in the list). 1529 * 1530 * Note: This function must only be called when "node" is a DEFINED token, 1531 * (and will abort with an assertion failure otherwise). 1532 * 1533 * If "node" is followed, (ignoring any SPACE tokens), by an IDENTIFIER token 1534 * (optionally preceded and followed by '(' and ')' tokens) then the following 1535 * occurs: 1536 * 1537 * If the identifier is a defined macro, this function returns 1. 1538 * 1539 * If the identifier is not a defined macro, this function returns 0. 1540 * 1541 * In either case, *last will be updated to the last node in the list 1542 * consumed by the evaluation, (either the token of the identifier or the 1543 * token of the closing parenthesis). 1544 * 1545 * In all other cases, (such as "node is the final node of the list", or 1546 * "missing closing parenthesis", etc.), this function generates a 1547 * preprocessor error, returns -1 and *last will not be set. 1548 */ 1549static int 1550_glcpp_parser_evaluate_defined(glcpp_parser_t *parser, token_node_t *node, 1551 token_node_t **last) 1552{ 1553 token_node_t *argument, *defined = node; 1554 1555 assert(node->token->type == DEFINED); 1556 1557 node = node->next; 1558 1559 /* Ignore whitespace after DEFINED token. */ 1560 while (node && node->token->type == SPACE) 1561 node = node->next; 1562 1563 if (node == NULL) 1564 goto FAIL; 1565 1566 if (node->token->type == IDENTIFIER || node->token->type == OTHER) { 1567 argument = node; 1568 } else if (node->token->type == '(') { 1569 node = node->next; 1570 1571 /* Ignore whitespace after '(' token. */ 1572 while (node && node->token->type == SPACE) 1573 node = node->next; 1574 1575 if (node == NULL || (node->token->type != IDENTIFIER && 1576 node->token->type != OTHER)) { 1577 goto FAIL; 1578 } 1579 1580 argument = node; 1581 1582 node = node->next; 1583 1584 /* Ignore whitespace after identifier, before ')' token. */ 1585 while (node && node->token->type == SPACE) 1586 node = node->next; 1587 1588 if (node == NULL || node->token->type != ')') 1589 goto FAIL; 1590 } else { 1591 goto FAIL; 1592 } 1593 1594 *last = node; 1595 1596 return _mesa_hash_table_search(parser->defines, 1597 argument->token->value.str) ? 1 : 0; 1598 1599FAIL: 1600 glcpp_error (&defined->token->location, parser, 1601 "\"defined\" not followed by an identifier"); 1602 return -1; 1603} 1604 1605/* Evaluate all DEFINED nodes in a given list, modifying the list in place. 1606 */ 1607static void 1608_glcpp_parser_evaluate_defined_in_list(glcpp_parser_t *parser, 1609 token_list_t *list) 1610{ 1611 token_node_t *node, *node_prev, *replacement, *last = NULL; 1612 int value; 1613 1614 if (list == NULL) 1615 return; 1616 1617 node_prev = NULL; 1618 node = list->head; 1619 1620 while (node) { 1621 1622 if (node->token->type != DEFINED) 1623 goto NEXT; 1624 1625 value = _glcpp_parser_evaluate_defined (parser, node, &last); 1626 if (value == -1) 1627 goto NEXT; 1628 1629 replacement = linear_alloc_child(parser->linalloc, sizeof(token_node_t)); 1630 replacement->token = _token_create_ival (parser, INTEGER, value); 1631 1632 /* Splice replacement node into list, replacing from "node" 1633 * through "last". */ 1634 if (node_prev) 1635 node_prev->next = replacement; 1636 else 1637 list->head = replacement; 1638 replacement->next = last->next; 1639 if (last == list->tail) 1640 list->tail = replacement; 1641 1642 node = replacement; 1643 1644 NEXT: 1645 node_prev = node; 1646 node = node->next; 1647 } 1648} 1649 1650/* Perform macro expansion on 'list', placing the resulting tokens 1651 * into a new list which is initialized with a first token of type 1652 * 'head_token_type'. Then begin lexing from the resulting list, 1653 * (return to the current lexing source when this list is exhausted). 1654 * 1655 * See the documentation of _glcpp_parser_expand_token_list for a description 1656 * of the "mode" parameter. 1657 */ 1658static void 1659_glcpp_parser_expand_and_lex_from(glcpp_parser_t *parser, int head_token_type, 1660 token_list_t *list, expansion_mode_t mode) 1661{ 1662 token_list_t *expanded; 1663 token_t *token; 1664 1665 expanded = _token_list_create (parser); 1666 token = _token_create_ival (parser, head_token_type, head_token_type); 1667 _token_list_append (parser, expanded, token); 1668 _glcpp_parser_expand_token_list (parser, list, mode); 1669 _token_list_append_list (expanded, list); 1670 glcpp_parser_lex_from (parser, expanded); 1671} 1672 1673static void 1674_glcpp_parser_apply_pastes(glcpp_parser_t *parser, token_list_t *list) 1675{ 1676 token_node_t *node; 1677 1678 node = list->head; 1679 while (node) { 1680 token_node_t *next_non_space; 1681 1682 /* Look ahead for a PASTE token, skipping space. */ 1683 next_non_space = node->next; 1684 while (next_non_space && next_non_space->token->type == SPACE) 1685 next_non_space = next_non_space->next; 1686 1687 if (next_non_space == NULL) 1688 break; 1689 1690 if (next_non_space->token->type != PASTE) { 1691 node = next_non_space; 1692 continue; 1693 } 1694 1695 /* Now find the next non-space token after the PASTE. */ 1696 next_non_space = next_non_space->next; 1697 while (next_non_space && next_non_space->token->type == SPACE) 1698 next_non_space = next_non_space->next; 1699 1700 if (next_non_space == NULL) { 1701 yyerror(&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n"); 1702 return; 1703 } 1704 1705 node->token = _token_paste(parser, node->token, next_non_space->token); 1706 node->next = next_non_space->next; 1707 if (next_non_space == list->tail) 1708 list->tail = node; 1709 } 1710 1711 list->non_space_tail = list->tail; 1712} 1713 1714/* This is a helper function that's essentially part of the 1715 * implementation of _glcpp_parser_expand_node. It shouldn't be called 1716 * except for by that function. 1717 * 1718 * Returns NULL if node is a simple token with no expansion, (that is, 1719 * although 'node' corresponds to an identifier defined as a 1720 * function-like macro, it is not followed with a parenthesized 1721 * argument list). 1722 * 1723 * Compute the complete expansion of node (which is a function-like 1724 * macro) and subsequent nodes which are arguments. 1725 * 1726 * Returns the token list that results from the expansion and sets 1727 * *last to the last node in the list that was consumed by the 1728 * expansion. Specifically, *last will be set as follows: as the 1729 * token of the closing right parenthesis. 1730 * 1731 * See the documentation of _glcpp_parser_expand_token_list for a description 1732 * of the "mode" parameter. 1733 */ 1734static token_list_t * 1735_glcpp_parser_expand_function(glcpp_parser_t *parser, token_node_t *node, 1736 token_node_t **last, expansion_mode_t mode) 1737{ 1738 struct hash_entry *entry; 1739 macro_t *macro; 1740 const char *identifier; 1741 argument_list_t *arguments; 1742 function_status_t status; 1743 token_list_t *substituted; 1744 int parameter_index; 1745 1746 identifier = node->token->value.str; 1747 1748 entry = _mesa_hash_table_search(parser->defines, identifier); 1749 macro = entry ? entry->data : NULL; 1750 1751 assert(macro->is_function); 1752 1753 arguments = _argument_list_create(parser); 1754 status = _arguments_parse(parser, arguments, node, last); 1755 1756 switch (status) { 1757 case FUNCTION_STATUS_SUCCESS: 1758 break; 1759 case FUNCTION_NOT_A_FUNCTION: 1760 return NULL; 1761 case FUNCTION_UNBALANCED_PARENTHESES: 1762 glcpp_error(&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier); 1763 return NULL; 1764 } 1765 1766 /* Replace a macro defined as empty with a SPACE token. */ 1767 if (macro->replacements == NULL) { 1768 return _token_list_create_with_one_space(parser); 1769 } 1770 1771 if (!((_argument_list_length (arguments) == 1772 _string_list_length (macro->parameters)) || 1773 (_string_list_length (macro->parameters) == 0 && 1774 _argument_list_length (arguments) == 1 && 1775 arguments->head->argument->head == NULL))) { 1776 glcpp_error(&node->token->location, parser, 1777 "Error: macro %s invoked with %d arguments (expected %d)\n", 1778 identifier, _argument_list_length (arguments), 1779 _string_list_length(macro->parameters)); 1780 return NULL; 1781 } 1782 1783 /* Perform argument substitution on the replacement list. */ 1784 substituted = _token_list_create(parser); 1785 1786 for (node = macro->replacements->head; node; node = node->next) { 1787 if (node->token->type == IDENTIFIER && 1788 _string_list_contains(macro->parameters, node->token->value.str, 1789 ¶meter_index)) { 1790 token_list_t *argument; 1791 argument = _argument_list_member_at(arguments, parameter_index); 1792 /* Before substituting, we expand the argument tokens, or append a 1793 * placeholder token for an empty argument. */ 1794 if (argument->head) { 1795 token_list_t *expanded_argument; 1796 expanded_argument = _token_list_copy(parser, argument); 1797 _glcpp_parser_expand_token_list(parser, expanded_argument, mode); 1798 _token_list_append_list(substituted, expanded_argument); 1799 } else { 1800 token_t *new_token; 1801 1802 new_token = _token_create_ival(parser, PLACEHOLDER, 1803 PLACEHOLDER); 1804 _token_list_append(parser, substituted, new_token); 1805 } 1806 } else { 1807 _token_list_append(parser, substituted, node->token); 1808 } 1809 } 1810 1811 /* After argument substitution, and before further expansion 1812 * below, implement token pasting. */ 1813 1814 _token_list_trim_trailing_space(substituted); 1815 1816 _glcpp_parser_apply_pastes(parser, substituted); 1817 1818 return substituted; 1819} 1820 1821/* Compute the complete expansion of node, (and subsequent nodes after 1822 * 'node' in the case that 'node' is a function-like macro and 1823 * subsequent nodes are arguments). 1824 * 1825 * Returns NULL if node is a simple token with no expansion. 1826 * 1827 * Otherwise, returns the token list that results from the expansion 1828 * and sets *last to the last node in the list that was consumed by 1829 * the expansion. Specifically, *last will be set as follows: 1830 * 1831 * As 'node' in the case of object-like macro expansion. 1832 * 1833 * As the token of the closing right parenthesis in the case of 1834 * function-like macro expansion. 1835 * 1836 * See the documentation of _glcpp_parser_expand_token_list for a description 1837 * of the "mode" parameter. 1838 */ 1839static token_list_t * 1840_glcpp_parser_expand_node(glcpp_parser_t *parser, token_node_t *node, 1841 token_node_t **last, expansion_mode_t mode) 1842{ 1843 token_t *token = node->token; 1844 const char *identifier; 1845 struct hash_entry *entry; 1846 macro_t *macro; 1847 1848 /* We only expand identifiers */ 1849 if (token->type != IDENTIFIER) { 1850 return NULL; 1851 } 1852 1853 *last = node; 1854 identifier = token->value.str; 1855 1856 /* Special handling for __LINE__ and __FILE__, (not through 1857 * the hash table). */ 1858 if (*identifier == '_') { 1859 if (strcmp(identifier, "__LINE__") == 0) 1860 return _token_list_create_with_one_integer(parser, 1861 node->token->location.first_line); 1862 1863 if (strcmp(identifier, "__FILE__") == 0) 1864 return _token_list_create_with_one_integer(parser, 1865 node->token->location.source); 1866 } 1867 1868 /* Look up this identifier in the hash table. */ 1869 entry = _mesa_hash_table_search(parser->defines, identifier); 1870 macro = entry ? entry->data : NULL; 1871 1872 /* Not a macro, so no expansion needed. */ 1873 if (macro == NULL) 1874 return NULL; 1875 1876 /* Finally, don't expand this macro if we're already actively 1877 * expanding it, (to avoid infinite recursion). */ 1878 if (_parser_active_list_contains (parser, identifier)) { 1879 /* We change the token type here from IDENTIFIER to OTHER to prevent any 1880 * future expansion of this unexpanded token. */ 1881 char *str; 1882 token_list_t *expansion; 1883 token_t *final; 1884 1885 str = linear_strdup(parser->linalloc, token->value.str); 1886 final = _token_create_str(parser, OTHER, str); 1887 expansion = _token_list_create(parser); 1888 _token_list_append(parser, expansion, final); 1889 return expansion; 1890 } 1891 1892 if (! macro->is_function) { 1893 token_list_t *replacement; 1894 1895 /* Replace a macro defined as empty with a SPACE token. */ 1896 if (macro->replacements == NULL) 1897 return _token_list_create_with_one_space(parser); 1898 1899 replacement = _token_list_copy(parser, macro->replacements); 1900 _glcpp_parser_apply_pastes(parser, replacement); 1901 return replacement; 1902 } 1903 1904 return _glcpp_parser_expand_function(parser, node, last, mode); 1905} 1906 1907/* Push a new identifier onto the parser's active list. 1908 * 1909 * Here, 'marker' is the token node that appears in the list after the 1910 * expansion of 'identifier'. That is, when the list iterator begins 1911 * examining 'marker', then it is time to pop this node from the 1912 * active stack. 1913 */ 1914static void 1915_parser_active_list_push(glcpp_parser_t *parser, const char *identifier, 1916 token_node_t *marker) 1917{ 1918 active_list_t *node; 1919 1920 node = linear_alloc_child(parser->linalloc, sizeof(active_list_t)); 1921 node->identifier = linear_strdup(parser->linalloc, identifier); 1922 node->marker = marker; 1923 node->next = parser->active; 1924 1925 parser->active = node; 1926} 1927 1928static void 1929_parser_active_list_pop(glcpp_parser_t *parser) 1930{ 1931 active_list_t *node = parser->active; 1932 1933 if (node == NULL) { 1934 parser->active = NULL; 1935 return; 1936 } 1937 1938 node = parser->active->next; 1939 parser->active = node; 1940} 1941 1942static int 1943_parser_active_list_contains(glcpp_parser_t *parser, const char *identifier) 1944{ 1945 active_list_t *node; 1946 1947 if (parser->active == NULL) 1948 return 0; 1949 1950 for (node = parser->active; node; node = node->next) 1951 if (strcmp(node->identifier, identifier) == 0) 1952 return 1; 1953 1954 return 0; 1955} 1956 1957/* Walk over the token list replacing nodes with their expansion. 1958 * Whenever nodes are expanded the walking will walk over the new 1959 * nodes, continuing to expand as necessary. The results are placed in 1960 * 'list' itself. 1961 * 1962 * The "mode" argument controls the handling of any DEFINED tokens that 1963 * result from expansion as follows: 1964 * 1965 * EXPANSION_MODE_IGNORE_DEFINED: Any resulting DEFINED tokens will be 1966 * left in the final list, unevaluated. This is the correct mode 1967 * for expanding any list in any context other than a 1968 * preprocessor conditional, (#if or #elif). 1969 * 1970 * EXPANSION_MODE_EVALUATE_DEFINED: Any resulting DEFINED tokens will be 1971 * evaluated to 0 or 1 tokens depending on whether the following 1972 * token is the name of a defined macro. If the DEFINED token is 1973 * not followed by an (optionally parenthesized) identifier, then 1974 * an error will be generated. This the correct mode for 1975 * expanding any list in the context of a preprocessor 1976 * conditional, (#if or #elif). 1977 */ 1978static void 1979_glcpp_parser_expand_token_list(glcpp_parser_t *parser, token_list_t *list, 1980 expansion_mode_t mode) 1981{ 1982 token_node_t *node_prev; 1983 token_node_t *node, *last = NULL; 1984 token_list_t *expansion; 1985 active_list_t *active_initial = parser->active; 1986 1987 if (list == NULL) 1988 return; 1989 1990 _token_list_trim_trailing_space (list); 1991 1992 node_prev = NULL; 1993 node = list->head; 1994 1995 if (mode == EXPANSION_MODE_EVALUATE_DEFINED) 1996 _glcpp_parser_evaluate_defined_in_list (parser, list); 1997 1998 while (node) { 1999 2000 while (parser->active && parser->active->marker == node) 2001 _parser_active_list_pop (parser); 2002 2003 expansion = _glcpp_parser_expand_node (parser, node, &last, mode); 2004 if (expansion) { 2005 token_node_t *n; 2006 2007 if (mode == EXPANSION_MODE_EVALUATE_DEFINED) { 2008 _glcpp_parser_evaluate_defined_in_list (parser, expansion); 2009 } 2010 2011 for (n = node; n != last->next; n = n->next) 2012 while (parser->active && parser->active->marker == n) { 2013 _parser_active_list_pop (parser); 2014 } 2015 2016 _parser_active_list_push(parser, node->token->value.str, last->next); 2017 2018 /* Splice expansion into list, supporting a simple deletion if the 2019 * expansion is empty. 2020 */ 2021 if (expansion->head) { 2022 if (node_prev) 2023 node_prev->next = expansion->head; 2024 else 2025 list->head = expansion->head; 2026 expansion->tail->next = last->next; 2027 if (last == list->tail) 2028 list->tail = expansion->tail; 2029 } else { 2030 if (node_prev) 2031 node_prev->next = last->next; 2032 else 2033 list->head = last->next; 2034 if (last == list->tail) 2035 list->tail = NULL; 2036 } 2037 } else { 2038 node_prev = node; 2039 } 2040 node = node_prev ? node_prev->next : list->head; 2041 } 2042 2043 /* Remove any lingering effects of this invocation on the 2044 * active list. That is, pop until the list looks like it did 2045 * at the beginning of this function. */ 2046 while (parser->active && parser->active != active_initial) 2047 _parser_active_list_pop (parser); 2048 2049 list->non_space_tail = list->tail; 2050} 2051 2052void 2053_glcpp_parser_print_expanded_token_list(glcpp_parser_t *parser, 2054 token_list_t *list) 2055{ 2056 if (list == NULL) 2057 return; 2058 2059 _glcpp_parser_expand_token_list (parser, list, EXPANSION_MODE_IGNORE_DEFINED); 2060 2061 _token_list_trim_trailing_space (list); 2062 2063 _token_list_print (parser, list); 2064} 2065 2066static void 2067_check_for_reserved_macro_name(glcpp_parser_t *parser, YYLTYPE *loc, 2068 const char *identifier) 2069{ 2070 /* Section 3.3 (Preprocessor) of the GLSL 1.30 spec (and later) and 2071 * the GLSL ES spec (all versions) say: 2072 * 2073 * "All macro names containing two consecutive underscores ( __ ) 2074 * are reserved for future use as predefined macro names. All 2075 * macro names prefixed with "GL_" ("GL" followed by a single 2076 * underscore) are also reserved." 2077 * 2078 * The intention is that names containing __ are reserved for internal 2079 * use by the implementation, and names prefixed with GL_ are reserved 2080 * for use by Khronos. Since every extension adds a name prefixed 2081 * with GL_ (i.e., the name of the extension), that should be an 2082 * error. Names simply containing __ are dangerous to use, but should 2083 * be allowed. 2084 * 2085 * A future version of the GLSL specification will clarify this. 2086 */ 2087 if (strstr(identifier, "__")) { 2088 glcpp_warning(loc, parser, "Macro names containing \"__\" are reserved " 2089 "for use by the implementation.\n"); 2090 } 2091 if (strncmp(identifier, "GL_", 3) == 0) { 2092 glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n"); 2093 } 2094 if (strcmp(identifier, "defined") == 0) { 2095 glcpp_error (loc, parser, "\"defined\" cannot be used as a macro name"); 2096 } 2097} 2098 2099static int 2100_macro_equal(macro_t *a, macro_t *b) 2101{ 2102 if (a->is_function != b->is_function) 2103 return 0; 2104 2105 if (a->is_function) { 2106 if (! _string_list_equal (a->parameters, b->parameters)) 2107 return 0; 2108 } 2109 2110 return _token_list_equal_ignoring_space(a->replacements, b->replacements); 2111} 2112 2113void 2114_define_object_macro(glcpp_parser_t *parser, YYLTYPE *loc, 2115 const char *identifier, token_list_t *replacements) 2116{ 2117 macro_t *macro, *previous; 2118 struct hash_entry *entry; 2119 2120 /* We define pre-defined macros before we've started parsing the actual 2121 * file. So if there's no location defined yet, that's what were doing and 2122 * we don't want to generate an error for using the reserved names. */ 2123 if (loc != NULL) 2124 _check_for_reserved_macro_name(parser, loc, identifier); 2125 2126 macro = linear_alloc_child(parser->linalloc, sizeof(macro_t)); 2127 2128 macro->is_function = 0; 2129 macro->parameters = NULL; 2130 macro->identifier = linear_strdup(parser->linalloc, identifier); 2131 macro->replacements = replacements; 2132 2133 entry = _mesa_hash_table_search(parser->defines, identifier); 2134 previous = entry ? entry->data : NULL; 2135 if (previous) { 2136 if (_macro_equal (macro, previous)) { 2137 return; 2138 } 2139 glcpp_error (loc, parser, "Redefinition of macro %s\n", identifier); 2140 } 2141 2142 _mesa_hash_table_insert (parser->defines, identifier, macro); 2143} 2144 2145void 2146_define_function_macro(glcpp_parser_t *parser, YYLTYPE *loc, 2147 const char *identifier, string_list_t *parameters, 2148 token_list_t *replacements) 2149{ 2150 macro_t *macro, *previous; 2151 struct hash_entry *entry; 2152 const char *dup; 2153 2154 _check_for_reserved_macro_name(parser, loc, identifier); 2155 2156 /* Check for any duplicate parameter names. */ 2157 if ((dup = _string_list_has_duplicate (parameters)) != NULL) { 2158 glcpp_error (loc, parser, "Duplicate macro parameter \"%s\"", dup); 2159 } 2160 2161 macro = linear_alloc_child(parser->linalloc, sizeof(macro_t)); 2162 2163 macro->is_function = 1; 2164 macro->parameters = parameters; 2165 macro->identifier = linear_strdup(parser->linalloc, identifier); 2166 macro->replacements = replacements; 2167 2168 entry = _mesa_hash_table_search(parser->defines, identifier); 2169 previous = entry ? entry->data : NULL; 2170 if (previous) { 2171 if (_macro_equal (macro, previous)) { 2172 return; 2173 } 2174 glcpp_error (loc, parser, "Redefinition of macro %s\n", identifier); 2175 } 2176 2177 _mesa_hash_table_insert(parser->defines, identifier, macro); 2178} 2179 2180static int 2181glcpp_parser_lex(YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser) 2182{ 2183 token_node_t *node; 2184 int ret; 2185 2186 if (parser->lex_from_list == NULL) { 2187 ret = glcpp_lex(yylval, yylloc, parser->scanner); 2188 2189 /* XXX: This ugly block of code exists for the sole 2190 * purpose of converting a NEWLINE token into a SPACE 2191 * token, but only in the case where we have seen a 2192 * function-like macro name, but have not yet seen its 2193 * closing parenthesis. 2194 * 2195 * There's perhaps a more compact way to do this with 2196 * mid-rule actions in the grammar. 2197 * 2198 * I'm definitely not pleased with the complexity of 2199 * this code here. 2200 */ 2201 if (parser->newline_as_space) { 2202 if (ret == '(') { 2203 parser->paren_count++; 2204 } else if (ret == ')') { 2205 parser->paren_count--; 2206 if (parser->paren_count == 0) 2207 parser->newline_as_space = 0; 2208 } else if (ret == NEWLINE) { 2209 ret = SPACE; 2210 } else if (ret != SPACE) { 2211 if (parser->paren_count == 0) 2212 parser->newline_as_space = 0; 2213 } 2214 } else if (parser->in_control_line) { 2215 if (ret == NEWLINE) 2216 parser->in_control_line = 0; 2217 } 2218 else if (ret == DEFINE_TOKEN || ret == UNDEF || ret == IF || 2219 ret == IFDEF || ret == IFNDEF || ret == ELIF || ret == ELSE || 2220 ret == ENDIF || ret == HASH_TOKEN) { 2221 parser->in_control_line = 1; 2222 } else if (ret == IDENTIFIER) { 2223 struct hash_entry *entry = _mesa_hash_table_search(parser->defines, 2224 yylval->str); 2225 macro_t *macro = entry ? entry->data : NULL; 2226 if (macro && macro->is_function) { 2227 parser->newline_as_space = 1; 2228 parser->paren_count = 0; 2229 } 2230 } 2231 2232 return ret; 2233 } 2234 2235 node = parser->lex_from_node; 2236 2237 if (node == NULL) { 2238 parser->lex_from_list = NULL; 2239 return NEWLINE; 2240 } 2241 2242 *yylval = node->token->value; 2243 ret = node->token->type; 2244 2245 parser->lex_from_node = node->next; 2246 2247 return ret; 2248} 2249 2250static void 2251glcpp_parser_lex_from(glcpp_parser_t *parser, token_list_t *list) 2252{ 2253 token_node_t *node; 2254 2255 assert (parser->lex_from_list == NULL); 2256 2257 /* Copy list, eliminating any space tokens. */ 2258 parser->lex_from_list = _token_list_create (parser); 2259 2260 for (node = list->head; node; node = node->next) { 2261 if (node->token->type == SPACE) 2262 continue; 2263 _token_list_append (parser, parser->lex_from_list, node->token); 2264 } 2265 2266 parser->lex_from_node = parser->lex_from_list->head; 2267 2268 /* It's possible the list consisted of nothing but whitespace. */ 2269 if (parser->lex_from_node == NULL) { 2270 parser->lex_from_list = NULL; 2271 } 2272} 2273 2274static void 2275_glcpp_parser_skip_stack_push_if(glcpp_parser_t *parser, YYLTYPE *loc, 2276 int condition) 2277{ 2278 skip_type_t current = SKIP_NO_SKIP; 2279 skip_node_t *node; 2280 2281 if (parser->skip_stack) 2282 current = parser->skip_stack->type; 2283 2284 node = linear_alloc_child(parser->linalloc, sizeof(skip_node_t)); 2285 node->loc = *loc; 2286 2287 if (current == SKIP_NO_SKIP) { 2288 if (condition) 2289 node->type = SKIP_NO_SKIP; 2290 else 2291 node->type = SKIP_TO_ELSE; 2292 } else { 2293 node->type = SKIP_TO_ENDIF; 2294 } 2295 2296 node->has_else = false; 2297 node->next = parser->skip_stack; 2298 parser->skip_stack = node; 2299} 2300 2301static void 2302_glcpp_parser_skip_stack_change_if(glcpp_parser_t *parser, YYLTYPE *loc, 2303 const char *type, int condition) 2304{ 2305 if (parser->skip_stack == NULL) { 2306 glcpp_error (loc, parser, "#%s without #if\n", type); 2307 return; 2308 } 2309 2310 if (parser->skip_stack->type == SKIP_TO_ELSE) { 2311 if (condition) 2312 parser->skip_stack->type = SKIP_NO_SKIP; 2313 } else { 2314 parser->skip_stack->type = SKIP_TO_ENDIF; 2315 } 2316} 2317 2318static void 2319_glcpp_parser_skip_stack_pop(glcpp_parser_t *parser, YYLTYPE *loc) 2320{ 2321 skip_node_t *node; 2322 2323 if (parser->skip_stack == NULL) { 2324 glcpp_error (loc, parser, "#endif without #if\n"); 2325 return; 2326 } 2327 2328 node = parser->skip_stack; 2329 parser->skip_stack = node->next; 2330} 2331 2332static void 2333_glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version, 2334 const char *identifier, 2335 bool explicitly_set) 2336{ 2337 if (parser->version_set) 2338 return; 2339 2340 parser->version = version; 2341 parser->version_set = true; 2342 2343 add_builtin_define (parser, "__VERSION__", version); 2344 2345 parser->is_gles = (version == 100) || 2346 (identifier && (strcmp(identifier, "es") == 0)); 2347 bool is_compat = version >= 150 && identifier && 2348 strcmp(identifier, "compatibility") == 0; 2349 2350 /* Add pre-defined macros. */ 2351 if (parser->is_gles) 2352 add_builtin_define(parser, "GL_ES", 1); 2353 else if (is_compat) 2354 add_builtin_define(parser, "GL_compatibility_profile", 1); 2355 else if (version >= 150) 2356 add_builtin_define(parser, "GL_core_profile", 1); 2357 2358 /* Currently, all ES2/ES3 implementations support highp in the 2359 * fragment shader, so we always define this macro in ES2/ES3. 2360 * If we ever get a driver that doesn't support highp, we'll 2361 * need to add a flag to the gl_context and check that here. 2362 */ 2363 if (version >= 130 || parser->is_gles) 2364 add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1); 2365 2366 /* Add all the extension macros available in this context */ 2367 if (parser->extensions) 2368 parser->extensions(parser->state, add_builtin_define, parser, 2369 version, parser->is_gles); 2370 2371 if (parser->extension_list) { 2372 /* If MESA_shader_integer_functions is supported, then the building 2373 * blocks required for the 64x64 => 64 multiply exist. Add defines for 2374 * those functions so that they can be tested. 2375 */ 2376 if (parser->extension_list->MESA_shader_integer_functions) { 2377 add_builtin_define(parser, "__have_builtin_builtin_sign64", 1); 2378 add_builtin_define(parser, "__have_builtin_builtin_umul64", 1); 2379 add_builtin_define(parser, "__have_builtin_builtin_udiv64", 1); 2380 add_builtin_define(parser, "__have_builtin_builtin_umod64", 1); 2381 add_builtin_define(parser, "__have_builtin_builtin_idiv64", 1); 2382 add_builtin_define(parser, "__have_builtin_builtin_imod64", 1); 2383 } 2384 } 2385 2386 if (explicitly_set) { 2387 _mesa_string_buffer_printf(parser->output, 2388 "#version %" PRIiMAX "%s%s", version, 2389 identifier ? " " : "", 2390 identifier ? identifier : ""); 2391 } 2392} 2393 2394/* GLSL version if no version is explicitly specified. */ 2395#define IMPLICIT_GLSL_VERSION 110 2396 2397/* GLSL ES version if no version is explicitly specified. */ 2398#define IMPLICIT_GLSL_ES_VERSION 100 2399 2400void 2401glcpp_parser_resolve_implicit_version(glcpp_parser_t *parser) 2402{ 2403 int language_version = parser->api == API_OPENGLES2 ? 2404 IMPLICIT_GLSL_ES_VERSION : IMPLICIT_GLSL_VERSION; 2405 2406 _glcpp_parser_handle_version_declaration(parser, language_version, 2407 NULL, false); 2408} 2409