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