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 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