| /*===- ScriptParser.yy ----------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===*/ |
| |
| %{ |
| /* C/C++ Declarations */ |
| #include "mcld/Script/ScriptReader.h" |
| #include "mcld/Script/ScriptScanner.h" |
| #include "mcld/Script/Operand.h" |
| #include "mcld/Script/Operator.h" |
| #include "mcld/Script/Assignment.h" |
| #include "mcld/Script/RpnExpr.h" |
| #include "mcld/Script/FileToken.h" |
| #include "mcld/Script/NameSpec.h" |
| #include "mcld/Script/WildcardPattern.h" |
| #include "mcld/Support/MsgHandling.h" |
| using namespace mcld; |
| |
| #undef yylex |
| #define yylex m_ScriptScanner.lex |
| %} |
| |
| %code requires { |
| #include "mcld/Script/StrToken.h" |
| #include "mcld/Script/StringList.h" |
| #include "mcld/Script/OutputSectDesc.h" |
| #include "mcld/Script/InputSectDesc.h" |
| #include <llvm/Support/DataTypes.h> |
| |
| using namespace mcld; |
| |
| } |
| |
| %require "2.4" |
| %skeleton "glr.cc" |
| /* |
| * BEGIN android-removed: prevent bison from generating the header in current directory |
| %defines "ScriptParser.h" |
| * END android-removed |
| */ |
| %debug |
| %define parse.error verbose |
| %define api.namespace {mcld} |
| %define api.parser.class {ScriptParser} |
| %parse-param { const class LinkerConfig& m_LDConfig } |
| %parse-param { class ScriptFile& m_ScriptFile } |
| %parse-param { class ScriptScanner& m_ScriptScanner } |
| %parse-param { class ObjectReader& m_ObjectReader} |
| %parse-param { class ArchiveReader& m_ArchiveReader} |
| %parse-param { class DynObjReader& m_DynObjReader} |
| %parse-param { class GroupReader& m_GroupReader} |
| %lex-param { const class ScriptFile& m_ScriptFile } |
| |
| %locations |
| %initial-action |
| { |
| /* Initialize the initial location. */ |
| @$.begin.filename = @$.end.filename = &(m_ScriptFile.name()); |
| } |
| |
| %start script_file |
| |
| %union { |
| const std::string* string; |
| uint64_t integer; |
| RpnExpr* rpn_expr; |
| StrToken* str_token; |
| StringList* str_tokens; |
| OutputSectDesc::Prolog output_prolog; |
| OutputSectDesc::Type output_type; |
| OutputSectDesc::Constraint output_constraint; |
| OutputSectDesc::Epilog output_epilog; |
| WildcardPattern* wildcard; |
| InputSectDesc::Spec input_spec; |
| } |
| |
| %token END 0 /* EOF */ |
| %token <string> STRING LNAMESPEC |
| %token <integer> INTEGER |
| |
| /* Initial states */ |
| %token LINKER_SCRIPT DEFSYM VERSION_SCRIPT DYNAMIC_LIST |
| |
| /* Entry point */ |
| %token ENTRY |
| /* File Commands */ |
| %token INCLUDE |
| %token INPUT |
| %token GROUP |
| %token AS_NEEDED |
| %token OUTPUT |
| %token SEARCH_DIR |
| %token STARTUP |
| /* Format Commands */ |
| %token OUTPUT_FORMAT |
| %token TARGET |
| /* Misc Commands */ |
| %token ASSERT |
| %token EXTERN |
| %token FORCE_COMMON_ALLOCATION |
| %token INHIBIT_COMMON_ALLOCATION |
| %token INSERT |
| %token NOCROSSREFS |
| %token OUTPUT_ARCH |
| %token LD_FEATURE |
| /* Assignments */ |
| %token HIDDEN |
| %token PROVIDE |
| %token PROVIDE_HIDDEN |
| /* SECTIONS Command */ |
| %token SECTIONS |
| /* MEMORY Command */ |
| %token MEMORY |
| /* PHDRS Command */ |
| %token PHDRS |
| /* Builtin Functions */ |
| %token ABSOLUTE |
| %token ADDR |
| %token ALIGN |
| %token ALIGNOF |
| %token BLOCK |
| %token DATA_SEGMENT_ALIGN |
| %token DATA_SEGMENT_END |
| %token DATA_SEGMENT_RELRO_END |
| %token DEFINED |
| %token LENGTH |
| %token LOADADDR |
| %token MAX |
| %token MIN |
| %token NEXT |
| %token ORIGIN |
| %token SEGMENT_START |
| %token SIZEOF |
| %token SIZEOF_HEADERS |
| %token CONSTANT |
| /* Symbolic Constants */ |
| %token MAXPAGESIZE |
| %token COMMONPAGESIZE |
| /* Input Section Description */ |
| %token EXCLUDE_FILE |
| %token COMMON |
| %token KEEP |
| %token SORT_BY_NAME |
| %token SORT_BY_ALIGNMENT |
| %token SORT_NONE |
| %token SORT_BY_INIT_PRIORITY |
| /* Output Section Data */ |
| %token BYTE |
| %token SHORT |
| %token LONG |
| %token QUAD |
| %token SQUAD |
| %token FILL |
| /* Output Section Discarding */ |
| %token DISCARD |
| /* Output Section Keywords */ |
| %token CREATE_OBJECT_SYMBOLS |
| %token CONSTRUCTORS |
| /* Output Section Attributes */ |
| /* Output Section Type */ |
| %token NOLOAD |
| %token DSECT |
| %token COPY |
| %token INFO |
| %token OVERLAY |
| /* Output Section LMA */ |
| %token AT |
| /* Forced Input Alignment */ |
| %token SUBALIGN |
| /* Output Section Constraint */ |
| %token ONLY_IF_RO |
| %token ONLY_IF_RW |
| /* Operators are listed top to bottem, in ascending order */ |
| %left ',' |
| %right '=' ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN DIV_ASSIGN AND_ASSIGN OR_ASSIGN LS_ASSIGN RS_ASSIGN |
| %right '?' ':' |
| %left LOGICAL_OR |
| %left LOGICAL_AND |
| %left '|' |
| %left '^' |
| %left '&' |
| %left EQ NE |
| %left '<' LE '>' GE |
| %left LSHIFT RSHIFT |
| %left '+' '-' |
| %left '*' '/' '%' |
| %right UNARY_PLUS UNARY_MINUS '!' '~' |
| |
| %type <integer> exp |
| %type <string> string symbol opt_region opt_lma_region wildcard_pattern |
| %type <rpn_expr> script_exp opt_lma opt_align opt_subalign opt_fill |
| %type <str_token> input phdr |
| %type <str_tokens> input_list opt_phdr opt_exclude_files input_sect_wildcard_patterns |
| %type <output_prolog> output_desc_prolog opt_vma_and_type |
| %type <output_type> opt_type type |
| %type <output_constraint> opt_constraint |
| %type <output_epilog> output_desc_epilog |
| %type <wildcard> wildcard_file wildcard_section |
| %type <input_spec> input_sect_spec |
| |
| %% |
| |
| script_file : LINKER_SCRIPT |
| { m_ScriptScanner.setLexState(ScriptFile::LDScript); } |
| linker_script |
| { m_ScriptScanner.popLexState(); } |
| ; |
| |
| linker_script : linker_script script_command |
| | /* Empty */ |
| ; |
| |
| script_command : entry_command |
| | output_format_command |
| | group_command |
| | input_command |
| | output_command |
| | search_dir_command |
| | output_arch_command |
| | assert_command |
| | symbol_assignment |
| | sections_command |
| | ';' |
| ; |
| |
| entry_command : ENTRY '(' STRING ')' |
| { m_ScriptFile.addEntryPoint(*$3); } |
| ; |
| |
| output_format_command : OUTPUT_FORMAT '(' STRING ')' |
| { m_ScriptFile.addOutputFormatCmd(*$3); } |
| | OUTPUT_FORMAT '(' STRING ',' STRING ',' STRING ')' |
| { m_ScriptFile.addOutputFormatCmd(*$3, *$5, *$7); } |
| ; |
| |
| group_command : GROUP '(' input_list ')' |
| { m_ScriptFile.addGroupCmd(*$3, m_GroupReader, m_LDConfig); } |
| ; |
| |
| input_command : INPUT '(' input_list ')' |
| { |
| m_ScriptFile.addInputCmd(*$3, m_ObjectReader, m_ArchiveReader, |
| m_DynObjReader, m_LDConfig); |
| } |
| ; |
| |
| search_dir_command : SEARCH_DIR '(' STRING ')' |
| { m_ScriptFile.addSearchDirCmd(*$3); } |
| ; |
| |
| output_command : OUTPUT '(' STRING ')' |
| { m_ScriptFile.addOutputCmd(*$3); } |
| ; |
| |
| output_arch_command : OUTPUT_ARCH '(' STRING ')' |
| { m_ScriptFile.addOutputArchCmd(*$3); } |
| ; |
| |
| assert_command : ASSERT '(' script_exp ',' string ')' |
| { m_ScriptFile.addAssertCmd(*$3, *$5); } |
| ; |
| |
| input_list : { m_ScriptFile.createStringList(); } |
| inputs |
| { $$ = m_ScriptFile.getCurrentStringList(); } |
| ; |
| |
| inputs : input |
| { m_ScriptFile.getCurrentStringList()->push_back($1); } |
| | inputs input |
| { m_ScriptFile.getCurrentStringList()->push_back($2); } |
| | inputs ',' input |
| { m_ScriptFile.getCurrentStringList()->push_back($3); } |
| | AS_NEEDED '(' |
| { m_ScriptFile.setAsNeeded(true); } |
| inputs ')' |
| { m_ScriptFile.setAsNeeded(false); } |
| | inputs AS_NEEDED '(' |
| { m_ScriptFile.setAsNeeded(true); } |
| inputs ')' |
| { m_ScriptFile.setAsNeeded(false); } |
| | inputs ',' AS_NEEDED '(' |
| { m_ScriptFile.setAsNeeded(true); } |
| inputs ')' |
| { m_ScriptFile.setAsNeeded(false); } |
| ; |
| |
| input : string |
| { $$ = FileToken::create(*$1, m_ScriptFile.asNeeded()); } |
| | LNAMESPEC |
| { $$ = NameSpec::create(*$1, m_ScriptFile.asNeeded()); } |
| ; |
| |
| /* |
| SECTIONS |
| { |
| sections-command |
| sections-command |
| ... |
| } |
| */ |
| sections_command : SECTIONS |
| { m_ScriptFile.enterSectionsCmd(); } |
| '{' sect_commands '}' |
| { m_ScriptFile.leaveSectionsCmd(); } |
| ; |
| |
| sect_commands : sect_commands sect_cmd |
| | /* Empty */ |
| ; |
| |
| /* |
| Each sections-command may of be one of the following: |
| |
| an ENTRY command (see Entry command) |
| a symbol assignment (see Assignments) |
| an output section description |
| an overlay description |
| */ |
| sect_cmd : entry_command |
| | symbol_assignment |
| | output_sect_desc |
| ; |
| |
| /* |
| The full description of an output section looks like this: |
| |
| section [address] [(type)] : |
| [AT(lma)] |
| [ALIGN(section_align)] |
| [SUBALIGN(subsection_align)] |
| [constraint] |
| { |
| output-section-command |
| output-section-command |
| ... |
| } [>region] [AT>lma_region] [:phdr :phdr ...] [=fillexp] |
| */ |
| output_sect_desc : string output_desc_prolog |
| { m_ScriptFile.enterOutputSectDesc(*$1, $2); } |
| '{' |
| output_sect_commands |
| '}' output_desc_epilog |
| { m_ScriptFile.leaveOutputSectDesc($7); } |
| ; |
| |
| output_desc_prolog : { |
| m_ScriptScanner.setLexState(ScriptFile::Expression); |
| /* create exp for vma */ |
| m_ScriptFile.createRpnExpr(); |
| } |
| opt_vma_and_type |
| { m_ScriptScanner.popLexState(); } |
| ':' |
| opt_lma opt_align opt_subalign opt_constraint |
| { |
| $$.m_pVMA = $2.m_pVMA; |
| $$.m_Type = $2.m_Type; |
| $$.m_pLMA = $5; |
| $$.m_pAlign = $6; |
| $$.m_pSubAlign = $7; |
| $$.m_Constraint = $8; |
| } |
| ; |
| |
| output_sect_commands : output_sect_commands output_sect_cmd |
| | /* Empty */ |
| ; |
| |
| output_desc_epilog : opt_region opt_lma_region opt_phdr opt_fill |
| { |
| $$.m_pRegion = $1; |
| $$.m_pLMARegion = $2; |
| $$.m_pPhdrs = $3; |
| $$.m_pFillExp = $4; |
| } |
| ; |
| |
| /* Output Section Attributes */ |
| opt_vma_and_type : exp opt_type |
| { |
| $$.m_pVMA = m_ScriptFile.getCurrentRpnExpr(); |
| $$.m_Type = $2; |
| } |
| | opt_type |
| { |
| $$.m_pVMA = NULL; |
| $$.m_Type = $1; |
| } |
| ; |
| |
| opt_type : '(' type ')' |
| { $$ = $2; } |
| | '(' ')' |
| { $$ = OutputSectDesc::LOAD; } |
| | /* Empty */ |
| { $$ = OutputSectDesc::LOAD; } |
| ; |
| |
| type : NOLOAD |
| { $$ = OutputSectDesc::NOLOAD; } |
| | DSECT |
| { $$ = OutputSectDesc::DSECT; } |
| | COPY |
| { $$ = OutputSectDesc::COPY; } |
| | INFO |
| { $$ = OutputSectDesc::INFO; } |
| | OVERLAY |
| { $$ = OutputSectDesc::OVERLAY; } |
| ; |
| |
| opt_lma : AT '(' script_exp ')' |
| { $$ = $3; } |
| | /* Empty */ |
| { $$ = NULL; } |
| ; |
| |
| /* Forced Output Alignment */ |
| opt_align : ALIGN '(' script_exp ')' |
| { $$ = $3; } |
| | /* Empty */ |
| { $$ = NULL; } |
| ; |
| |
| /* Forced Input Alignment */ |
| opt_subalign : SUBALIGN '(' script_exp ')' |
| { $$ = $3; } |
| | /* Empty */ |
| { $$ = NULL; } |
| ; |
| |
| opt_constraint : ONLY_IF_RO |
| { $$ = OutputSectDesc::ONLY_IF_RO; } |
| | ONLY_IF_RW |
| { $$ = OutputSectDesc::ONLY_IF_RW; } |
| | /* Empty */ |
| { $$ = OutputSectDesc::NO_CONSTRAINT; } |
| ; |
| |
| opt_region : '>' string |
| { $$ = $2; } |
| | /* Empty */ |
| { $$ = NULL; } |
| ; |
| |
| opt_lma_region : AT '>' string |
| { $$ = $3; } |
| | /* Empty */ |
| { $$ = NULL; } |
| ; |
| |
| opt_phdr : { m_ScriptFile.createStringList(); } |
| phdrs |
| { $$ = m_ScriptFile.getCurrentStringList(); } |
| ; |
| |
| phdrs : phdrs ':' phdr |
| { m_ScriptFile.getCurrentStringList()->push_back($3); } |
| | /* Empty */ |
| ; |
| |
| phdr : string |
| { $$ = StrToken::create(*$1); } |
| ; |
| |
| opt_fill : '=' script_exp |
| { $$ = $2; } |
| | /* Empty */ |
| { $$ = NULL; } |
| ; |
| |
| /* |
| Each output-section-command may be one of the following: |
| |
| a symbol assignment (see Assignments) |
| an input section description (see Input Section) |
| data values to include directly (see Output Section Data) |
| a special output section keyword (see Output Section Keywords) |
| */ |
| output_sect_cmd : symbol_assignment |
| | input_sect_desc |
| | output_sect_data |
| | output_sect_keyword |
| | ';' |
| ; |
| |
| input_sect_desc : input_sect_spec |
| { m_ScriptFile.addInputSectDesc(InputSectDesc::NoKeep, $1); } |
| | KEEP '(' input_sect_spec ')' |
| { m_ScriptFile.addInputSectDesc(InputSectDesc::Keep, $3); } |
| ; |
| |
| input_sect_spec : string |
| { |
| $$.m_pWildcardFile = |
| WildcardPattern::create(*$1, WildcardPattern::SORT_NONE); |
| $$.m_pExcludeFiles = NULL; |
| $$.m_pWildcardSections = NULL; |
| } |
| | wildcard_file '(' opt_exclude_files input_sect_wildcard_patterns ')' |
| { |
| $$.m_pWildcardFile = $1; |
| $$.m_pExcludeFiles = $3; |
| $$.m_pWildcardSections = $4; |
| } |
| ; |
| |
| wildcard_file : wildcard_pattern |
| { $$ = WildcardPattern::create(*$1, WildcardPattern::SORT_NONE); } |
| | SORT_BY_NAME '(' wildcard_pattern ')' |
| { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_NAME); } |
| ; |
| |
| wildcard_pattern : string |
| { $$ = $1; } |
| | '*' |
| { $$ = &m_ScriptFile.createParserStr("*", 1); } |
| | '?' |
| { $$ = &m_ScriptFile.createParserStr("?", 1); } |
| ; |
| |
| opt_exclude_files : EXCLUDE_FILE '(' |
| { m_ScriptFile.createStringList(); } |
| exclude_files ')' |
| { $$ = m_ScriptFile.getCurrentStringList(); } |
| | /* Empty */ |
| { $$ = NULL; } |
| ; |
| |
| exclude_files : exclude_files wildcard_pattern |
| { |
| m_ScriptFile.getCurrentStringList()->push_back( |
| WildcardPattern::create(*$2, WildcardPattern::SORT_NONE)); |
| } |
| | wildcard_pattern |
| { |
| m_ScriptFile.getCurrentStringList()->push_back( |
| WildcardPattern::create(*$1, WildcardPattern::SORT_NONE)); |
| } |
| ; |
| |
| input_sect_wildcard_patterns : { m_ScriptFile.createStringList(); } |
| wildcard_sections |
| { $$ = m_ScriptFile.getCurrentStringList(); } |
| ; |
| |
| wildcard_sections : wildcard_sections wildcard_section |
| { |
| m_ScriptFile.getCurrentStringList()->push_back($2); |
| } |
| | wildcard_section |
| { |
| m_ScriptFile.getCurrentStringList()->push_back($1); |
| } |
| ; |
| |
| wildcard_section : wildcard_pattern |
| { $$ = WildcardPattern::create(*$1, WildcardPattern::SORT_NONE); } |
| | SORT_NONE '(' wildcard_pattern ')' |
| { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_NONE); } |
| | SORT_BY_NAME '(' wildcard_pattern ')' |
| { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_NAME); } |
| | SORT_BY_ALIGNMENT '(' wildcard_pattern ')' |
| { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_ALIGNMENT); } |
| | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_pattern ')' ')' |
| { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_NAME_ALIGNMENT); } |
| | SORT_BY_ALIGNMENT '('SORT_BY_NAME '(' wildcard_pattern ')' ')' |
| { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_ALIGNMENT_NAME); } |
| | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_pattern ')' ')' |
| { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_NAME); } |
| | SORT_BY_ALIGNMENT '(' SORT_BY_ALIGNMENT '(' wildcard_pattern ')' ')' |
| { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_ALIGNMENT); } |
| | SORT_BY_INIT_PRIORITY '(' wildcard_pattern ')' |
| { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_INIT_PRIORITY); } |
| ; |
| |
| output_sect_data : BYTE '(' script_exp ')' |
| | SHORT '(' script_exp ')' |
| | LONG '(' script_exp ')' |
| | QUAD '(' script_exp ')' |
| | SQUAD '(' script_exp ')' |
| ; |
| |
| output_sect_keyword : CREATE_OBJECT_SYMBOLS |
| | CONSTRUCTORS |
| | SORT_BY_NAME '(' CONSTRUCTORS ')' |
| ; |
| |
| symbol_assignment : symbol '=' script_exp ';' |
| { m_ScriptFile.addAssignment(*$1, *$3); } |
| | symbol ADD_ASSIGN exp ';' |
| | symbol SUB_ASSIGN exp ';' |
| | symbol MUL_ASSIGN exp ';' |
| | symbol DIV_ASSIGN exp ';' |
| | symbol AND_ASSIGN exp ';' |
| | symbol OR_ASSIGN exp ';' |
| | symbol LS_ASSIGN exp ';' |
| | symbol RS_ASSIGN exp ';' |
| | HIDDEN '(' symbol '=' script_exp ')' ';' |
| { |
| m_ScriptFile.addAssignment(*$3, *$5, |
| Assignment::HIDDEN); |
| } |
| | PROVIDE '(' symbol '=' script_exp ')' ';' |
| { |
| m_ScriptFile.addAssignment(*$3, *$5, |
| Assignment::PROVIDE); |
| } |
| | PROVIDE_HIDDEN '(' symbol '=' script_exp ')' ';' |
| { |
| m_ScriptFile.addAssignment(*$3, *$5, |
| Assignment::PROVIDE_HIDDEN); |
| } |
| ; |
| |
| script_exp : { |
| m_ScriptScanner.setLexState(ScriptFile::Expression); |
| m_ScriptFile.createRpnExpr(); |
| } |
| exp |
| { |
| m_ScriptScanner.popLexState(); |
| $$ = m_ScriptFile.getCurrentRpnExpr(); |
| } |
| ; |
| |
| exp : '(' exp ')' |
| { |
| $$ = $2; |
| } |
| | '+' exp %prec UNARY_PLUS |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::UNARY_PLUS>()); |
| $$ = $2 + 1; |
| } |
| | '-' exp %prec UNARY_MINUS |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::UNARY_MINUS>()); |
| $$ = $2 + 1; |
| } |
| | '!' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::LOGICAL_NOT>()); |
| $$ = $2 + 1; |
| } |
| | '~' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::BITWISE_NOT>()); |
| $$ = $2 + 1; |
| } |
| | exp '*' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::MUL>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp '/' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::DIV>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp '%' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::MOD>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp '+' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::ADD>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp '-' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::SUB>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp LSHIFT exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::LSHIFT>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp RSHIFT exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::RSHIFT>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp '<' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::LT>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp LE exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::LE>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp '>' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::GT>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp GE exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::GE>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp EQ exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::EQ>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp NE exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::NE>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp '&' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::BITWISE_AND>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp '^' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::BITWISE_XOR>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp '|' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::BITWISE_OR>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp LOGICAL_AND exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::LOGICAL_AND>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp LOGICAL_OR exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::LOGICAL_OR>()); |
| $$ = $1 + $3 + 1; |
| } |
| | exp '?' exp ':' exp |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::TERNARY_IF>()); |
| $$ = $1 + $3 + $5 + 1; |
| } |
| | ABSOLUTE '(' exp ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::ABSOLUTE>()); |
| $$ = $3 + 1; |
| } |
| | ADDR '(' string ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3)); |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::ADDR>()); |
| $$ = 2; |
| } |
| | ALIGN '(' exp ')' |
| { |
| RpnExpr::iterator pos = m_ScriptFile.getCurrentRpnExpr()->begin() + |
| m_ScriptFile.getCurrentRpnExpr()->size() - $3; |
| m_ScriptFile.getCurrentRpnExpr()->insert(pos, SymOperand::create(".")); |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::ALIGN>()); |
| $$ = $3 + 2; |
| } |
| | ALIGN '(' exp ',' exp ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::ALIGN>()); |
| $$ = $3 + $5 + 1; |
| } |
| | ALIGNOF '(' string ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3)); |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::ALIGNOF>()); |
| $$ = 2; |
| } |
| | BLOCK '(' exp ')' |
| { |
| RpnExpr::iterator pos = m_ScriptFile.getCurrentRpnExpr()->begin() + |
| m_ScriptFile.getCurrentRpnExpr()->size() - $3; |
| m_ScriptFile.getCurrentRpnExpr()->insert(pos, SymOperand::create(".")); |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::ALIGN>()); |
| $$ = $3 + 2; |
| } |
| | DATA_SEGMENT_ALIGN |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back(SymOperand::create(".")); |
| } |
| '(' exp ',' exp ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::DATA_SEGMENT_ALIGN>()); |
| $$ = $4 + $6 + 2; |
| } |
| | DATA_SEGMENT_END '(' exp ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::DATA_SEGMENT_END>()); |
| $$ = $3 + 1; |
| } |
| | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::DATA_SEGMENT_RELRO_END>()); |
| $$ = $3 + $5 + 1; |
| } |
| | DEFINED '(' symbol ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back(SymOperand::create(*$3)); |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::DEFINED>()); |
| $$ = 2; |
| } |
| | LENGTH '(' string ')' |
| { |
| /* TODO */ |
| } |
| | LOADADDR '(' string ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3)); |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::LOADADDR>()); |
| $$ = 2; |
| } |
| | MAX '(' exp ',' exp ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::MAX>()); |
| $$ = $3 + $5 + 1; |
| } |
| | MIN '(' exp ',' exp ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::MIN>()); |
| $$ = $3 + $5 + 1; |
| } |
| | NEXT '(' exp ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::NEXT>()); |
| $$ = $3 + 1; |
| } |
| | ORIGIN '(' string ')' |
| { |
| /* TODO */ |
| } |
| | SEGMENT_START '(' string |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3)); |
| } |
| ',' exp ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::SEGMENT_START>()); |
| $$ = $6 + 2; |
| } |
| | SIZEOF '(' string ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3)); |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::SIZEOF>()); |
| $$ = 2; |
| } |
| | SIZEOF_HEADERS |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::SIZEOF_HEADERS>()); |
| $$ = 1; |
| } |
| | CONSTANT '(' MAXPAGESIZE ')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::MAXPAGESIZE>()); |
| $$ = 1; |
| } |
| | CONSTANT '(' COMMONPAGESIZE')' |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back( |
| &Operator::create<Operator::COMMONPAGESIZE>()); |
| $$ = 1; |
| } |
| | INTEGER |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back(IntOperand::create($1)); |
| $$ = 1; |
| } |
| | symbol |
| { |
| m_ScriptFile.getCurrentRpnExpr()->push_back(SymOperand::create(*$1)); |
| $$ = 1; |
| } |
| ; |
| |
| symbol : STRING |
| { $$ = $1; } |
| ; |
| |
| string : STRING |
| { $$ = $1; } |
| | '"' STRING '"' |
| { $$ = $2; } |
| ; |
| |
| %% |
| |
| void mcld::ScriptParser::error(const mcld::ScriptParser::location_type& pLoc, |
| const std::string &pMsg) |
| { |
| position last = pLoc.end - 1; |
| std::string filename = "NaN"; |
| if (last.filename != NULL) |
| filename = *last.filename; |
| |
| mcld::error(diag::err_syntax_error) |
| << filename << last.line << last.column << pMsg; |
| } |
| |