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