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