* ldgram.y (section): Reverse the order of memspec_opt and
[platform/upstream/binutils.git] / ld / ldgram.y
1 /* A YACC grammer to parse a superset of the AT&T linker scripting languaue.
2    Copyright (C) 1991, 1993 Free Software Foundation, Inc.
3    Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
4
5 This file is part of GNU ld.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 %{
22 /*
23
24  */
25
26 #define DONTDECLARE_MALLOC
27
28 #include "bfd.h"
29 #include "sysdep.h"
30 #include "bfdlink.h"
31 #include "ld.h"    
32 #include "ldexp.h"
33 #include "ldver.h"
34 #include "ldlang.h"
35 #include "ldemul.h"
36 #include "ldfile.h"
37 #include "ldmisc.h"
38 #include "ldmain.h"
39 #include "mri.h"
40 #include "ldlex.h"
41
42 #define YYDEBUG 1
43
44 static int typebits;
45
46 lang_memory_region_type *region;
47
48
49 char *current_file;
50 boolean ldgram_want_filename = true;
51 boolean had_script = false;
52 boolean force_make_executable = false;
53
54 boolean ldgram_in_script = false;
55 boolean ldgram_had_equals = false;
56
57
58 #define ERROR_NAME_MAX 20
59 static char *error_names[ERROR_NAME_MAX];
60 static int error_index;
61 #define PUSH_ERROR(x) if (error_index < ERROR_NAME_MAX) error_names[error_index] = x; error_index++;
62 #define POP_ERROR()   error_index--;
63 %}
64 %union {
65   bfd_vma integer;
66   char *name;
67   int token;
68   union etree_union *etree;
69 }
70
71 %type <etree> exp  opt_exp_with_type  mustbe_exp opt_at
72 %type <integer> fill_opt
73 %type <name> memspec_opt
74 %token <integer> INT  
75 %token <name> NAME
76 %type  <integer> length
77
78 %right <token> PLUSEQ MINUSEQ MULTEQ DIVEQ  '=' LSHIFTEQ RSHIFTEQ   ANDEQ OREQ 
79 %right <token> '?' ':'
80 %left <token> OROR
81 %left <token>  ANDAND
82 %left <token> '|'
83 %left <token>  '^'
84 %left  <token> '&'
85 %left <token>  EQ NE
86 %left  <token> '<' '>' LE GE
87 %left  <token> LSHIFT RSHIFT
88
89 %left  <token> '+' '-'
90 %left  <token> '*' '/' '%'
91
92 %right UNARY
93 %token END 
94 %left <token> '('
95 %token <token> ALIGN_K BLOCK QUAD LONG SHORT BYTE
96 %token SECTIONS
97 %token '{' '}'
98 %token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
99 %token SIZEOF_HEADERS
100 %token INCLUDE
101 %token MEMORY DEFSYMEND
102 %token NOLOAD DSECT COPY INFO OVERLAY
103 %token NAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY
104 %token <integer> SIZEOF NEXT ADDR
105 %token STARTUP HLL SYSLIB FLOAT NOFLOAT
106 %token ORIGIN FILL
107 %token LENGTH CREATE_OBJECT_SYMBOLS INPUT OUTPUT CONSTRUCTORS
108 %token ALIGNMOD AT
109 %type <token> assign_op 
110 %type <name>  filename
111 %token CHIP LIST SECT ABSOLUTE  LOAD NEWLINE ENDWORD ORDER NAMEWORD
112 %token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
113 %token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM
114
115 %%
116
117 file:   
118                 INPUT_SCRIPT script_file
119         |       INPUT_MRI_SCRIPT mri_script_file
120         |       INPUT_DEFSYM defsym_expr
121         ;
122
123
124 filename:  NAME;
125
126
127 defsym_expr:
128                 { ldlex_defsym(); }
129                 NAME '=' exp
130                 {
131                   ldlex_popstate();
132                   lang_add_assignment(exp_assop($3,$2,$4));
133                 }
134
135 /* SYNTAX WITHIN AN MRI SCRIPT FILE */  
136 mri_script_file:
137                 {       ldlex_mri_script();
138                         PUSH_ERROR("MRI style script");
139                 }
140              mri_script_lines
141                 {       ldlex_popstate(); 
142                         POP_ERROR();
143                 }
144         ;
145
146 mri_script_lines:
147                 mri_script_lines mri_script_command NEWLINE
148           |
149         ;
150
151 mri_script_command:
152                 CHIP  exp 
153         |       CHIP  exp ',' exp
154         |       NAME    {
155                         einfo("%P%F: unrecognised keyword in MRI style script '%s'\n",$1);
156                         }
157         |       LIST    {
158                         write_map = true;
159                         config.map_filename = "-";
160                         }
161         |       ORDER ordernamelist
162         |       ENDWORD 
163         |       PUBLIC NAME '=' exp 
164                         { mri_public($2, $4); }
165         |       PUBLIC NAME ',' exp 
166                         { mri_public($2, $4); }
167         |       PUBLIC NAME  exp 
168                         { mri_public($2, $3); }
169         |       FORMAT NAME
170                         { mri_format($2); }
171         |       SECT NAME ',' exp 
172                         { mri_output_section($2, $4);}
173         |       SECT NAME  exp
174                         { mri_output_section($2, $3);}
175         |       SECT NAME '=' exp
176                         { mri_output_section($2, $4);}
177         |       ALIGN_K NAME '=' exp
178                         { mri_align($2,$4); }
179         |       ALIGNMOD NAME '=' exp
180                         { mri_alignmod($2,$4); }
181         |       ABSOLUTE mri_abs_name_list
182         |       LOAD     mri_load_name_list
183         |       NAMEWORD NAME 
184                         { mri_name($2); }   
185         |       ALIAS NAME ',' NAME
186                         { mri_alias($2,$4,0);}
187         |       ALIAS NAME ',' INT
188                         { mri_alias($2,0,(int) $4);}
189         |       BASE     exp
190                         { mri_base($2); }
191         |       TRUNCATE INT
192                 {  mri_truncate((unsigned int) $2); }
193         |
194         ;
195
196 ordernamelist:
197               ordernamelist ',' NAME         { mri_order($3); }
198         |     ordernamelist  NAME         { mri_order($2); }
199         |
200         ;
201
202 mri_load_name_list:
203                 NAME
204                         { mri_load($1); }
205         |       mri_load_name_list ',' NAME { mri_load($3); }
206         ;
207
208 mri_abs_name_list:
209                 NAME
210                         { mri_only_load($1); }
211         |       mri_abs_name_list ','  NAME
212                         { mri_only_load($3); }
213         ;
214
215 script_file:
216         {
217          ldlex_both();
218         }
219        ifile_list
220         {
221         ldlex_popstate();
222         }
223         ;
224
225
226 ifile_list:
227        ifile_list ifile_p1
228         |
229         ;
230
231
232
233 ifile_p1:
234                 memory
235         |       sections
236         |       startup
237         |       high_level_library
238         |       low_level_library
239         |       floating_point_support
240         |       statement_anywhere
241         |        ';'
242         |       TARGET_K '(' NAME ')'
243                 { lang_add_target($3); }
244         |       SEARCH_DIR '(' filename ')'
245                 { ldfile_add_library_path($3); }
246         |       OUTPUT '(' filename ')'
247                 { lang_add_output($3, 1); }
248         |       OUTPUT_FORMAT '(' NAME ')'
249                   { lang_add_output_format($3, 1); }
250         |       OUTPUT_ARCH '(' NAME ')'
251                   { ldfile_set_output_arch($3); }
252         |       FORCE_COMMON_ALLOCATION
253                 { command_line.force_common_definition = true ; }
254         |       INPUT '(' input_list ')'
255         |       MAP '(' filename ')'
256                 { lang_add_map($3); }
257         |       INCLUDE filename 
258                 { ldfile_open_command_file($2); } ifile_list END
259         ;
260
261 input_list:
262                 NAME
263                 { lang_add_input_file($1,lang_input_file_is_search_file_enum,
264                                  (char *)NULL); }
265         |       input_list ',' NAME
266                 { lang_add_input_file($3,lang_input_file_is_search_file_enum,
267                                  (char *)NULL); }
268         |       input_list NAME
269                 { lang_add_input_file($2,lang_input_file_is_search_file_enum,
270                                  (char *)NULL); }
271         ;
272
273 sections:
274                 SECTIONS '{' sec_or_group_p1 '}'
275         ;
276
277 sec_or_group_p1:
278                 sec_or_group_p1 section
279         |       sec_or_group_p1 statement_anywhere
280         |
281         ;
282
283 statement_anywhere:
284                 ENTRY '(' NAME ')'
285                 { lang_add_entry($3); }
286         |       assignment end
287         ;
288
289 file_NAME_list:
290                 NAME
291                         { lang_add_wild($1, current_file); }
292         |       file_NAME_list opt_comma NAME
293                         { lang_add_wild($3, current_file); }
294         ;
295
296 input_section_spec:
297                 NAME
298                 {
299                 lang_add_wild((char *)NULL, $1);
300                 }
301         |       '['
302                         {
303                         current_file = (char *)NULL;
304                         }
305                         file_NAME_list
306                 ']'
307         |       NAME
308                         {
309                         current_file =$1;
310                         }
311                 '(' file_NAME_list ')'
312         |       '*'
313                         {
314                         current_file = (char *)NULL;
315                         }
316                 '(' file_NAME_list ')'
317         ;
318
319 statement:
320                 assignment end
321         |       CREATE_OBJECT_SYMBOLS
322                 {
323                 lang_add_attribute(lang_object_symbols_statement_enum); 
324                 }
325         |       ';'
326         |       CONSTRUCTORS
327                 {
328                 
329                   lang_add_attribute(lang_constructors_statement_enum); 
330                 }
331         | input_section_spec
332         | length '(' exp ')'
333                         {
334                         lang_add_data((int) $1,$3);
335                         }
336   
337         | FILL '(' exp ')'
338                         {
339                           lang_add_fill
340                             (exp_get_value_int($3,
341                                                0,
342                                                "fill value",
343                                                lang_first_phase_enum));
344                         }
345         ;
346
347 statement_list:
348                 statement_list statement
349         |       statement
350         ;
351   
352 statement_list_opt:
353                 /* empty */
354         |       statement_list
355         ;
356
357 length:
358                 QUAD
359                         { $$ = $1; }
360         |       LONG
361                         { $$ = $1; }
362         |       SHORT
363                         { $$ = $1; }
364         |       BYTE
365                         { $$ = $1; }
366         ;
367
368 fill_opt:
369           '=' mustbe_exp
370                 {
371                   $$ =   exp_get_value_int($2,
372                                            0,
373                                            "fill value",
374                                            lang_first_phase_enum);
375                 }
376         |       { $$ = 0; }
377         ;
378
379                 
380
381 assign_op:
382                 PLUSEQ
383                         { $$ = '+'; }
384         |       MINUSEQ
385                         { $$ = '-'; }
386         |       MULTEQ
387                         { $$ = '*'; }
388         |       DIVEQ
389                         { $$ = '/'; }
390         |       LSHIFTEQ
391                         { $$ = LSHIFT; }
392         |       RSHIFTEQ
393                         { $$ = RSHIFT; }
394         |       ANDEQ
395                         { $$ = '&'; }
396         |       OREQ
397                         { $$ = '|'; }
398
399         ;
400
401 end:    ';' | ','
402         ;
403
404
405 assignment:
406                 NAME '=' mustbe_exp
407                 {
408                   lang_add_assignment(exp_assop($2,$1,$3));
409                 }
410         |       NAME assign_op mustbe_exp
411                 {
412                 
413 lang_add_assignment(exp_assop('=',$1,exp_binop($2,exp_nameop(NAME,$1),$3)));
414                 }
415                 
416         ;
417
418
419 opt_comma:
420                 ','     |       ;
421
422
423 memory:
424                 MEMORY '{' memory_spec memory_spec_list '}'
425         ;
426
427 memory_spec_list:
428                 memory_spec_list memory_spec
429         |       memory_spec_list ',' memory_spec
430         |
431         ;
432
433
434 memory_spec:            NAME
435                         { region = lang_memory_region_lookup($1); }
436                 attributes_opt ':'
437                 origin_spec opt_comma length_spec
438
439         ; origin_spec:
440         ORIGIN '=' mustbe_exp
441                 { region->current =
442                  region->origin =
443                  exp_get_vma($3, 0L,"origin", lang_first_phase_enum);
444 }
445         ; length_spec:
446              LENGTH '=' mustbe_exp
447                { region->length = exp_get_vma($3,
448                                                ~((bfd_vma)0),
449                                                "length",
450                                                lang_first_phase_enum);
451                 }
452         
453
454 attributes_opt:
455                   '(' NAME ')'
456                         {
457                         lang_set_flags(&region->flags, $2);
458                         }
459         |
460   
461         ;
462
463 startup:
464         STARTUP '(' filename ')'
465                 { lang_startup($3); }
466         ;
467
468 high_level_library:
469                 HLL '(' high_level_library_NAME_list ')'
470         |       HLL '(' ')'
471                         { ldemul_hll((char *)NULL); }
472         ;
473
474 high_level_library_NAME_list:
475                 high_level_library_NAME_list opt_comma filename
476                         { ldemul_hll($3); }
477         |       filename
478                         { ldemul_hll($1); }
479
480         ;
481
482 low_level_library:
483         SYSLIB '(' low_level_library_NAME_list ')'
484         ; low_level_library_NAME_list:
485                 low_level_library_NAME_list opt_comma filename
486                         { ldemul_syslib($3); }
487         |
488         ;
489
490 floating_point_support:
491                 FLOAT
492                         { lang_float(true); }
493         |       NOFLOAT
494                         { lang_float(false); }
495         ;
496                 
497
498 mustbe_exp:              { ldlex_expression(); }
499                 exp
500                          { ldlex_popstate(); $$=$2;}
501         ;
502
503 exp     :
504                 '-' exp %prec UNARY
505                         { $$ = exp_unop('-', $2); }
506         |       '(' exp ')'
507                         { $$ = $2; }
508         |       NEXT '(' exp ')' %prec UNARY
509                         { $$ = exp_unop((int) $1,$3); }
510         |       '!' exp %prec UNARY
511                         { $$ = exp_unop('!', $2); }
512         |       '+' exp %prec UNARY
513                         { $$ = $2; }
514         |       '~' exp %prec UNARY
515                         { $$ = exp_unop('~', $2);}
516
517         |       exp '*' exp
518                         { $$ = exp_binop('*', $1, $3); }
519         |       exp '/' exp
520                         { $$ = exp_binop('/', $1, $3); }
521         |       exp '%' exp
522                         { $$ = exp_binop('%', $1, $3); }
523         |       exp '+' exp
524                         { $$ = exp_binop('+', $1, $3); }
525         |       exp '-' exp
526                         { $$ = exp_binop('-' , $1, $3); }
527         |       exp LSHIFT exp
528                         { $$ = exp_binop(LSHIFT , $1, $3); }
529         |       exp RSHIFT exp
530                         { $$ = exp_binop(RSHIFT , $1, $3); }
531         |       exp EQ exp
532                         { $$ = exp_binop(EQ , $1, $3); }
533         |       exp NE exp
534                         { $$ = exp_binop(NE , $1, $3); }
535         |       exp LE exp
536                         { $$ = exp_binop(LE , $1, $3); }
537         |       exp GE exp
538                         { $$ = exp_binop(GE , $1, $3); }
539         |       exp '<' exp
540                         { $$ = exp_binop('<' , $1, $3); }
541         |       exp '>' exp
542                         { $$ = exp_binop('>' , $1, $3); }
543         |       exp '&' exp
544                         { $$ = exp_binop('&' , $1, $3); }
545         |       exp '^' exp
546                         { $$ = exp_binop('^' , $1, $3); }
547         |       exp '|' exp
548                         { $$ = exp_binop('|' , $1, $3); }
549         |       exp '?' exp ':' exp
550                         { $$ = exp_trinop('?' , $1, $3, $5); }
551         |       exp ANDAND exp
552                         { $$ = exp_binop(ANDAND , $1, $3); }
553         |       exp OROR exp
554                         { $$ = exp_binop(OROR , $1, $3); }
555         |       DEFINED '(' NAME ')'
556                         { $$ = exp_nameop(DEFINED, $3); }
557         |       INT
558                         { $$ = exp_intop($1); }
559         |       SIZEOF_HEADERS
560                         { $$ = exp_nameop(SIZEOF_HEADERS,0); }
561
562         |       SIZEOF '(' NAME ')'
563                         { $$ = exp_nameop(SIZEOF,$3); }
564         |       ADDR '(' NAME ')'
565                         { $$ = exp_nameop(ADDR,$3); }
566         |       ABSOLUTE '(' exp ')'
567                         { $$ = exp_unop(ABSOLUTE, $3); }
568         |       ALIGN_K '(' exp ')'
569                         { $$ = exp_unop(ALIGN_K,$3); }
570         |       NAME
571                         { $$ = exp_nameop(NAME,$1); }
572         ;
573
574
575 opt_at:
576                 AT '(' exp ')' { $$ = $3; }
577         |       { $$ = 0; }
578         ;
579
580 section:        NAME            { ldlex_expression(); }
581                 opt_exp_with_type 
582                 opt_at          { ldlex_popstate(); }
583                 '{'
584                         {
585                         lang_enter_output_section_statement($1,$3,typebits,0,0,0,$4);
586                         }
587                 statement_list_opt      
588                 '}' {ldlex_expression();} memspec_opt fill_opt
589                 {
590                   ldlex_popstate();
591                   lang_leave_output_section_statement($12, $11);
592                 }
593 opt_comma
594
595         ;
596
597 type:
598            NOLOAD  { typebits = SEC_NEVER_LOAD; }
599         |  DSECT   { typebits = 0; }
600         |  COPY    { typebits = 0; }
601         |  INFO    { typebits = 0; }
602         |  OVERLAY { typebits = 0; }
603         | { typebits = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; }
604         ;
605
606
607 opt_exp_with_type:
608                 exp ':'                 { $$ = $1; typebits =0;}
609         |       exp '(' type ')' ':'    { $$ = $1; }
610         |       ':'                     { $$= (etree_type *)NULL; typebits = 0; }
611         |       '(' type ')' ':'        { $$= (etree_type *)NULL;  }
612         ;
613
614 memspec_opt:
615                 '>' NAME
616                 { $$ = $2; }
617         |       { $$ = "*default*"; }
618         ;
619 %%
620 void
621 yyerror(arg) 
622      const char *arg;
623
624   if (error_index > 0 && error_index < ERROR_NAME_MAX)
625      einfo("%P%F: %S %s in %s\n", arg, error_names[error_index-1]);
626   else
627      einfo("%P%F: %S %s\n", arg);
628 }