1 /*===- ScriptParser.yy ----------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===*/ 9 10 %{ 11 /* C/C++ Declarations */ 12 #include <mcld/Script/ScriptReader.h> 13 #include <mcld/Script/ScriptScanner.h> 14 #include <mcld/Script/Operand.h> 15 #include <mcld/Script/Operator.h> 16 #include <mcld/Script/Assignment.h> 17 #include <mcld/Script/RpnExpr.h> 18 #include <mcld/Script/FileToken.h> 19 #include <mcld/Script/NameSpec.h> 20 #include <mcld/Script/WildcardPattern.h> 21 #include <mcld/Support/MsgHandling.h> 22 using namespace mcld; 23 24 #undef yylex 25 #define yylex m_ScriptScanner.lex 26 %} 27 28 %code requires { 29 #include <mcld/Script/StrToken.h> 30 #include <mcld/Script/StringList.h> 31 #include <mcld/Script/OutputSectDesc.h> 32 #include <mcld/Script/InputSectDesc.h> 33 #include <llvm/Support/DataTypes.h> 34 35 using namespace mcld; 36 37 } 38 39 %require "2.4" 40 %skeleton "glr.cc" 41 /* 42 * BEGIN android-removed: prevent bison from generating the header in current directory 43 %defines "ScriptParser.h" 44 * END android-removed 45 */ 46 %debug 47 %error-verbose 48 %define namespace "mcld" 49 %define "parser_class_name" "ScriptParser" 50 %parse-param { const class LinkerConfig& m_LDConfig } 51 %parse-param { class ScriptFile& m_ScriptFile } 52 %parse-param { class ScriptScanner& m_ScriptScanner } 53 %parse-param { class GroupReader& m_GroupReader} 54 %lex-param { const class ScriptFile& m_ScriptFile } 55 56 %locations 57 %initial-action 58 { 59 /* Initialize the initial location. */ 60 @$.begin.filename = @$.end.filename = &(m_ScriptFile.name()); 61 } 62 63 %start script_file 64 65 %union { 66 const std::string* string; 67 uint64_t integer; 68 RpnExpr* rpn_expr; 69 StrToken* str_token; 70 StringList* str_tokens; 71 OutputSectDesc::Prolog output_prolog; 72 OutputSectDesc::Type output_type; 73 OutputSectDesc::Constraint output_constraint; 74 OutputSectDesc::Epilog output_epilog; 75 WildcardPattern* wildcard; 76 InputSectDesc::Spec input_spec; 77 } 78 79 %token END 0 /* EOF */ 80 %token <string> STRING LNAMESPEC 81 %token <integer> INTEGER 82 83 /* Initial states */ 84 %token LINKER_SCRIPT DEFSYM VERSION_SCRIPT DYNAMIC_LIST 85 86 /* Entry point */ 87 %token ENTRY 88 /* File Commands */ 89 %token INCLUDE 90 %token INPUT 91 %token GROUP 92 %token AS_NEEDED 93 %token OUTPUT 94 %token SEARCH_DIR 95 %token STARTUP 96 /* Format Commands */ 97 %token OUTPUT_FORMAT 98 %token TARGET 99 /* Misc Commands */ 100 %token ASSERT 101 %token EXTERN 102 %token FORCE_COMMON_ALLOCATION 103 %token INHIBIT_COMMON_ALLOCATION 104 %token INSERT 105 %token NOCROSSREFS 106 %token OUTPUT_ARCH 107 %token LD_FEATURE 108 /* Assignments */ 109 %token HIDDEN 110 %token PROVIDE 111 %token PROVIDE_HIDDEN 112 /* SECTIONS Command */ 113 %token SECTIONS 114 /* MEMORY Command */ 115 %token MEMORY 116 /* PHDRS Command */ 117 %token PHDRS 118 /* Builtin Functions */ 119 %token ABSOLUTE 120 %token ADDR 121 %token ALIGN 122 %token ALIGNOF 123 %token BLOCK 124 %token DATA_SEGMENT_ALIGN 125 %token DATA_SEGMENT_END 126 %token DATA_SEGMENT_RELRO_END 127 %token DEFINED 128 %token LENGTH 129 %token LOADADDR 130 %token MAX 131 %token MIN 132 %token NEXT 133 %token ORIGIN 134 %token SEGMENT_START 135 %token SIZEOF 136 %token SIZEOF_HEADERS 137 %token CONSTANT 138 /* Symbolic Constants */ 139 %token MAXPAGESIZE 140 %token COMMONPAGESIZE 141 /* Input Section Description */ 142 %token EXCLUDE_FILE 143 %token COMMON 144 %token KEEP 145 %token SORT_BY_NAME 146 %token SORT_BY_ALIGNMENT 147 %token SORT_NONE 148 %token SORT_BY_INIT_PRIORITY 149 /* Output Section Data */ 150 %token BYTE 151 %token SHORT 152 %token LONG 153 %token QUAD 154 %token SQUAD 155 %token FILL 156 /* Output Section Discarding */ 157 %token DISCARD 158 /* Output Section Keywords */ 159 %token CREATE_OBJECT_SYMBOLS 160 %token CONSTRUCTORS 161 /* Output Section Attributes */ 162 /* Output Section Type */ 163 %token NOLOAD 164 %token DSECT 165 %token COPY 166 %token INFO 167 %token OVERLAY 168 /* Output Section LMA */ 169 %token AT 170 /* Forced Input Alignment */ 171 %token SUBALIGN 172 /* Output Section Constraint */ 173 %token ONLY_IF_RO 174 %token ONLY_IF_RW 175 /* Operators are listed top to bottem, in ascending order */ 176 %left ',' 177 %right '=' ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN DIV_ASSIGN AND_ASSIGN OR_ASSIGN LS_ASSIGN RS_ASSIGN 178 %right '?' ':' 179 %left LOGICAL_OR 180 %left LOGICAL_AND 181 %left '|' 182 %left '^' 183 %left '&' 184 %left EQ NE 185 %left '<' LE '>' GE 186 %left LSHIFT RSHIFT 187 %left '+' '-' 188 %left '*' '/' '%' 189 %right UNARY_PLUS UNARY_MINUS '!' '~' 190 191 %type <integer> exp 192 %type <string> string symbol opt_region opt_lma_region wildcard_pattern 193 %type <rpn_expr> script_exp opt_lma opt_align opt_subalign opt_fill 194 %type <str_token> input phdr 195 %type <str_tokens> input_list opt_phdr opt_exclude_files input_sect_wildcard_patterns 196 %type <output_prolog> output_desc_prolog opt_vma_and_type 197 %type <output_type> opt_type type 198 %type <output_constraint> opt_constraint 199 %type <output_epilog> output_desc_epilog 200 %type <wildcard> wildcard_file wildcard_section 201 %type <input_spec> input_sect_spec 202 203 %% 204 205 script_file : LINKER_SCRIPT 206 { m_ScriptScanner.setLexState(ScriptFile::LDScript); } 207 linker_script 208 { m_ScriptScanner.popLexState(); } 209 ; 210 211 linker_script : linker_script script_command 212 | /* Empty */ 213 ; 214 215 script_command : entry_command 216 | output_format_command 217 | group_command 218 | output_command 219 | search_dir_command 220 | output_arch_command 221 | assert_command 222 | symbol_assignment 223 | sections_command 224 | ';' 225 ; 226 227 entry_command : ENTRY '(' STRING ')' 228 { m_ScriptFile.addEntryPoint(*$3); } 229 ; 230 231 output_format_command : OUTPUT_FORMAT '(' STRING ')' 232 { m_ScriptFile.addOutputFormatCmd(*$3); } 233 | OUTPUT_FORMAT '(' STRING ',' STRING ',' STRING ')' 234 { m_ScriptFile.addOutputFormatCmd(*$3, *$5, *$7); } 235 ; 236 237 group_command : GROUP '(' input_list ')' 238 { m_ScriptFile.addGroupCmd(*$3, m_GroupReader, m_LDConfig); } 239 ; 240 241 search_dir_command : SEARCH_DIR '(' STRING ')' 242 { m_ScriptFile.addSearchDirCmd(*$3); } 243 ; 244 245 output_command : OUTPUT '(' STRING ')' 246 { m_ScriptFile.addOutputCmd(*$3); } 247 ; 248 249 output_arch_command : OUTPUT_ARCH '(' STRING ')' 250 { m_ScriptFile.addOutputArchCmd(*$3); } 251 ; 252 253 assert_command : ASSERT '(' script_exp ',' string ')' 254 { m_ScriptFile.addAssertCmd(*$3, *$5); } 255 ; 256 257 input_list : { m_ScriptFile.createStringList(); } 258 inputs 259 { $$ = m_ScriptFile.getCurrentStringList(); } 260 ; 261 262 inputs : input 263 { m_ScriptFile.getCurrentStringList()->push_back($1); } 264 | inputs input 265 { m_ScriptFile.getCurrentStringList()->push_back($2); } 266 | inputs ',' input 267 { m_ScriptFile.getCurrentStringList()->push_back($3); } 268 | AS_NEEDED '(' 269 { m_ScriptFile.setAsNeeded(true); } 270 inputs ')' 271 { m_ScriptFile.setAsNeeded(false); } 272 | inputs AS_NEEDED '(' 273 { m_ScriptFile.setAsNeeded(true); } 274 inputs ')' 275 { m_ScriptFile.setAsNeeded(false); } 276 | inputs ',' AS_NEEDED '(' 277 { m_ScriptFile.setAsNeeded(true); } 278 inputs ')' 279 { m_ScriptFile.setAsNeeded(false); } 280 ; 281 282 input : string 283 { $$ = FileToken::create(*$1, m_ScriptFile.asNeeded()); } 284 | LNAMESPEC 285 { $$ = NameSpec::create(*$1, m_ScriptFile.asNeeded()); } 286 ; 287 288 /* 289 SECTIONS 290 { 291 sections-command 292 sections-command 293 ... 294 } 295 */ 296 sections_command : SECTIONS 297 { m_ScriptFile.enterSectionsCmd(); } 298 '{' sect_commands '}' 299 { m_ScriptFile.leaveSectionsCmd(); } 300 ; 301 302 sect_commands : sect_commands sect_cmd 303 | /* Empty */ 304 ; 305 306 /* 307 Each sections-command may of be one of the following: 308 309 an ENTRY command (see Entry command) 310 a symbol assignment (see Assignments) 311 an output section description 312 an overlay description 313 */ 314 sect_cmd : entry_command 315 | symbol_assignment 316 | output_sect_desc 317 ; 318 319 /* 320 The full description of an output section looks like this: 321 322 section [address] [(type)] : 323 [AT(lma)] 324 [ALIGN(section_align)] 325 [SUBALIGN(subsection_align)] 326 [constraint] 327 { 328 output-section-command 329 output-section-command 330 ... 331 } [>region] [AT>lma_region] [:phdr :phdr ...] [=fillexp] 332 */ 333 output_sect_desc : string output_desc_prolog 334 { m_ScriptFile.enterOutputSectDesc(*$1, $2); } 335 '{' 336 output_sect_commands 337 '}' output_desc_epilog 338 { m_ScriptFile.leaveOutputSectDesc($7); } 339 ; 340 341 output_desc_prolog : { 342 m_ScriptScanner.setLexState(ScriptFile::Expression); 343 /* create exp for vma */ 344 m_ScriptFile.createRpnExpr(); 345 } 346 opt_vma_and_type 347 { m_ScriptScanner.popLexState(); } 348 ':' 349 opt_lma opt_align opt_subalign opt_constraint 350 { 351 $$.m_pVMA = $2.m_pVMA; 352 $$.m_Type = $2.m_Type; 353 $$.m_pLMA = $5; 354 $$.m_pAlign = $6; 355 $$.m_pSubAlign = $7; 356 $$.m_Constraint = $8; 357 } 358 ; 359 360 output_sect_commands : output_sect_commands output_sect_cmd 361 | /* Empty */ 362 ; 363 364 output_desc_epilog : opt_region opt_lma_region opt_phdr opt_fill 365 { 366 $$.m_pRegion = $1; 367 $$.m_pLMARegion = $2; 368 $$.m_pPhdrs = $3; 369 $$.m_pFillExp = $4; 370 } 371 ; 372 373 /* Output Section Attributes */ 374 opt_vma_and_type : exp opt_type 375 { 376 $$.m_pVMA = m_ScriptFile.getCurrentRpnExpr(); 377 $$.m_Type = $2; 378 } 379 | opt_type 380 { 381 $$.m_pVMA = NULL; 382 $$.m_Type = $1; 383 } 384 ; 385 386 opt_type : '(' type ')' 387 { $$ = $2; } 388 | '(' ')' 389 { $$ = OutputSectDesc::LOAD; } 390 | /* Empty */ 391 { $$ = OutputSectDesc::LOAD; } 392 ; 393 394 type : NOLOAD 395 { $$ = OutputSectDesc::NOLOAD; } 396 | DSECT 397 { $$ = OutputSectDesc::DSECT; } 398 | COPY 399 { $$ = OutputSectDesc::COPY; } 400 | INFO 401 { $$ = OutputSectDesc::INFO; } 402 | OVERLAY 403 { $$ = OutputSectDesc::OVERLAY; } 404 ; 405 406 opt_lma : AT '(' script_exp ')' 407 { $$ = $3; } 408 | /* Empty */ 409 { $$ = NULL; } 410 ; 411 412 /* Forced Output Alignment */ 413 opt_align : ALIGN '(' script_exp ')' 414 { $$ = $3; } 415 | /* Empty */ 416 { $$ = NULL; } 417 ; 418 419 /* Forced Input Alignment */ 420 opt_subalign : SUBALIGN '(' script_exp ')' 421 { $$ = $3; } 422 | /* Empty */ 423 { $$ = NULL; } 424 ; 425 426 opt_constraint : ONLY_IF_RO 427 { $$ = OutputSectDesc::ONLY_IF_RO; } 428 | ONLY_IF_RW 429 { $$ = OutputSectDesc::ONLY_IF_RW; } 430 | /* Empty */ 431 { $$ = OutputSectDesc::NO_CONSTRAINT; } 432 ; 433 434 opt_region : '>' string 435 { $$ = $2; } 436 | /* Empty */ 437 { $$ = NULL; } 438 ; 439 440 opt_lma_region : AT '>' string 441 { $$ = $3; } 442 | /* Empty */ 443 { $$ = NULL; } 444 ; 445 446 opt_phdr : { m_ScriptFile.createStringList(); } 447 phdrs 448 { $$ = m_ScriptFile.getCurrentStringList(); } 449 ; 450 451 phdrs : phdrs ':' phdr 452 { m_ScriptFile.getCurrentStringList()->push_back($3); } 453 | /* Empty */ 454 ; 455 456 phdr : string 457 { $$ = StrToken::create(*$1); } 458 ; 459 460 opt_fill : '=' script_exp 461 { $$ = $2; } 462 | /* Empty */ 463 { $$ = NULL; } 464 ; 465 466 /* 467 Each output-section-command may be one of the following: 468 469 a symbol assignment (see Assignments) 470 an input section description (see Input Section) 471 data values to include directly (see Output Section Data) 472 a special output section keyword (see Output Section Keywords) 473 */ 474 output_sect_cmd : symbol_assignment 475 | input_sect_desc 476 | output_sect_data 477 | output_sect_keyword 478 | ';' 479 ; 480 481 input_sect_desc : input_sect_spec 482 { m_ScriptFile.addInputSectDesc(InputSectDesc::NoKeep, $1); } 483 | KEEP '(' input_sect_spec ')' 484 { m_ScriptFile.addInputSectDesc(InputSectDesc::Keep, $3); } 485 ; 486 487 input_sect_spec : string 488 { 489 $$.m_pWildcardFile = 490 WildcardPattern::create(*$1, WildcardPattern::SORT_NONE); 491 $$.m_pExcludeFiles = NULL; 492 $$.m_pWildcardSections = NULL; 493 } 494 | wildcard_file '(' opt_exclude_files input_sect_wildcard_patterns ')' 495 { 496 $$.m_pWildcardFile = $1; 497 $$.m_pExcludeFiles = $3; 498 $$.m_pWildcardSections = $4; 499 } 500 ; 501 502 wildcard_file : wildcard_pattern 503 { $$ = WildcardPattern::create(*$1, WildcardPattern::SORT_NONE); } 504 | SORT_BY_NAME '(' wildcard_pattern ')' 505 { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_NAME); } 506 ; 507 508 wildcard_pattern : string 509 { $$ = $1; } 510 | '*' 511 { $$ = &m_ScriptFile.createParserStr("*", 1); } 512 | '?' 513 { $$ = &m_ScriptFile.createParserStr("?", 1); } 514 ; 515 516 opt_exclude_files : EXCLUDE_FILE '(' 517 { m_ScriptFile.createStringList(); } 518 exclude_files ')' 519 { $$ = m_ScriptFile.getCurrentStringList(); } 520 | /* Empty */ 521 { $$ = NULL; } 522 ; 523 524 exclude_files : exclude_files wildcard_pattern 525 { 526 m_ScriptFile.getCurrentStringList()->push_back( 527 WildcardPattern::create(*$2, WildcardPattern::SORT_NONE)); 528 } 529 | wildcard_pattern 530 { 531 m_ScriptFile.getCurrentStringList()->push_back( 532 WildcardPattern::create(*$1, WildcardPattern::SORT_NONE)); 533 } 534 ; 535 536 input_sect_wildcard_patterns : { m_ScriptFile.createStringList(); } 537 wildcard_sections 538 { $$ = m_ScriptFile.getCurrentStringList(); } 539 ; 540 541 wildcard_sections : wildcard_sections wildcard_section 542 { 543 m_ScriptFile.getCurrentStringList()->push_back($2); 544 } 545 | wildcard_section 546 { 547 m_ScriptFile.getCurrentStringList()->push_back($1); 548 } 549 ; 550 551 wildcard_section : wildcard_pattern 552 { $$ = WildcardPattern::create(*$1, WildcardPattern::SORT_NONE); } 553 | SORT_NONE '(' wildcard_pattern ')' 554 { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_NONE); } 555 | SORT_BY_NAME '(' wildcard_pattern ')' 556 { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_NAME); } 557 | SORT_BY_ALIGNMENT '(' wildcard_pattern ')' 558 { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_ALIGNMENT); } 559 | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_pattern ')' ')' 560 { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_NAME_ALIGNMENT); } 561 | SORT_BY_ALIGNMENT '('SORT_BY_NAME '(' wildcard_pattern ')' ')' 562 { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_ALIGNMENT_NAME); } 563 | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_pattern ')' ')' 564 { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_NAME); } 565 | SORT_BY_ALIGNMENT '(' SORT_BY_ALIGNMENT '(' wildcard_pattern ')' ')' 566 { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_ALIGNMENT); } 567 | SORT_BY_INIT_PRIORITY '(' wildcard_pattern ')' 568 { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_INIT_PRIORITY); } 569 ; 570 571 output_sect_data : BYTE '(' script_exp ')' 572 | SHORT '(' script_exp ')' 573 | LONG '(' script_exp ')' 574 | QUAD '(' script_exp ')' 575 | SQUAD '(' script_exp ')' 576 ; 577 578 output_sect_keyword : CREATE_OBJECT_SYMBOLS 579 | CONSTRUCTORS 580 | SORT_BY_NAME '(' CONSTRUCTORS ')' 581 ; 582 583 symbol_assignment : symbol '=' script_exp ';' 584 { m_ScriptFile.addAssignment(*$1, *$3); } 585 | symbol ADD_ASSIGN exp ';' 586 | symbol SUB_ASSIGN exp ';' 587 | symbol MUL_ASSIGN exp ';' 588 | symbol DIV_ASSIGN exp ';' 589 | symbol AND_ASSIGN exp ';' 590 | symbol OR_ASSIGN exp ';' 591 | symbol LS_ASSIGN exp ';' 592 | symbol RS_ASSIGN exp ';' 593 | HIDDEN '(' symbol '=' script_exp ')' ';' 594 { 595 m_ScriptFile.addAssignment(*$3, *$5, 596 Assignment::HIDDEN); 597 } 598 | PROVIDE '(' symbol '=' script_exp ')' ';' 599 { 600 m_ScriptFile.addAssignment(*$3, *$5, 601 Assignment::PROVIDE); 602 } 603 | PROVIDE_HIDDEN '(' symbol '=' script_exp ')' ';' 604 { 605 m_ScriptFile.addAssignment(*$3, *$5, 606 Assignment::PROVIDE_HIDDEN); 607 } 608 ; 609 610 script_exp : { 611 m_ScriptScanner.setLexState(ScriptFile::Expression); 612 m_ScriptFile.createRpnExpr(); 613 } 614 exp 615 { 616 m_ScriptScanner.popLexState(); 617 $$ = m_ScriptFile.getCurrentRpnExpr(); 618 } 619 ; 620 621 exp : '(' exp ')' 622 { 623 $$ = $2; 624 } 625 | '+' exp %prec UNARY_PLUS 626 { 627 m_ScriptFile.getCurrentRpnExpr()->push_back( 628 &Operator::create<Operator::UNARY_PLUS>()); 629 $$ = $2 + 1; 630 } 631 | '-' exp %prec UNARY_MINUS 632 { 633 m_ScriptFile.getCurrentRpnExpr()->push_back( 634 &Operator::create<Operator::UNARY_MINUS>()); 635 $$ = $2 + 1; 636 } 637 | '!' exp 638 { 639 m_ScriptFile.getCurrentRpnExpr()->push_back( 640 &Operator::create<Operator::LOGICAL_NOT>()); 641 $$ = $2 + 1; 642 } 643 | '~' exp 644 { 645 m_ScriptFile.getCurrentRpnExpr()->push_back( 646 &Operator::create<Operator::BITWISE_NOT>()); 647 $$ = $2 + 1; 648 } 649 | exp '*' exp 650 { 651 m_ScriptFile.getCurrentRpnExpr()->push_back( 652 &Operator::create<Operator::MUL>()); 653 $$ = $1 + $3 + 1; 654 } 655 | exp '/' exp 656 { 657 m_ScriptFile.getCurrentRpnExpr()->push_back( 658 &Operator::create<Operator::DIV>()); 659 $$ = $1 + $3 + 1; 660 } 661 | exp '%' exp 662 { 663 m_ScriptFile.getCurrentRpnExpr()->push_back( 664 &Operator::create<Operator::MOD>()); 665 $$ = $1 + $3 + 1; 666 } 667 | exp '+' exp 668 { 669 m_ScriptFile.getCurrentRpnExpr()->push_back( 670 &Operator::create<Operator::ADD>()); 671 $$ = $1 + $3 + 1; 672 } 673 | exp '-' exp 674 { 675 m_ScriptFile.getCurrentRpnExpr()->push_back( 676 &Operator::create<Operator::SUB>()); 677 $$ = $1 + $3 + 1; 678 } 679 | exp LSHIFT exp 680 { 681 m_ScriptFile.getCurrentRpnExpr()->push_back( 682 &Operator::create<Operator::LSHIFT>()); 683 $$ = $1 + $3 + 1; 684 } 685 | exp RSHIFT exp 686 { 687 m_ScriptFile.getCurrentRpnExpr()->push_back( 688 &Operator::create<Operator::RSHIFT>()); 689 $$ = $1 + $3 + 1; 690 } 691 | exp '<' exp 692 { 693 m_ScriptFile.getCurrentRpnExpr()->push_back( 694 &Operator::create<Operator::LT>()); 695 $$ = $1 + $3 + 1; 696 } 697 | exp LE exp 698 { 699 m_ScriptFile.getCurrentRpnExpr()->push_back( 700 &Operator::create<Operator::LE>()); 701 $$ = $1 + $3 + 1; 702 } 703 | exp '>' exp 704 { 705 m_ScriptFile.getCurrentRpnExpr()->push_back( 706 &Operator::create<Operator::GT>()); 707 $$ = $1 + $3 + 1; 708 } 709 | exp GE exp 710 { 711 m_ScriptFile.getCurrentRpnExpr()->push_back( 712 &Operator::create<Operator::GE>()); 713 $$ = $1 + $3 + 1; 714 } 715 | exp EQ exp 716 { 717 m_ScriptFile.getCurrentRpnExpr()->push_back( 718 &Operator::create<Operator::EQ>()); 719 $$ = $1 + $3 + 1; 720 } 721 | exp NE exp 722 { 723 m_ScriptFile.getCurrentRpnExpr()->push_back( 724 &Operator::create<Operator::NE>()); 725 $$ = $1 + $3 + 1; 726 } 727 | exp '&' exp 728 { 729 m_ScriptFile.getCurrentRpnExpr()->push_back( 730 &Operator::create<Operator::BITWISE_AND>()); 731 $$ = $1 + $3 + 1; 732 } 733 | exp '^' exp 734 { 735 m_ScriptFile.getCurrentRpnExpr()->push_back( 736 &Operator::create<Operator::BITWISE_XOR>()); 737 $$ = $1 + $3 + 1; 738 } 739 | exp '|' exp 740 { 741 m_ScriptFile.getCurrentRpnExpr()->push_back( 742 &Operator::create<Operator::BITWISE_OR>()); 743 $$ = $1 + $3 + 1; 744 } 745 | exp LOGICAL_AND exp 746 { 747 m_ScriptFile.getCurrentRpnExpr()->push_back( 748 &Operator::create<Operator::LOGICAL_AND>()); 749 $$ = $1 + $3 + 1; 750 } 751 | exp LOGICAL_OR exp 752 { 753 m_ScriptFile.getCurrentRpnExpr()->push_back( 754 &Operator::create<Operator::LOGICAL_OR>()); 755 $$ = $1 + $3 + 1; 756 } 757 | exp '?' exp ':' exp 758 { 759 m_ScriptFile.getCurrentRpnExpr()->push_back( 760 &Operator::create<Operator::TERNARY_IF>()); 761 $$ = $1 + $3 + $5 + 1; 762 } 763 | ABSOLUTE '(' exp ')' 764 { 765 m_ScriptFile.getCurrentRpnExpr()->push_back( 766 &Operator::create<Operator::ABSOLUTE>()); 767 $$ = $3 + 1; 768 } 769 | ADDR '(' string ')' 770 { 771 m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3)); 772 m_ScriptFile.getCurrentRpnExpr()->push_back( 773 &Operator::create<Operator::ADDR>()); 774 $$ = 2; 775 } 776 | ALIGN '(' exp ')' 777 { 778 RpnExpr::iterator pos = m_ScriptFile.getCurrentRpnExpr()->begin() + 779 m_ScriptFile.getCurrentRpnExpr()->size() - $3; 780 m_ScriptFile.getCurrentRpnExpr()->insert(pos, SymOperand::create(".")); 781 m_ScriptFile.getCurrentRpnExpr()->push_back( 782 &Operator::create<Operator::ALIGN>()); 783 $$ = $3 + 2; 784 } 785 | ALIGN '(' exp ',' exp ')' 786 { 787 m_ScriptFile.getCurrentRpnExpr()->push_back( 788 &Operator::create<Operator::ALIGN>()); 789 $$ = $3 + $5 + 1; 790 } 791 | ALIGNOF '(' string ')' 792 { 793 m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3)); 794 m_ScriptFile.getCurrentRpnExpr()->push_back( 795 &Operator::create<Operator::ALIGNOF>()); 796 $$ = 2; 797 } 798 | BLOCK '(' exp ')' 799 { 800 RpnExpr::iterator pos = m_ScriptFile.getCurrentRpnExpr()->begin() + 801 m_ScriptFile.getCurrentRpnExpr()->size() - $3; 802 m_ScriptFile.getCurrentRpnExpr()->insert(pos, SymOperand::create(".")); 803 m_ScriptFile.getCurrentRpnExpr()->push_back( 804 &Operator::create<Operator::ALIGN>()); 805 $$ = $3 + 2; 806 } 807 | DATA_SEGMENT_ALIGN 808 { 809 m_ScriptFile.getCurrentRpnExpr()->push_back(SymOperand::create(".")); 810 } 811 '(' exp ',' exp ')' 812 { 813 m_ScriptFile.getCurrentRpnExpr()->push_back( 814 &Operator::create<Operator::DATA_SEGMENT_ALIGN>()); 815 $$ = $4 + $6 + 2; 816 } 817 | DATA_SEGMENT_END '(' exp ')' 818 { 819 m_ScriptFile.getCurrentRpnExpr()->push_back( 820 &Operator::create<Operator::DATA_SEGMENT_END>()); 821 $$ = $3 + 1; 822 } 823 | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')' 824 { 825 m_ScriptFile.getCurrentRpnExpr()->push_back( 826 &Operator::create<Operator::DATA_SEGMENT_RELRO_END>()); 827 $$ = $3 + $5 + 1; 828 } 829 | DEFINED '(' symbol ')' 830 { 831 m_ScriptFile.getCurrentRpnExpr()->push_back(SymOperand::create(*$3)); 832 m_ScriptFile.getCurrentRpnExpr()->push_back( 833 &Operator::create<Operator::DEFINED>()); 834 $$ = 2; 835 } 836 | LENGTH '(' string ')' 837 { 838 /* TODO */ 839 } 840 | LOADADDR '(' string ')' 841 { 842 m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3)); 843 m_ScriptFile.getCurrentRpnExpr()->push_back( 844 &Operator::create<Operator::LOADADDR>()); 845 $$ = 2; 846 } 847 | MAX '(' exp ',' exp ')' 848 { 849 m_ScriptFile.getCurrentRpnExpr()->push_back( 850 &Operator::create<Operator::MAX>()); 851 $$ = $3 + $5 + 1; 852 } 853 | MIN '(' exp ',' exp ')' 854 { 855 m_ScriptFile.getCurrentRpnExpr()->push_back( 856 &Operator::create<Operator::MIN>()); 857 $$ = $3 + $5 + 1; 858 } 859 | NEXT '(' exp ')' 860 { 861 m_ScriptFile.getCurrentRpnExpr()->push_back( 862 &Operator::create<Operator::NEXT>()); 863 $$ = $3 + 1; 864 } 865 | ORIGIN '(' string ')' 866 { 867 /* TODO */ 868 } 869 | SEGMENT_START '(' string 870 { 871 m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3)); 872 } 873 ',' exp ')' 874 { 875 m_ScriptFile.getCurrentRpnExpr()->push_back( 876 &Operator::create<Operator::SEGMENT_START>()); 877 $$ = $6 + 2; 878 } 879 | SIZEOF '(' string ')' 880 { 881 m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3)); 882 m_ScriptFile.getCurrentRpnExpr()->push_back( 883 &Operator::create<Operator::SIZEOF>()); 884 $$ = 2; 885 } 886 | SIZEOF_HEADERS 887 { 888 m_ScriptFile.getCurrentRpnExpr()->push_back( 889 &Operator::create<Operator::SIZEOF_HEADERS>()); 890 $$ = 1; 891 } 892 | CONSTANT '(' MAXPAGESIZE ')' 893 { 894 m_ScriptFile.getCurrentRpnExpr()->push_back( 895 &Operator::create<Operator::MAXPAGESIZE>()); 896 $$ = 1; 897 } 898 | CONSTANT '(' COMMONPAGESIZE')' 899 { 900 m_ScriptFile.getCurrentRpnExpr()->push_back( 901 &Operator::create<Operator::COMMONPAGESIZE>()); 902 $$ = 1; 903 } 904 | INTEGER 905 { 906 m_ScriptFile.getCurrentRpnExpr()->push_back(IntOperand::create($1)); 907 $$ = 1; 908 } 909 | symbol 910 { 911 m_ScriptFile.getCurrentRpnExpr()->push_back(SymOperand::create(*$1)); 912 $$ = 1; 913 } 914 ; 915 916 symbol : STRING 917 { $$ = $1; } 918 ; 919 920 string : STRING 921 { $$ = $1; } 922 | '"' STRING '"' 923 { $$ = $2; } 924 ; 925 926 %% 927 928 void mcld::ScriptParser::error(const mcld::ScriptParser::location_type& pLoc, 929 const std::string &pMsg) 930 { 931 position last = pLoc.end - 1; 932 std::string filename = "NaN"; 933 if (last.filename != NULL) 934 filename = *last.filename; 935 936 mcld::error(diag::err_syntax_error) 937 << filename << last.line << last.column << pMsg; 938 } 939 940