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