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/core.h" /* for struct gl_extensions */ 33#include "main/mtypes.h" /* for gl_api enum */ 34 35static void 36yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error); 37 38static void 39_define_object_macro (glcpp_parser_t *parser, 40 YYLTYPE *loc, 41 const char *macro, 42 token_list_t *replacements); 43 44static void 45_define_function_macro (glcpp_parser_t *parser, 46 YYLTYPE *loc, 47 const char *macro, 48 string_list_t *parameters, 49 token_list_t *replacements); 50 51static string_list_t * 52_string_list_create (void *ctx); 53 54static void 55_string_list_append_item (string_list_t *list, const char *str); 56 57static int 58_string_list_contains (string_list_t *list, const char *member, int *index); 59 60static int 61_string_list_length (string_list_t *list); 62 63static int 64_string_list_equal (string_list_t *a, string_list_t *b); 65 66static argument_list_t * 67_argument_list_create (void *ctx); 68 69static void 70_argument_list_append (argument_list_t *list, token_list_t *argument); 71 72static int 73_argument_list_length (argument_list_t *list); 74 75static token_list_t * 76_argument_list_member_at (argument_list_t *list, int index); 77 78/* Note: This function ralloc_steal()s the str pointer. */ 79static token_t * 80_token_create_str (void *ctx, int type, char *str); 81 82static token_t * 83_token_create_ival (void *ctx, int type, int ival); 84 85static token_list_t * 86_token_list_create (void *ctx); 87 88static void 89_token_list_append (token_list_t *list, token_t *token); 90 91static void 92_token_list_append_list (token_list_t *list, token_list_t *tail); 93 94static int 95_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b); 96 97static void 98_parser_active_list_push (glcpp_parser_t *parser, 99 const char *identifier, 100 token_node_t *marker); 101 102static void 103_parser_active_list_pop (glcpp_parser_t *parser); 104 105static int 106_parser_active_list_contains (glcpp_parser_t *parser, const char *identifier); 107 108/* Expand list, and begin lexing from the result (after first 109 * prefixing a token of type 'head_token_type'). 110 */ 111static void 112_glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser, 113 int head_token_type, 114 token_list_t *list); 115 116/* Perform macro expansion in-place on the given list. */ 117static void 118_glcpp_parser_expand_token_list (glcpp_parser_t *parser, 119 token_list_t *list); 120 121static void 122_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser, 123 token_list_t *list); 124 125static void 126_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc, 127 int condition); 128 129static void 130_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc, 131 const char *type, int condition); 132 133static void 134_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc); 135 136static int 137glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser); 138 139static void 140glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list); 141 142static void 143add_builtin_define(glcpp_parser_t *parser, const char *name, int value); 144 145%} 146 147%pure-parser 148%error-verbose 149 150%locations 151%initial-action { 152 @$.first_line = 1; 153 @$.first_column = 1; 154 @$.last_line = 1; 155 @$.last_column = 1; 156 @$.source = 0; 157} 158 159%parse-param {glcpp_parser_t *parser} 160%lex-param {glcpp_parser_t *parser} 161 162%expect 0 163%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE FUNC_IDENTIFIER OBJ_IDENTIFIER HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_LINE HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE 164%token PASTE 165%type <ival> expression INTEGER operator SPACE integer_constant 166%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER 167%type <string_list> identifier_list 168%type <token> preprocessing_token conditional_token 169%type <token_list> pp_tokens replacement_list text_line conditional_tokens 170%left OR 171%left AND 172%left '|' 173%left '^' 174%left '&' 175%left EQUAL NOT_EQUAL 176%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL 177%left LEFT_SHIFT RIGHT_SHIFT 178%left '+' '-' 179%left '*' '/' '%' 180%right UNARY 181 182%% 183 184input: 185 /* empty */ 186| input line 187; 188 189line: 190 control_line { 191 ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n"); 192 } 193| text_line { 194 _glcpp_parser_print_expanded_token_list (parser, $1); 195 ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n"); 196 ralloc_free ($1); 197 } 198| expanded_line 199| HASH non_directive 200; 201 202expanded_line: 203 IF_EXPANDED expression NEWLINE { 204 _glcpp_parser_skip_stack_push_if (parser, & @1, $2); 205 } 206| ELIF_EXPANDED expression NEWLINE { 207 _glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2); 208 } 209| LINE_EXPANDED integer_constant NEWLINE { 210 parser->has_new_line_number = 1; 211 parser->new_line_number = $2; 212 ralloc_asprintf_rewrite_tail (&parser->output, 213 &parser->output_length, 214 "#line %" PRIiMAX "\n", 215 $2); 216 } 217| LINE_EXPANDED integer_constant integer_constant NEWLINE { 218 parser->has_new_line_number = 1; 219 parser->new_line_number = $2; 220 parser->has_new_source_number = 1; 221 parser->new_source_number = $3; 222 ralloc_asprintf_rewrite_tail (&parser->output, 223 &parser->output_length, 224 "#line %" PRIiMAX " %" PRIiMAX "\n", 225 $2, $3); 226 } 227; 228 229control_line: 230 HASH_DEFINE OBJ_IDENTIFIER replacement_list NEWLINE { 231 _define_object_macro (parser, & @2, $2, $3); 232 } 233| HASH_DEFINE FUNC_IDENTIFIER '(' ')' replacement_list NEWLINE { 234 _define_function_macro (parser, & @2, $2, NULL, $5); 235 } 236| HASH_DEFINE FUNC_IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE { 237 _define_function_macro (parser, & @2, $2, $4, $6); 238 } 239| HASH_UNDEF IDENTIFIER NEWLINE { 240 macro_t *macro = hash_table_find (parser->defines, $2); 241 if (macro) { 242 hash_table_remove (parser->defines, $2); 243 ralloc_free (macro); 244 } 245 ralloc_free ($2); 246 } 247| HASH_LINE pp_tokens NEWLINE { 248 if (parser->skip_stack == NULL || 249 parser->skip_stack->type == SKIP_NO_SKIP) 250 { 251 _glcpp_parser_expand_and_lex_from (parser, 252 LINE_EXPANDED, $2); 253 } 254 } 255| HASH_IF conditional_tokens NEWLINE { 256 /* Be careful to only evaluate the 'if' expression if 257 * we are not skipping. When we are skipping, we 258 * simply push a new 0-valued 'if' onto the skip 259 * stack. 260 * 261 * This avoids generating diagnostics for invalid 262 * expressions that are being skipped. */ 263 if (parser->skip_stack == NULL || 264 parser->skip_stack->type == SKIP_NO_SKIP) 265 { 266 _glcpp_parser_expand_and_lex_from (parser, 267 IF_EXPANDED, $2); 268 } 269 else 270 { 271 _glcpp_parser_skip_stack_push_if (parser, & @1, 0); 272 parser->skip_stack->type = SKIP_TO_ENDIF; 273 } 274 } 275| HASH_IF NEWLINE { 276 /* #if without an expression is only an error if we 277 * are not skipping */ 278 if (parser->skip_stack == NULL || 279 parser->skip_stack->type == SKIP_NO_SKIP) 280 { 281 glcpp_error(& @1, parser, "#if with no expression"); 282 } 283 _glcpp_parser_skip_stack_push_if (parser, & @1, 0); 284 } 285| HASH_IFDEF IDENTIFIER junk NEWLINE { 286 macro_t *macro = hash_table_find (parser->defines, $2); 287 ralloc_free ($2); 288 _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL); 289 } 290| HASH_IFNDEF IDENTIFIER junk NEWLINE { 291 macro_t *macro = hash_table_find (parser->defines, $2); 292 ralloc_free ($2); 293 _glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL); 294 } 295| HASH_ELIF conditional_tokens NEWLINE { 296 /* Be careful to only evaluate the 'elif' expression 297 * if we are not skipping. When we are skipping, we 298 * simply change to a 0-valued 'elif' on the skip 299 * stack. 300 * 301 * This avoids generating diagnostics for invalid 302 * expressions that are being skipped. */ 303 if (parser->skip_stack && 304 parser->skip_stack->type == SKIP_TO_ELSE) 305 { 306 _glcpp_parser_expand_and_lex_from (parser, 307 ELIF_EXPANDED, $2); 308 } 309 else 310 { 311 _glcpp_parser_skip_stack_change_if (parser, & @1, 312 "elif", 0); 313 } 314 } 315| HASH_ELIF NEWLINE { 316 /* #elif without an expression is an error unless we 317 * are skipping. */ 318 if (parser->skip_stack && 319 parser->skip_stack->type == SKIP_TO_ELSE) 320 { 321 glcpp_error(& @1, parser, "#elif with no expression"); 322 } 323 else 324 { 325 _glcpp_parser_skip_stack_change_if (parser, & @1, 326 "elif", 0); 327 glcpp_warning(& @1, parser, "ignoring illegal #elif without expression"); 328 } 329 } 330| HASH_ELSE { 331 _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1); 332 } NEWLINE 333| HASH_ENDIF { 334 _glcpp_parser_skip_stack_pop (parser, & @1); 335 } NEWLINE 336| HASH_VERSION integer_constant NEWLINE { 337 macro_t *macro = hash_table_find (parser->defines, "__VERSION__"); 338 if (macro) { 339 hash_table_remove (parser->defines, "__VERSION__"); 340 ralloc_free (macro); 341 } 342 add_builtin_define (parser, "__VERSION__", $2); 343 344 if ($2 == 100) 345 add_builtin_define (parser, "GL_ES", 1); 346 347 /* Currently, all ES2 implementations support highp in the 348 * fragment shader, so we always define this macro in ES2. 349 * If we ever get a driver that doesn't support highp, we'll 350 * need to add a flag to the gl_context and check that here. 351 */ 352 if ($2 >= 130 || $2 == 100) 353 add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1); 354 355 ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "#version %" PRIiMAX, $2); 356 } 357| HASH NEWLINE 358; 359 360integer_constant: 361 INTEGER_STRING { 362 if (strlen ($1) >= 3 && strncmp ($1, "0x", 2) == 0) { 363 $$ = strtoll ($1 + 2, NULL, 16); 364 } else if ($1[0] == '0') { 365 $$ = strtoll ($1, NULL, 8); 366 } else { 367 $$ = strtoll ($1, NULL, 10); 368 } 369 } 370| INTEGER { 371 $$ = $1; 372 } 373 374expression: 375 integer_constant 376| IDENTIFIER { 377 $$ = 0; 378 } 379| expression OR expression { 380 $$ = $1 || $3; 381 } 382| expression AND expression { 383 $$ = $1 && $3; 384 } 385| expression '|' expression { 386 $$ = $1 | $3; 387 } 388| expression '^' expression { 389 $$ = $1 ^ $3; 390 } 391| expression '&' expression { 392 $$ = $1 & $3; 393 } 394| expression NOT_EQUAL expression { 395 $$ = $1 != $3; 396 } 397| expression EQUAL expression { 398 $$ = $1 == $3; 399 } 400| expression GREATER_OR_EQUAL expression { 401 $$ = $1 >= $3; 402 } 403| expression LESS_OR_EQUAL expression { 404 $$ = $1 <= $3; 405 } 406| expression '>' expression { 407 $$ = $1 > $3; 408 } 409| expression '<' expression { 410 $$ = $1 < $3; 411 } 412| expression RIGHT_SHIFT expression { 413 $$ = $1 >> $3; 414 } 415| expression LEFT_SHIFT expression { 416 $$ = $1 << $3; 417 } 418| expression '-' expression { 419 $$ = $1 - $3; 420 } 421| expression '+' expression { 422 $$ = $1 + $3; 423 } 424| expression '%' expression { 425 if ($3 == 0) { 426 yyerror (& @1, parser, 427 "zero modulus in preprocessor directive"); 428 } else { 429 $$ = $1 % $3; 430 } 431 } 432| expression '/' expression { 433 if ($3 == 0) { 434 yyerror (& @1, parser, 435 "division by 0 in preprocessor directive"); 436 } else { 437 $$ = $1 / $3; 438 } 439 } 440| expression '*' expression { 441 $$ = $1 * $3; 442 } 443| '!' expression %prec UNARY { 444 $$ = ! $2; 445 } 446| '~' expression %prec UNARY { 447 $$ = ~ $2; 448 } 449| '-' expression %prec UNARY { 450 $$ = - $2; 451 } 452| '+' expression %prec UNARY { 453 $$ = + $2; 454 } 455| '(' expression ')' { 456 $$ = $2; 457 } 458; 459 460identifier_list: 461 IDENTIFIER { 462 $$ = _string_list_create (parser); 463 _string_list_append_item ($$, $1); 464 ralloc_steal ($$, $1); 465 } 466| identifier_list ',' IDENTIFIER { 467 $$ = $1; 468 _string_list_append_item ($$, $3); 469 ralloc_steal ($$, $3); 470 } 471; 472 473text_line: 474 NEWLINE { $$ = NULL; } 475| pp_tokens NEWLINE 476; 477 478non_directive: 479 pp_tokens NEWLINE { 480 yyerror (& @1, parser, "Invalid tokens after #"); 481 } 482; 483 484replacement_list: 485 /* empty */ { $$ = NULL; } 486| pp_tokens 487; 488 489junk: 490 /* empty */ 491| pp_tokens { 492 glcpp_warning(&@1, parser, "extra tokens at end of directive"); 493 } 494; 495 496conditional_token: 497 /* Handle "defined" operator */ 498 DEFINED IDENTIFIER { 499 int v = hash_table_find (parser->defines, $2) ? 1 : 0; 500 $$ = _token_create_ival (parser, INTEGER, v); 501 } 502| DEFINED '(' IDENTIFIER ')' { 503 int v = hash_table_find (parser->defines, $3) ? 1 : 0; 504 $$ = _token_create_ival (parser, INTEGER, v); 505 } 506| preprocessing_token 507; 508 509conditional_tokens: 510 /* Exactly the same as pp_tokens, but using conditional_token */ 511 conditional_token { 512 $$ = _token_list_create (parser); 513 _token_list_append ($$, $1); 514 } 515| conditional_tokens conditional_token { 516 $$ = $1; 517 _token_list_append ($$, $2); 518 } 519; 520 521pp_tokens: 522 preprocessing_token { 523 parser->space_tokens = 1; 524 $$ = _token_list_create (parser); 525 _token_list_append ($$, $1); 526 } 527| pp_tokens preprocessing_token { 528 $$ = $1; 529 _token_list_append ($$, $2); 530 } 531; 532 533preprocessing_token: 534 IDENTIFIER { 535 $$ = _token_create_str (parser, IDENTIFIER, $1); 536 $$->location = yylloc; 537 } 538| INTEGER_STRING { 539 $$ = _token_create_str (parser, INTEGER_STRING, $1); 540 $$->location = yylloc; 541 } 542| operator { 543 $$ = _token_create_ival (parser, $1, $1); 544 $$->location = yylloc; 545 } 546| OTHER { 547 $$ = _token_create_str (parser, OTHER, $1); 548 $$->location = yylloc; 549 } 550| SPACE { 551 $$ = _token_create_ival (parser, SPACE, SPACE); 552 $$->location = yylloc; 553 } 554; 555 556operator: 557 '[' { $$ = '['; } 558| ']' { $$ = ']'; } 559| '(' { $$ = '('; } 560| ')' { $$ = ')'; } 561| '{' { $$ = '{'; } 562| '}' { $$ = '}'; } 563| '.' { $$ = '.'; } 564| '&' { $$ = '&'; } 565| '*' { $$ = '*'; } 566| '+' { $$ = '+'; } 567| '-' { $$ = '-'; } 568| '~' { $$ = '~'; } 569| '!' { $$ = '!'; } 570| '/' { $$ = '/'; } 571| '%' { $$ = '%'; } 572| LEFT_SHIFT { $$ = LEFT_SHIFT; } 573| RIGHT_SHIFT { $$ = RIGHT_SHIFT; } 574| '<' { $$ = '<'; } 575| '>' { $$ = '>'; } 576| LESS_OR_EQUAL { $$ = LESS_OR_EQUAL; } 577| GREATER_OR_EQUAL { $$ = GREATER_OR_EQUAL; } 578| EQUAL { $$ = EQUAL; } 579| NOT_EQUAL { $$ = NOT_EQUAL; } 580| '^' { $$ = '^'; } 581| '|' { $$ = '|'; } 582| AND { $$ = AND; } 583| OR { $$ = OR; } 584| ';' { $$ = ';'; } 585| ',' { $$ = ','; } 586| '=' { $$ = '='; } 587| PASTE { $$ = PASTE; } 588; 589 590%% 591 592string_list_t * 593_string_list_create (void *ctx) 594{ 595 string_list_t *list; 596 597 list = ralloc (ctx, string_list_t); 598 list->head = NULL; 599 list->tail = NULL; 600 601 return list; 602} 603 604void 605_string_list_append_item (string_list_t *list, const char *str) 606{ 607 string_node_t *node; 608 609 node = ralloc (list, string_node_t); 610 node->str = ralloc_strdup (node, str); 611 612 node->next = NULL; 613 614 if (list->head == NULL) { 615 list->head = node; 616 } else { 617 list->tail->next = node; 618 } 619 620 list->tail = node; 621} 622 623int 624_string_list_contains (string_list_t *list, const char *member, int *index) 625{ 626 string_node_t *node; 627 int i; 628 629 if (list == NULL) 630 return 0; 631 632 for (i = 0, node = list->head; node; i++, node = node->next) { 633 if (strcmp (node->str, member) == 0) { 634 if (index) 635 *index = i; 636 return 1; 637 } 638 } 639 640 return 0; 641} 642 643int 644_string_list_length (string_list_t *list) 645{ 646 int length = 0; 647 string_node_t *node; 648 649 if (list == NULL) 650 return 0; 651 652 for (node = list->head; node; node = node->next) 653 length++; 654 655 return length; 656} 657 658int 659_string_list_equal (string_list_t *a, string_list_t *b) 660{ 661 string_node_t *node_a, *node_b; 662 663 if (a == NULL && b == NULL) 664 return 1; 665 666 if (a == NULL || b == NULL) 667 return 0; 668 669 for (node_a = a->head, node_b = b->head; 670 node_a && node_b; 671 node_a = node_a->next, node_b = node_b->next) 672 { 673 if (strcmp (node_a->str, node_b->str)) 674 return 0; 675 } 676 677 /* Catch the case of lists being different lengths, (which 678 * would cause the loop above to terminate after the shorter 679 * list). */ 680 return node_a == node_b; 681} 682 683argument_list_t * 684_argument_list_create (void *ctx) 685{ 686 argument_list_t *list; 687 688 list = ralloc (ctx, argument_list_t); 689 list->head = NULL; 690 list->tail = NULL; 691 692 return list; 693} 694 695void 696_argument_list_append (argument_list_t *list, token_list_t *argument) 697{ 698 argument_node_t *node; 699 700 node = ralloc (list, argument_node_t); 701 node->argument = argument; 702 703 node->next = NULL; 704 705 if (list->head == NULL) { 706 list->head = node; 707 } else { 708 list->tail->next = node; 709 } 710 711 list->tail = node; 712} 713 714int 715_argument_list_length (argument_list_t *list) 716{ 717 int length = 0; 718 argument_node_t *node; 719 720 if (list == NULL) 721 return 0; 722 723 for (node = list->head; node; node = node->next) 724 length++; 725 726 return length; 727} 728 729token_list_t * 730_argument_list_member_at (argument_list_t *list, int index) 731{ 732 argument_node_t *node; 733 int i; 734 735 if (list == NULL) 736 return NULL; 737 738 node = list->head; 739 for (i = 0; i < index; i++) { 740 node = node->next; 741 if (node == NULL) 742 break; 743 } 744 745 if (node) 746 return node->argument; 747 748 return NULL; 749} 750 751/* Note: This function ralloc_steal()s the str pointer. */ 752token_t * 753_token_create_str (void *ctx, int type, char *str) 754{ 755 token_t *token; 756 757 token = ralloc (ctx, token_t); 758 token->type = type; 759 token->value.str = str; 760 761 ralloc_steal (token, str); 762 763 return token; 764} 765 766token_t * 767_token_create_ival (void *ctx, int type, int ival) 768{ 769 token_t *token; 770 771 token = ralloc (ctx, token_t); 772 token->type = type; 773 token->value.ival = ival; 774 775 return token; 776} 777 778token_list_t * 779_token_list_create (void *ctx) 780{ 781 token_list_t *list; 782 783 list = ralloc (ctx, token_list_t); 784 list->head = NULL; 785 list->tail = NULL; 786 list->non_space_tail = NULL; 787 788 return list; 789} 790 791void 792_token_list_append (token_list_t *list, token_t *token) 793{ 794 token_node_t *node; 795 796 node = ralloc (list, token_node_t); 797 node->token = token; 798 node->next = NULL; 799 800 if (list->head == NULL) { 801 list->head = node; 802 } else { 803 list->tail->next = node; 804 } 805 806 list->tail = node; 807 if (token->type != SPACE) 808 list->non_space_tail = node; 809} 810 811void 812_token_list_append_list (token_list_t *list, token_list_t *tail) 813{ 814 if (tail == NULL || tail->head == NULL) 815 return; 816 817 if (list->head == NULL) { 818 list->head = tail->head; 819 } else { 820 list->tail->next = tail->head; 821 } 822 823 list->tail = tail->tail; 824 list->non_space_tail = tail->non_space_tail; 825} 826 827static token_list_t * 828_token_list_copy (void *ctx, token_list_t *other) 829{ 830 token_list_t *copy; 831 token_node_t *node; 832 833 if (other == NULL) 834 return NULL; 835 836 copy = _token_list_create (ctx); 837 for (node = other->head; node; node = node->next) { 838 token_t *new_token = ralloc (copy, token_t); 839 *new_token = *node->token; 840 _token_list_append (copy, new_token); 841 } 842 843 return copy; 844} 845 846static void 847_token_list_trim_trailing_space (token_list_t *list) 848{ 849 token_node_t *tail, *next; 850 851 if (list->non_space_tail) { 852 tail = list->non_space_tail->next; 853 list->non_space_tail->next = NULL; 854 list->tail = list->non_space_tail; 855 856 while (tail) { 857 next = tail->next; 858 ralloc_free (tail); 859 tail = next; 860 } 861 } 862} 863 864static int 865_token_list_is_empty_ignoring_space (token_list_t *l) 866{ 867 token_node_t *n; 868 869 if (l == NULL) 870 return 1; 871 872 n = l->head; 873 while (n != NULL && n->token->type == SPACE) 874 n = n->next; 875 876 return n == NULL; 877} 878 879int 880_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b) 881{ 882 token_node_t *node_a, *node_b; 883 884 if (a == NULL || b == NULL) { 885 int a_empty = _token_list_is_empty_ignoring_space(a); 886 int b_empty = _token_list_is_empty_ignoring_space(b); 887 return a_empty == b_empty; 888 } 889 890 node_a = a->head; 891 node_b = b->head; 892 893 while (1) 894 { 895 if (node_a == NULL && node_b == NULL) 896 break; 897 898 if (node_a == NULL || node_b == NULL) 899 return 0; 900 901 if (node_a->token->type == SPACE) { 902 node_a = node_a->next; 903 continue; 904 } 905 906 if (node_b->token->type == SPACE) { 907 node_b = node_b->next; 908 continue; 909 } 910 911 if (node_a->token->type != node_b->token->type) 912 return 0; 913 914 switch (node_a->token->type) { 915 case INTEGER: 916 if (node_a->token->value.ival != 917 node_b->token->value.ival) 918 { 919 return 0; 920 } 921 break; 922 case IDENTIFIER: 923 case INTEGER_STRING: 924 case OTHER: 925 if (strcmp (node_a->token->value.str, 926 node_b->token->value.str)) 927 { 928 return 0; 929 } 930 break; 931 } 932 933 node_a = node_a->next; 934 node_b = node_b->next; 935 } 936 937 return 1; 938} 939 940static void 941_token_print (char **out, size_t *len, token_t *token) 942{ 943 if (token->type < 256) { 944 ralloc_asprintf_rewrite_tail (out, len, "%c", token->type); 945 return; 946 } 947 948 switch (token->type) { 949 case INTEGER: 950 ralloc_asprintf_rewrite_tail (out, len, "%" PRIiMAX, token->value.ival); 951 break; 952 case IDENTIFIER: 953 case INTEGER_STRING: 954 case OTHER: 955 ralloc_asprintf_rewrite_tail (out, len, "%s", token->value.str); 956 break; 957 case SPACE: 958 ralloc_asprintf_rewrite_tail (out, len, " "); 959 break; 960 case LEFT_SHIFT: 961 ralloc_asprintf_rewrite_tail (out, len, "<<"); 962 break; 963 case RIGHT_SHIFT: 964 ralloc_asprintf_rewrite_tail (out, len, ">>"); 965 break; 966 case LESS_OR_EQUAL: 967 ralloc_asprintf_rewrite_tail (out, len, "<="); 968 break; 969 case GREATER_OR_EQUAL: 970 ralloc_asprintf_rewrite_tail (out, len, ">="); 971 break; 972 case EQUAL: 973 ralloc_asprintf_rewrite_tail (out, len, "=="); 974 break; 975 case NOT_EQUAL: 976 ralloc_asprintf_rewrite_tail (out, len, "!="); 977 break; 978 case AND: 979 ralloc_asprintf_rewrite_tail (out, len, "&&"); 980 break; 981 case OR: 982 ralloc_asprintf_rewrite_tail (out, len, "||"); 983 break; 984 case PASTE: 985 ralloc_asprintf_rewrite_tail (out, len, "##"); 986 break; 987 case COMMA_FINAL: 988 ralloc_asprintf_rewrite_tail (out, len, ","); 989 break; 990 case PLACEHOLDER: 991 /* Nothing to print. */ 992 break; 993 default: 994 assert(!"Error: Don't know how to print token."); 995 break; 996 } 997} 998 999/* Return a new token (ralloc()ed off of 'token') formed by pasting 1000 * 'token' and 'other'. Note that this function may return 'token' or 1001 * 'other' directly rather than allocating anything new. 1002 * 1003 * Caution: Only very cursory error-checking is performed to see if 1004 * the final result is a valid single token. */ 1005static token_t * 1006_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other) 1007{ 1008 token_t *combined = NULL; 1009 1010 /* Pasting a placeholder onto anything makes no change. */ 1011 if (other->type == PLACEHOLDER) 1012 return token; 1013 1014 /* When 'token' is a placeholder, just return 'other'. */ 1015 if (token->type == PLACEHOLDER) 1016 return other; 1017 1018 /* A very few single-character punctuators can be combined 1019 * with another to form a multi-character punctuator. */ 1020 switch (token->type) { 1021 case '<': 1022 if (other->type == '<') 1023 combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT); 1024 else if (other->type == '=') 1025 combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL); 1026 break; 1027 case '>': 1028 if (other->type == '>') 1029 combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT); 1030 else if (other->type == '=') 1031 combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL); 1032 break; 1033 case '=': 1034 if (other->type == '=') 1035 combined = _token_create_ival (token, EQUAL, EQUAL); 1036 break; 1037 case '!': 1038 if (other->type == '=') 1039 combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL); 1040 break; 1041 case '&': 1042 if (other->type == '&') 1043 combined = _token_create_ival (token, AND, AND); 1044 break; 1045 case '|': 1046 if (other->type == '|') 1047 combined = _token_create_ival (token, OR, OR); 1048 break; 1049 } 1050 1051 if (combined != NULL) { 1052 /* Inherit the location from the first token */ 1053 combined->location = token->location; 1054 return combined; 1055 } 1056 1057 /* Two string-valued tokens can usually just be mashed 1058 * together. 1059 * 1060 * XXX: This isn't actually legitimate. Several things here 1061 * should result in a diagnostic since the result cannot be a 1062 * valid, single pre-processing token. For example, pasting 1063 * "123" and "abc" is not legal, but we don't catch that 1064 * here. */ 1065 if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) && 1066 (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING)) 1067 { 1068 char *str; 1069 1070 str = ralloc_asprintf (token, "%s%s", token->value.str, 1071 other->value.str); 1072 combined = _token_create_str (token, token->type, str); 1073 combined->location = token->location; 1074 return combined; 1075 } 1076 1077 glcpp_error (&token->location, parser, ""); 1078 ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "Pasting \""); 1079 _token_print (&parser->info_log, &parser->info_log_length, token); 1080 ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "\" and \""); 1081 _token_print (&parser->info_log, &parser->info_log_length, other); 1082 ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "\" does not give a valid preprocessing token.\n"); 1083 1084 return token; 1085} 1086 1087static void 1088_token_list_print (glcpp_parser_t *parser, token_list_t *list) 1089{ 1090 token_node_t *node; 1091 1092 if (list == NULL) 1093 return; 1094 1095 for (node = list->head; node; node = node->next) 1096 _token_print (&parser->output, &parser->output_length, node->token); 1097} 1098 1099void 1100yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error) 1101{ 1102 glcpp_error(locp, parser, "%s", error); 1103} 1104 1105static void add_builtin_define(glcpp_parser_t *parser, 1106 const char *name, int value) 1107{ 1108 token_t *tok; 1109 token_list_t *list; 1110 1111 tok = _token_create_ival (parser, INTEGER, value); 1112 1113 list = _token_list_create(parser); 1114 _token_list_append(list, tok); 1115 _define_object_macro(parser, NULL, name, list); 1116} 1117 1118glcpp_parser_t * 1119glcpp_parser_create (const struct gl_extensions *extensions, int api) 1120{ 1121 glcpp_parser_t *parser; 1122 int language_version; 1123 1124 parser = ralloc (NULL, glcpp_parser_t); 1125 1126 glcpp_lex_init_extra (parser, &parser->scanner); 1127 parser->defines = hash_table_ctor (32, hash_table_string_hash, 1128 hash_table_string_compare); 1129 parser->active = NULL; 1130 parser->lexing_if = 0; 1131 parser->space_tokens = 1; 1132 parser->newline_as_space = 0; 1133 parser->in_control_line = 0; 1134 parser->paren_count = 0; 1135 1136 parser->skip_stack = NULL; 1137 1138 parser->lex_from_list = NULL; 1139 parser->lex_from_node = NULL; 1140 1141 parser->output = ralloc_strdup(parser, ""); 1142 parser->output_length = 0; 1143 parser->info_log = ralloc_strdup(parser, ""); 1144 parser->info_log_length = 0; 1145 parser->error = 0; 1146 1147 parser->has_new_line_number = 0; 1148 parser->new_line_number = 1; 1149 parser->has_new_source_number = 0; 1150 parser->new_source_number = 0; 1151 1152 /* Add pre-defined macros. */ 1153 add_builtin_define(parser, "GL_ARB_draw_buffers", 1); 1154 add_builtin_define(parser, "GL_ARB_texture_rectangle", 1); 1155 1156 if (api == API_OPENGLES2) 1157 add_builtin_define(parser, "GL_ES", 1); 1158 1159 if (extensions != NULL) { 1160 if (extensions->EXT_texture_array) { 1161 add_builtin_define(parser, "GL_EXT_texture_array", 1); 1162 } 1163 1164 if (extensions->ARB_fragment_coord_conventions) 1165 add_builtin_define(parser, "GL_ARB_fragment_coord_conventions", 1166 1); 1167 1168 if (extensions->ARB_explicit_attrib_location) 1169 add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1); 1170 1171 if (extensions->ARB_shader_texture_lod) 1172 add_builtin_define(parser, "GL_ARB_shader_texture_lod", 1); 1173 1174 if (extensions->ARB_draw_instanced) 1175 add_builtin_define(parser, "GL_ARB_draw_instanced", 1); 1176 1177 if (extensions->ARB_conservative_depth) { 1178 add_builtin_define(parser, "GL_AMD_conservative_depth", 1); 1179 add_builtin_define(parser, "GL_ARB_conservative_depth", 1); 1180 } 1181 1182 if (extensions->OES_EGL_image_external) 1183 add_builtin_define(parser, "GL_OES_EGL_image_external", 1); 1184 1185 if (extensions->ARB_shader_bit_encoding) 1186 add_builtin_define(parser, "GL_ARB_shader_bit_encoding", 1); 1187 1188 if (extensions->ARB_uniform_buffer_object) 1189 add_builtin_define(parser, "GL_ARB_uniform_buffer_object", 1); 1190 } 1191 1192 language_version = 110; 1193 add_builtin_define(parser, "__VERSION__", language_version); 1194 1195 return parser; 1196} 1197 1198void 1199glcpp_parser_destroy (glcpp_parser_t *parser) 1200{ 1201 glcpp_lex_destroy (parser->scanner); 1202 hash_table_dtor (parser->defines); 1203 ralloc_free (parser); 1204} 1205 1206typedef enum function_status 1207{ 1208 FUNCTION_STATUS_SUCCESS, 1209 FUNCTION_NOT_A_FUNCTION, 1210 FUNCTION_UNBALANCED_PARENTHESES 1211} function_status_t; 1212 1213/* Find a set of function-like macro arguments by looking for a 1214 * balanced set of parentheses. 1215 * 1216 * When called, 'node' should be the opening-parenthesis token, (or 1217 * perhaps preceeding SPACE tokens). Upon successful return *last will 1218 * be the last consumed node, (corresponding to the closing right 1219 * parenthesis). 1220 * 1221 * Return values: 1222 * 1223 * FUNCTION_STATUS_SUCCESS: 1224 * 1225 * Successfully parsed a set of function arguments. 1226 * 1227 * FUNCTION_NOT_A_FUNCTION: 1228 * 1229 * Macro name not followed by a '('. This is not an error, but 1230 * simply that the macro name should be treated as a non-macro. 1231 * 1232 * FUNCTION_UNBALANCED_PARENTHESES 1233 * 1234 * Macro name is not followed by a balanced set of parentheses. 1235 */ 1236static function_status_t 1237_arguments_parse (argument_list_t *arguments, 1238 token_node_t *node, 1239 token_node_t **last) 1240{ 1241 token_list_t *argument; 1242 int paren_count; 1243 1244 node = node->next; 1245 1246 /* Ignore whitespace before first parenthesis. */ 1247 while (node && node->token->type == SPACE) 1248 node = node->next; 1249 1250 if (node == NULL || node->token->type != '(') 1251 return FUNCTION_NOT_A_FUNCTION; 1252 1253 node = node->next; 1254 1255 argument = _token_list_create (arguments); 1256 _argument_list_append (arguments, argument); 1257 1258 for (paren_count = 1; node; node = node->next) { 1259 if (node->token->type == '(') 1260 { 1261 paren_count++; 1262 } 1263 else if (node->token->type == ')') 1264 { 1265 paren_count--; 1266 if (paren_count == 0) 1267 break; 1268 } 1269 1270 if (node->token->type == ',' && 1271 paren_count == 1) 1272 { 1273 _token_list_trim_trailing_space (argument); 1274 argument = _token_list_create (arguments); 1275 _argument_list_append (arguments, argument); 1276 } 1277 else { 1278 if (argument->head == NULL) { 1279 /* Don't treat initial whitespace as 1280 * part of the arguement. */ 1281 if (node->token->type == SPACE) 1282 continue; 1283 } 1284 _token_list_append (argument, node->token); 1285 } 1286 } 1287 1288 if (paren_count) 1289 return FUNCTION_UNBALANCED_PARENTHESES; 1290 1291 *last = node; 1292 1293 return FUNCTION_STATUS_SUCCESS; 1294} 1295 1296static token_list_t * 1297_token_list_create_with_one_space (void *ctx) 1298{ 1299 token_list_t *list; 1300 token_t *space; 1301 1302 list = _token_list_create (ctx); 1303 space = _token_create_ival (list, SPACE, SPACE); 1304 _token_list_append (list, space); 1305 1306 return list; 1307} 1308 1309/* Perform macro expansion on 'list', placing the resulting tokens 1310 * into a new list which is initialized with a first token of type 1311 * 'head_token_type'. Then begin lexing from the resulting list, 1312 * (return to the current lexing source when this list is exhausted). 1313 */ 1314static void 1315_glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser, 1316 int head_token_type, 1317 token_list_t *list) 1318{ 1319 token_list_t *expanded; 1320 token_t *token; 1321 1322 expanded = _token_list_create (parser); 1323 token = _token_create_ival (parser, head_token_type, head_token_type); 1324 _token_list_append (expanded, token); 1325 _glcpp_parser_expand_token_list (parser, list); 1326 _token_list_append_list (expanded, list); 1327 glcpp_parser_lex_from (parser, expanded); 1328} 1329 1330static void 1331_glcpp_parser_apply_pastes (glcpp_parser_t *parser, token_list_t *list) 1332{ 1333 token_node_t *node; 1334 1335 node = list->head; 1336 while (node) 1337 { 1338 token_node_t *next_non_space; 1339 1340 /* Look ahead for a PASTE token, skipping space. */ 1341 next_non_space = node->next; 1342 while (next_non_space && next_non_space->token->type == SPACE) 1343 next_non_space = next_non_space->next; 1344 1345 if (next_non_space == NULL) 1346 break; 1347 1348 if (next_non_space->token->type != PASTE) { 1349 node = next_non_space; 1350 continue; 1351 } 1352 1353 /* Now find the next non-space token after the PASTE. */ 1354 next_non_space = next_non_space->next; 1355 while (next_non_space && next_non_space->token->type == SPACE) 1356 next_non_space = next_non_space->next; 1357 1358 if (next_non_space == NULL) { 1359 yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n"); 1360 return; 1361 } 1362 1363 node->token = _token_paste (parser, node->token, next_non_space->token); 1364 node->next = next_non_space->next; 1365 if (next_non_space == list->tail) 1366 list->tail = node; 1367 } 1368 1369 list->non_space_tail = list->tail; 1370} 1371 1372/* This is a helper function that's essentially part of the 1373 * implementation of _glcpp_parser_expand_node. It shouldn't be called 1374 * except for by that function. 1375 * 1376 * Returns NULL if node is a simple token with no expansion, (that is, 1377 * although 'node' corresponds to an identifier defined as a 1378 * function-like macro, it is not followed with a parenthesized 1379 * argument list). 1380 * 1381 * Compute the complete expansion of node (which is a function-like 1382 * macro) and subsequent nodes which are arguments. 1383 * 1384 * Returns the token list that results from the expansion and sets 1385 * *last to the last node in the list that was consumed by the 1386 * expansion. Specifically, *last will be set as follows: as the 1387 * token of the closing right parenthesis. 1388 */ 1389static token_list_t * 1390_glcpp_parser_expand_function (glcpp_parser_t *parser, 1391 token_node_t *node, 1392 token_node_t **last) 1393 1394{ 1395 macro_t *macro; 1396 const char *identifier; 1397 argument_list_t *arguments; 1398 function_status_t status; 1399 token_list_t *substituted; 1400 int parameter_index; 1401 1402 identifier = node->token->value.str; 1403 1404 macro = hash_table_find (parser->defines, identifier); 1405 1406 assert (macro->is_function); 1407 1408 arguments = _argument_list_create (parser); 1409 status = _arguments_parse (arguments, node, last); 1410 1411 switch (status) { 1412 case FUNCTION_STATUS_SUCCESS: 1413 break; 1414 case FUNCTION_NOT_A_FUNCTION: 1415 return NULL; 1416 case FUNCTION_UNBALANCED_PARENTHESES: 1417 glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier); 1418 return NULL; 1419 } 1420 1421 /* Replace a macro defined as empty with a SPACE token. */ 1422 if (macro->replacements == NULL) { 1423 ralloc_free (arguments); 1424 return _token_list_create_with_one_space (parser); 1425 } 1426 1427 if (! ((_argument_list_length (arguments) == 1428 _string_list_length (macro->parameters)) || 1429 (_string_list_length (macro->parameters) == 0 && 1430 _argument_list_length (arguments) == 1 && 1431 arguments->head->argument->head == NULL))) 1432 { 1433 glcpp_error (&node->token->location, parser, 1434 "Error: macro %s invoked with %d arguments (expected %d)\n", 1435 identifier, 1436 _argument_list_length (arguments), 1437 _string_list_length (macro->parameters)); 1438 return NULL; 1439 } 1440 1441 /* Perform argument substitution on the replacement list. */ 1442 substituted = _token_list_create (arguments); 1443 1444 for (node = macro->replacements->head; node; node = node->next) 1445 { 1446 if (node->token->type == IDENTIFIER && 1447 _string_list_contains (macro->parameters, 1448 node->token->value.str, 1449 ¶meter_index)) 1450 { 1451 token_list_t *argument; 1452 argument = _argument_list_member_at (arguments, 1453 parameter_index); 1454 /* Before substituting, we expand the argument 1455 * tokens, or append a placeholder token for 1456 * an empty argument. */ 1457 if (argument->head) { 1458 token_list_t *expanded_argument; 1459 expanded_argument = _token_list_copy (parser, 1460 argument); 1461 _glcpp_parser_expand_token_list (parser, 1462 expanded_argument); 1463 _token_list_append_list (substituted, 1464 expanded_argument); 1465 } else { 1466 token_t *new_token; 1467 1468 new_token = _token_create_ival (substituted, 1469 PLACEHOLDER, 1470 PLACEHOLDER); 1471 _token_list_append (substituted, new_token); 1472 } 1473 } else { 1474 _token_list_append (substituted, node->token); 1475 } 1476 } 1477 1478 /* After argument substitution, and before further expansion 1479 * below, implement token pasting. */ 1480 1481 _token_list_trim_trailing_space (substituted); 1482 1483 _glcpp_parser_apply_pastes (parser, substituted); 1484 1485 return substituted; 1486} 1487 1488/* Compute the complete expansion of node, (and subsequent nodes after 1489 * 'node' in the case that 'node' is a function-like macro and 1490 * subsequent nodes are arguments). 1491 * 1492 * Returns NULL if node is a simple token with no expansion. 1493 * 1494 * Otherwise, returns the token list that results from the expansion 1495 * and sets *last to the last node in the list that was consumed by 1496 * the expansion. Specifically, *last will be set as follows: 1497 * 1498 * As 'node' in the case of object-like macro expansion. 1499 * 1500 * As the token of the closing right parenthesis in the case of 1501 * function-like macro expansion. 1502 */ 1503static token_list_t * 1504_glcpp_parser_expand_node (glcpp_parser_t *parser, 1505 token_node_t *node, 1506 token_node_t **last) 1507{ 1508 token_t *token = node->token; 1509 const char *identifier; 1510 macro_t *macro; 1511 1512 /* We only expand identifiers */ 1513 if (token->type != IDENTIFIER) { 1514 /* We change any COMMA into a COMMA_FINAL to prevent 1515 * it being mistaken for an argument separator 1516 * later. */ 1517 if (token->type == ',') { 1518 token->type = COMMA_FINAL; 1519 token->value.ival = COMMA_FINAL; 1520 } 1521 1522 return NULL; 1523 } 1524 1525 /* Look up this identifier in the hash table. */ 1526 identifier = token->value.str; 1527 macro = hash_table_find (parser->defines, identifier); 1528 1529 /* Not a macro, so no expansion needed. */ 1530 if (macro == NULL) 1531 return NULL; 1532 1533 /* Finally, don't expand this macro if we're already actively 1534 * expanding it, (to avoid infinite recursion). */ 1535 if (_parser_active_list_contains (parser, identifier)) { 1536 /* We change the token type here from IDENTIFIER to 1537 * OTHER to prevent any future expansion of this 1538 * unexpanded token. */ 1539 char *str; 1540 token_list_t *expansion; 1541 token_t *final; 1542 1543 str = ralloc_strdup (parser, token->value.str); 1544 final = _token_create_str (parser, OTHER, str); 1545 expansion = _token_list_create (parser); 1546 _token_list_append (expansion, final); 1547 *last = node; 1548 return expansion; 1549 } 1550 1551 if (! macro->is_function) 1552 { 1553 token_list_t *replacement; 1554 *last = node; 1555 1556 /* Replace a macro defined as empty with a SPACE token. */ 1557 if (macro->replacements == NULL) 1558 return _token_list_create_with_one_space (parser); 1559 1560 replacement = _token_list_copy (parser, macro->replacements); 1561 _glcpp_parser_apply_pastes (parser, replacement); 1562 return replacement; 1563 } 1564 1565 return _glcpp_parser_expand_function (parser, node, last); 1566} 1567 1568/* Push a new identifier onto the parser's active list. 1569 * 1570 * Here, 'marker' is the token node that appears in the list after the 1571 * expansion of 'identifier'. That is, when the list iterator begins 1572 * examining 'marker', then it is time to pop this node from the 1573 * active stack. 1574 */ 1575static void 1576_parser_active_list_push (glcpp_parser_t *parser, 1577 const char *identifier, 1578 token_node_t *marker) 1579{ 1580 active_list_t *node; 1581 1582 node = ralloc (parser->active, active_list_t); 1583 node->identifier = ralloc_strdup (node, identifier); 1584 node->marker = marker; 1585 node->next = parser->active; 1586 1587 parser->active = node; 1588} 1589 1590static void 1591_parser_active_list_pop (glcpp_parser_t *parser) 1592{ 1593 active_list_t *node = parser->active; 1594 1595 if (node == NULL) { 1596 parser->active = NULL; 1597 return; 1598 } 1599 1600 node = parser->active->next; 1601 ralloc_free (parser->active); 1602 1603 parser->active = node; 1604} 1605 1606static int 1607_parser_active_list_contains (glcpp_parser_t *parser, const char *identifier) 1608{ 1609 active_list_t *node; 1610 1611 if (parser->active == NULL) 1612 return 0; 1613 1614 for (node = parser->active; node; node = node->next) 1615 if (strcmp (node->identifier, identifier) == 0) 1616 return 1; 1617 1618 return 0; 1619} 1620 1621/* Walk over the token list replacing nodes with their expansion. 1622 * Whenever nodes are expanded the walking will walk over the new 1623 * nodes, continuing to expand as necessary. The results are placed in 1624 * 'list' itself; 1625 */ 1626static void 1627_glcpp_parser_expand_token_list (glcpp_parser_t *parser, 1628 token_list_t *list) 1629{ 1630 token_node_t *node_prev; 1631 token_node_t *node, *last = NULL; 1632 token_list_t *expansion; 1633 active_list_t *active_initial = parser->active; 1634 1635 if (list == NULL) 1636 return; 1637 1638 _token_list_trim_trailing_space (list); 1639 1640 node_prev = NULL; 1641 node = list->head; 1642 1643 while (node) { 1644 1645 while (parser->active && parser->active->marker == node) 1646 _parser_active_list_pop (parser); 1647 1648 expansion = _glcpp_parser_expand_node (parser, node, &last); 1649 if (expansion) { 1650 token_node_t *n; 1651 1652 for (n = node; n != last->next; n = n->next) 1653 while (parser->active && 1654 parser->active->marker == n) 1655 { 1656 _parser_active_list_pop (parser); 1657 } 1658 1659 _parser_active_list_push (parser, 1660 node->token->value.str, 1661 last->next); 1662 1663 /* Splice expansion into list, supporting a 1664 * simple deletion if the expansion is 1665 * empty. */ 1666 if (expansion->head) { 1667 if (node_prev) 1668 node_prev->next = expansion->head; 1669 else 1670 list->head = expansion->head; 1671 expansion->tail->next = last->next; 1672 if (last == list->tail) 1673 list->tail = expansion->tail; 1674 } else { 1675 if (node_prev) 1676 node_prev->next = last->next; 1677 else 1678 list->head = last->next; 1679 if (last == list->tail) 1680 list->tail = NULL; 1681 } 1682 } else { 1683 node_prev = node; 1684 } 1685 node = node_prev ? node_prev->next : list->head; 1686 } 1687 1688 /* Remove any lingering effects of this invocation on the 1689 * active list. That is, pop until the list looks like it did 1690 * at the beginning of this function. */ 1691 while (parser->active && parser->active != active_initial) 1692 _parser_active_list_pop (parser); 1693 1694 list->non_space_tail = list->tail; 1695} 1696 1697void 1698_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser, 1699 token_list_t *list) 1700{ 1701 if (list == NULL) 1702 return; 1703 1704 _glcpp_parser_expand_token_list (parser, list); 1705 1706 _token_list_trim_trailing_space (list); 1707 1708 _token_list_print (parser, list); 1709} 1710 1711static void 1712_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc, 1713 const char *identifier) 1714{ 1715 /* According to the GLSL specification, macro names starting with "__" 1716 * or "GL_" are reserved for future use. So, don't allow them. 1717 */ 1718 if (strstr(identifier, "__")) { 1719 glcpp_error (loc, parser, "Macro names containing \"__\" are reserved.\n"); 1720 } 1721 if (strncmp(identifier, "GL_", 3) == 0) { 1722 glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n"); 1723 } 1724} 1725 1726static int 1727_macro_equal (macro_t *a, macro_t *b) 1728{ 1729 if (a->is_function != b->is_function) 1730 return 0; 1731 1732 if (a->is_function) { 1733 if (! _string_list_equal (a->parameters, b->parameters)) 1734 return 0; 1735 } 1736 1737 return _token_list_equal_ignoring_space (a->replacements, 1738 b->replacements); 1739} 1740 1741void 1742_define_object_macro (glcpp_parser_t *parser, 1743 YYLTYPE *loc, 1744 const char *identifier, 1745 token_list_t *replacements) 1746{ 1747 macro_t *macro, *previous; 1748 1749 if (loc != NULL) 1750 _check_for_reserved_macro_name(parser, loc, identifier); 1751 1752 macro = ralloc (parser, macro_t); 1753 1754 macro->is_function = 0; 1755 macro->parameters = NULL; 1756 macro->identifier = ralloc_strdup (macro, identifier); 1757 macro->replacements = replacements; 1758 ralloc_steal (macro, replacements); 1759 1760 previous = hash_table_find (parser->defines, identifier); 1761 if (previous) { 1762 if (_macro_equal (macro, previous)) { 1763 ralloc_free (macro); 1764 return; 1765 } 1766 glcpp_error (loc, parser, "Redefinition of macro %s\n", 1767 identifier); 1768 } 1769 1770 hash_table_insert (parser->defines, macro, identifier); 1771} 1772 1773void 1774_define_function_macro (glcpp_parser_t *parser, 1775 YYLTYPE *loc, 1776 const char *identifier, 1777 string_list_t *parameters, 1778 token_list_t *replacements) 1779{ 1780 macro_t *macro, *previous; 1781 1782 _check_for_reserved_macro_name(parser, loc, identifier); 1783 1784 macro = ralloc (parser, macro_t); 1785 ralloc_steal (macro, parameters); 1786 ralloc_steal (macro, replacements); 1787 1788 macro->is_function = 1; 1789 macro->parameters = parameters; 1790 macro->identifier = ralloc_strdup (macro, identifier); 1791 macro->replacements = replacements; 1792 previous = hash_table_find (parser->defines, identifier); 1793 if (previous) { 1794 if (_macro_equal (macro, previous)) { 1795 ralloc_free (macro); 1796 return; 1797 } 1798 glcpp_error (loc, parser, "Redefinition of macro %s\n", 1799 identifier); 1800 } 1801 1802 hash_table_insert (parser->defines, macro, identifier); 1803} 1804 1805static int 1806glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser) 1807{ 1808 token_node_t *node; 1809 int ret; 1810 1811 if (parser->lex_from_list == NULL) { 1812 ret = glcpp_lex (yylval, yylloc, parser->scanner); 1813 1814 /* XXX: This ugly block of code exists for the sole 1815 * purpose of converting a NEWLINE token into a SPACE 1816 * token, but only in the case where we have seen a 1817 * function-like macro name, but have not yet seen its 1818 * closing parenthesis. 1819 * 1820 * There's perhaps a more compact way to do this with 1821 * mid-rule actions in the grammar. 1822 * 1823 * I'm definitely not pleased with the complexity of 1824 * this code here. 1825 */ 1826 if (parser->newline_as_space) 1827 { 1828 if (ret == '(') { 1829 parser->paren_count++; 1830 } else if (ret == ')') { 1831 parser->paren_count--; 1832 if (parser->paren_count == 0) 1833 parser->newline_as_space = 0; 1834 } else if (ret == NEWLINE) { 1835 ret = SPACE; 1836 } else if (ret != SPACE) { 1837 if (parser->paren_count == 0) 1838 parser->newline_as_space = 0; 1839 } 1840 } 1841 else if (parser->in_control_line) 1842 { 1843 if (ret == NEWLINE) 1844 parser->in_control_line = 0; 1845 } 1846 else if (ret == HASH_DEFINE || 1847 ret == HASH_UNDEF || ret == HASH_IF || 1848 ret == HASH_IFDEF || ret == HASH_IFNDEF || 1849 ret == HASH_ELIF || ret == HASH_ELSE || 1850 ret == HASH_ENDIF || ret == HASH) 1851 { 1852 parser->in_control_line = 1; 1853 } 1854 else if (ret == IDENTIFIER) 1855 { 1856 macro_t *macro; 1857 macro = hash_table_find (parser->defines, 1858 yylval->str); 1859 if (macro && macro->is_function) { 1860 parser->newline_as_space = 1; 1861 parser->paren_count = 0; 1862 } 1863 } 1864 1865 return ret; 1866 } 1867 1868 node = parser->lex_from_node; 1869 1870 if (node == NULL) { 1871 ralloc_free (parser->lex_from_list); 1872 parser->lex_from_list = NULL; 1873 return NEWLINE; 1874 } 1875 1876 *yylval = node->token->value; 1877 ret = node->token->type; 1878 1879 parser->lex_from_node = node->next; 1880 1881 return ret; 1882} 1883 1884static void 1885glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list) 1886{ 1887 token_node_t *node; 1888 1889 assert (parser->lex_from_list == NULL); 1890 1891 /* Copy list, eliminating any space tokens. */ 1892 parser->lex_from_list = _token_list_create (parser); 1893 1894 for (node = list->head; node; node = node->next) { 1895 if (node->token->type == SPACE) 1896 continue; 1897 _token_list_append (parser->lex_from_list, node->token); 1898 } 1899 1900 ralloc_free (list); 1901 1902 parser->lex_from_node = parser->lex_from_list->head; 1903 1904 /* It's possible the list consisted of nothing but whitespace. */ 1905 if (parser->lex_from_node == NULL) { 1906 ralloc_free (parser->lex_from_list); 1907 parser->lex_from_list = NULL; 1908 } 1909} 1910 1911static void 1912_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc, 1913 int condition) 1914{ 1915 skip_type_t current = SKIP_NO_SKIP; 1916 skip_node_t *node; 1917 1918 if (parser->skip_stack) 1919 current = parser->skip_stack->type; 1920 1921 node = ralloc (parser, skip_node_t); 1922 node->loc = *loc; 1923 1924 if (current == SKIP_NO_SKIP) { 1925 if (condition) 1926 node->type = SKIP_NO_SKIP; 1927 else 1928 node->type = SKIP_TO_ELSE; 1929 } else { 1930 node->type = SKIP_TO_ENDIF; 1931 } 1932 1933 node->next = parser->skip_stack; 1934 parser->skip_stack = node; 1935} 1936 1937static void 1938_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc, 1939 const char *type, int condition) 1940{ 1941 if (parser->skip_stack == NULL) { 1942 glcpp_error (loc, parser, "%s without #if\n", type); 1943 return; 1944 } 1945 1946 if (parser->skip_stack->type == SKIP_TO_ELSE) { 1947 if (condition) 1948 parser->skip_stack->type = SKIP_NO_SKIP; 1949 } else { 1950 parser->skip_stack->type = SKIP_TO_ENDIF; 1951 } 1952} 1953 1954static void 1955_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc) 1956{ 1957 skip_node_t *node; 1958 1959 if (parser->skip_stack == NULL) { 1960 glcpp_error (loc, parser, "#endif without #if\n"); 1961 return; 1962 } 1963 1964 node = parser->skip_stack; 1965 parser->skip_stack = node->next; 1966 ralloc_free (node); 1967} 1968