Home | History | Annotate | Download | only in Script
      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