• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
22using 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
35using 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%define parse.error verbose
48%define api.namespace {mcld}
49%define api.parser.class {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
208script_file : LINKER_SCRIPT
209              { m_ScriptScanner.setLexState(ScriptFile::LDScript); }
210              linker_script
211              { m_ScriptScanner.popLexState(); }
212            ;
213
214linker_script : linker_script script_command
215              | /* Empty */
216              ;
217
218script_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
231entry_command : ENTRY '(' STRING ')'
232                { m_ScriptFile.addEntryPoint(*$3); }
233              ;
234
235output_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
241group_command : GROUP '(' input_list ')'
242                { m_ScriptFile.addGroupCmd(*$3, m_GroupReader, m_LDConfig); }
243              ;
244
245input_command : INPUT '(' input_list ')'
246                {
247                  m_ScriptFile.addInputCmd(*$3, m_ObjectReader, m_ArchiveReader,
248                                           m_DynObjReader, m_LDConfig);
249                }
250              ;
251
252search_dir_command : SEARCH_DIR '(' STRING ')'
253                     { m_ScriptFile.addSearchDirCmd(*$3); }
254                   ;
255
256output_command : OUTPUT '(' STRING ')'
257                 { m_ScriptFile.addOutputCmd(*$3); }
258               ;
259
260output_arch_command : OUTPUT_ARCH '(' STRING ')'
261                      { m_ScriptFile.addOutputArchCmd(*$3); }
262                    ;
263
264assert_command : ASSERT '(' script_exp ',' string ')'
265                 { m_ScriptFile.addAssertCmd(*$3, *$5); }
266               ;
267
268input_list : { m_ScriptFile.createStringList(); }
269             inputs
270             { $$ = m_ScriptFile.getCurrentStringList(); }
271           ;
272
273inputs : 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
293input : 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*/
307sections_command : SECTIONS
308                   { m_ScriptFile.enterSectionsCmd(); }
309                   '{' sect_commands '}'
310                   { m_ScriptFile.leaveSectionsCmd(); }
311                 ;
312
313sect_commands : sect_commands sect_cmd
314              | /* Empty */
315              ;
316
317/*
318Each sections-command may of be one of the following:
319
320an ENTRY command (see Entry command)
321a symbol assignment (see Assignments)
322an output section description
323an overlay description
324*/
325sect_cmd : entry_command
326         | symbol_assignment
327         | output_sect_desc
328         ;
329
330/*
331The 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*/
344output_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
352output_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
371output_sect_commands : output_sect_commands output_sect_cmd
372                     | /* Empty */
373                     ;
374
375output_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 */
385opt_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
397opt_type : '(' type ')'
398           { $$ = $2; }
399         | '(' ')'
400           { $$ = OutputSectDesc::LOAD; }
401         | /* Empty */
402           { $$ = OutputSectDesc::LOAD; }
403         ;
404
405type : 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
417opt_lma : AT '(' script_exp ')'
418          { $$ = $3; }
419        | /* Empty */
420          { $$ = NULL; }
421        ;
422
423/* Forced Output Alignment */
424opt_align : ALIGN '(' script_exp ')'
425            { $$ = $3; }
426          | /* Empty */
427            { $$ = NULL; }
428          ;
429
430/* Forced Input Alignment */
431opt_subalign : SUBALIGN '(' script_exp ')'
432               { $$ = $3; }
433             | /* Empty */
434               { $$ = NULL; }
435             ;
436
437opt_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
445opt_region : '>' string
446             { $$ = $2; }
447           | /* Empty */
448             { $$ = NULL; }
449           ;
450
451opt_lma_region : AT '>' string
452                 { $$ = $3; }
453               | /* Empty */
454                 { $$ = NULL; }
455               ;
456
457opt_phdr : { m_ScriptFile.createStringList(); }
458           phdrs
459           { $$ = m_ScriptFile.getCurrentStringList(); }
460         ;
461
462phdrs : phdrs ':' phdr
463        { m_ScriptFile.getCurrentStringList()->push_back($3); }
464      | /* Empty */
465      ;
466
467phdr : string
468       { $$ = StrToken::create(*$1); }
469     ;
470
471opt_fill : '=' script_exp
472           { $$ = $2; }
473         | /* Empty */
474           { $$ = NULL; }
475         ;
476
477/*
478Each output-section-command may be one of the following:
479
480a symbol assignment (see Assignments)
481an input section description (see Input Section)
482data values to include directly (see Output Section Data)
483a special output section keyword (see Output Section Keywords)
484*/
485output_sect_cmd : symbol_assignment
486                | input_sect_desc
487                | output_sect_data
488                | output_sect_keyword
489                | ';'
490                ;
491
492input_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
498input_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
513wildcard_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
519wildcard_pattern : string
520                   { $$ = $1; }
521                 | '*'
522                   { $$ = &m_ScriptFile.createParserStr("*", 1); }
523                 | '?'
524                   { $$ = &m_ScriptFile.createParserStr("?", 1); }
525                 ;
526
527opt_exclude_files : EXCLUDE_FILE '('
528                    { m_ScriptFile.createStringList(); }
529                    exclude_files ')'
530                    { $$ = m_ScriptFile.getCurrentStringList(); }
531                  | /* Empty */
532                    { $$ = NULL; }
533                  ;
534
535exclude_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
547input_sect_wildcard_patterns : { m_ScriptFile.createStringList(); }
548                               wildcard_sections
549                               { $$ = m_ScriptFile.getCurrentStringList(); }
550                             ;
551
552wildcard_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
562wildcard_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
582output_sect_data : BYTE  '(' script_exp ')'
583                 | SHORT '(' script_exp ')'
584                 | LONG  '(' script_exp ')'
585                 | QUAD  '(' script_exp ')'
586                 | SQUAD '(' script_exp ')'
587                 ;
588
589output_sect_keyword : CREATE_OBJECT_SYMBOLS
590                    | CONSTRUCTORS
591                    | SORT_BY_NAME '(' CONSTRUCTORS ')'
592                    ;
593
594symbol_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
621script_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
632exp : '(' 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
927symbol : STRING
928         { $$ = $1; }
929       ;
930
931string : STRING
932         { $$ = $1; }
933       | '"' STRING '"'
934         { $$ = $2; }
935       ;
936
937%%
938
939void 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