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