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