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