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