* ldlang.c (entry_symbol): Make static.
[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                         config.map_filename = "-";
159                         }
160         |       ORDER ordernamelist
161         |       ENDWORD 
162         |       PUBLIC NAME '=' exp 
163                         { mri_public($2, $4); }
164         |       PUBLIC NAME ',' exp 
165                         { mri_public($2, $4); }
166         |       PUBLIC NAME  exp 
167                         { mri_public($2, $3); }
168         |       FORMAT NAME
169                         { mri_format($2); }
170         |       SECT NAME ',' exp 
171                         { mri_output_section($2, $4);}
172         |       SECT NAME  exp
173                         { mri_output_section($2, $3);}
174         |       SECT NAME '=' exp
175                         { mri_output_section($2, $4);}
176         |       ALIGN_K NAME '=' exp
177                         { mri_align($2,$4); }
178         |       ALIGNMOD NAME '=' exp
179                         { mri_alignmod($2,$4); }
180         |       ABSOLUTE mri_abs_name_list
181         |       LOAD     mri_load_name_list
182         |       NAMEWORD NAME 
183                         { mri_name($2); }   
184         |       ALIAS NAME ',' NAME
185                         { mri_alias($2,$4,0);}
186         |       ALIAS NAME ',' INT
187                         { mri_alias($2,0,(int) $4);}
188         |       BASE     exp
189                         { mri_base($2); }
190         |       TRUNCATE INT
191                 {  mri_truncate((unsigned int) $2); }
192         |
193         ;
194
195 ordernamelist:
196               ordernamelist ',' NAME         { mri_order($3); }
197         |     ordernamelist  NAME         { mri_order($2); }
198         |
199         ;
200
201 mri_load_name_list:
202                 NAME
203                         { mri_load($1); }
204         |       mri_load_name_list ',' NAME { mri_load($3); }
205         ;
206
207 mri_abs_name_list:
208                 NAME
209                         { mri_only_load($1); }
210         |       mri_abs_name_list ','  NAME
211                         { mri_only_load($3); }
212         ;
213
214 script_file:
215         {
216          ldlex_both();
217         }
218        ifile_list
219         {
220         ldlex_popstate();
221         }
222         ;
223
224
225 ifile_list:
226        ifile_list ifile_p1
227         |
228         ;
229
230
231
232 ifile_p1:
233                 memory
234         |       sections
235         |       startup
236         |       high_level_library
237         |       low_level_library
238         |       floating_point_support
239         |       statement_anywhere
240         |        ';'
241         |       TARGET_K '(' NAME ')'
242                 { lang_add_target($3); }
243         |       SEARCH_DIR '(' filename ')'
244                 { ldfile_add_library_path($3); }
245         |       OUTPUT '(' filename ')'
246                 { lang_add_output($3, 1); }
247         |       OUTPUT_FORMAT '(' NAME ')'
248                   { lang_add_output_format($3, 1); }
249         |       OUTPUT_ARCH '(' NAME ')'
250                   { ldfile_set_output_arch($3); }
251         |       FORCE_COMMON_ALLOCATION
252                 { command_line.force_common_definition = true ; }
253         |       INPUT '(' input_list ')'
254         |       MAP '(' filename ')'
255                 { lang_add_map($3); }
256         |       INCLUDE filename 
257                 { ldfile_open_command_file($2); } ifile_list END
258         ;
259
260 input_list:
261                 NAME
262                 { lang_add_input_file($1,lang_input_file_is_search_file_enum,
263                                  (char *)NULL); }
264         |       input_list ',' NAME
265                 { lang_add_input_file($3,lang_input_file_is_search_file_enum,
266                                  (char *)NULL); }
267         |       input_list NAME
268                 { lang_add_input_file($2,lang_input_file_is_search_file_enum,
269                                  (char *)NULL); }
270         ;
271
272 sections:
273                 SECTIONS '{' sec_or_group_p1 '}'
274         ;
275
276 sec_or_group_p1:
277                 sec_or_group_p1 section
278         |       sec_or_group_p1 statement_anywhere
279         |
280         ;
281
282 statement_anywhere:
283                 ENTRY '(' NAME ')'
284                 { lang_add_entry ($3, 0); }
285         |       assignment end
286         ;
287
288 file_NAME_list:
289                 NAME
290                         { lang_add_wild($1, current_file); }
291         |       file_NAME_list opt_comma NAME
292                         { lang_add_wild($3, current_file); }
293         ;
294
295 input_section_spec:
296                 NAME
297                 {
298                 lang_add_wild((char *)NULL, $1);
299                 }
300         |       '['
301                         {
302                         current_file = (char *)NULL;
303                         }
304                         file_NAME_list
305                 ']'
306         |       NAME
307                         {
308                         current_file =$1;
309                         }
310                 '(' file_NAME_list ')'
311         |       '*'
312                         {
313                         current_file = (char *)NULL;
314                         }
315                 '(' file_NAME_list ')'
316         ;
317
318 statement:
319                 assignment end
320         |       CREATE_OBJECT_SYMBOLS
321                 {
322                 lang_add_attribute(lang_object_symbols_statement_enum); 
323                 }
324         |       ';'
325         |       CONSTRUCTORS
326                 {
327                 
328                   lang_add_attribute(lang_constructors_statement_enum); 
329                 }
330         | input_section_spec
331         | length '(' exp ')'
332                         {
333                         lang_add_data((int) $1,$3);
334                         }
335   
336         | FILL '(' exp ')'
337                         {
338                           lang_add_fill
339                             (exp_get_value_int($3,
340                                                0,
341                                                "fill value",
342                                                lang_first_phase_enum));
343                         }
344         ;
345
346 statement_list:
347                 statement_list statement
348         |       statement
349         ;
350   
351 statement_list_opt:
352                 /* empty */
353         |       statement_list
354         ;
355
356 length:
357                 QUAD
358                         { $$ = $1; }
359         |       LONG
360                         { $$ = $1; }
361         |       SHORT
362                         { $$ = $1; }
363         |       BYTE
364                         { $$ = $1; }
365         ;
366
367 fill_opt:
368           '=' mustbe_exp
369                 {
370                   $$ =   exp_get_value_int($2,
371                                            0,
372                                            "fill value",
373                                            lang_first_phase_enum);
374                 }
375         |       { $$ = 0; }
376         ;
377
378                 
379
380 assign_op:
381                 PLUSEQ
382                         { $$ = '+'; }
383         |       MINUSEQ
384                         { $$ = '-'; }
385         |       MULTEQ
386                         { $$ = '*'; }
387         |       DIVEQ
388                         { $$ = '/'; }
389         |       LSHIFTEQ
390                         { $$ = LSHIFT; }
391         |       RSHIFTEQ
392                         { $$ = RSHIFT; }
393         |       ANDEQ
394                         { $$ = '&'; }
395         |       OREQ
396                         { $$ = '|'; }
397
398         ;
399
400 end:    ';' | ','
401         ;
402
403
404 assignment:
405                 NAME '=' mustbe_exp
406                 {
407                   lang_add_assignment(exp_assop($2,$1,$3));
408                 }
409         |       NAME assign_op mustbe_exp
410                 {
411                 
412 lang_add_assignment(exp_assop('=',$1,exp_binop($2,exp_nameop(NAME,$1),$3)));
413                 }
414                 
415         ;
416
417
418 opt_comma:
419                 ','     |       ;
420
421
422 memory:
423                 MEMORY '{' memory_spec memory_spec_list '}'
424         ;
425
426 memory_spec_list:
427                 memory_spec_list memory_spec
428         |       memory_spec_list ',' memory_spec
429         |
430         ;
431
432
433 memory_spec:            NAME
434                         { region = lang_memory_region_lookup($1); }
435                 attributes_opt ':'
436                 origin_spec opt_comma length_spec
437
438         ; origin_spec:
439         ORIGIN '=' mustbe_exp
440                 { region->current =
441                  region->origin =
442                  exp_get_vma($3, 0L,"origin", lang_first_phase_enum);
443 }
444         ; length_spec:
445              LENGTH '=' mustbe_exp
446                { region->length = exp_get_vma($3,
447                                                ~((bfd_vma)0),
448                                                "length",
449                                                lang_first_phase_enum);
450                 }
451         
452
453 attributes_opt:
454                   '(' NAME ')'
455                         {
456                         lang_set_flags(&region->flags, $2);
457                         }
458         |
459   
460         ;
461
462 startup:
463         STARTUP '(' filename ')'
464                 { lang_startup($3); }
465         ;
466
467 high_level_library:
468                 HLL '(' high_level_library_NAME_list ')'
469         |       HLL '(' ')'
470                         { ldemul_hll((char *)NULL); }
471         ;
472
473 high_level_library_NAME_list:
474                 high_level_library_NAME_list opt_comma filename
475                         { ldemul_hll($3); }
476         |       filename
477                         { ldemul_hll($1); }
478
479         ;
480
481 low_level_library:
482         SYSLIB '(' low_level_library_NAME_list ')'
483         ; low_level_library_NAME_list:
484                 low_level_library_NAME_list opt_comma filename
485                         { ldemul_syslib($3); }
486         |
487         ;
488
489 floating_point_support:
490                 FLOAT
491                         { lang_float(true); }
492         |       NOFLOAT
493                         { lang_float(false); }
494         ;
495                 
496
497 mustbe_exp:              { ldlex_expression(); }
498                 exp
499                          { ldlex_popstate(); $$=$2;}
500         ;
501
502 exp     :
503                 '-' exp %prec UNARY
504                         { $$ = exp_unop('-', $2); }
505         |       '(' exp ')'
506                         { $$ = $2; }
507         |       NEXT '(' exp ')' %prec UNARY
508                         { $$ = exp_unop((int) $1,$3); }
509         |       '!' exp %prec UNARY
510                         { $$ = exp_unop('!', $2); }
511         |       '+' exp %prec UNARY
512                         { $$ = $2; }
513         |       '~' exp %prec UNARY
514                         { $$ = exp_unop('~', $2);}
515
516         |       exp '*' exp
517                         { $$ = exp_binop('*', $1, $3); }
518         |       exp '/' exp
519                         { $$ = exp_binop('/', $1, $3); }
520         |       exp '%' exp
521                         { $$ = exp_binop('%', $1, $3); }
522         |       exp '+' exp
523                         { $$ = exp_binop('+', $1, $3); }
524         |       exp '-' exp
525                         { $$ = exp_binop('-' , $1, $3); }
526         |       exp LSHIFT exp
527                         { $$ = exp_binop(LSHIFT , $1, $3); }
528         |       exp RSHIFT exp
529                         { $$ = exp_binop(RSHIFT , $1, $3); }
530         |       exp EQ exp
531                         { $$ = exp_binop(EQ , $1, $3); }
532         |       exp NE exp
533                         { $$ = exp_binop(NE , $1, $3); }
534         |       exp LE exp
535                         { $$ = exp_binop(LE , $1, $3); }
536         |       exp GE exp
537                         { $$ = exp_binop(GE , $1, $3); }
538         |       exp '<' exp
539                         { $$ = exp_binop('<' , $1, $3); }
540         |       exp '>' exp
541                         { $$ = exp_binop('>' , $1, $3); }
542         |       exp '&' exp
543                         { $$ = exp_binop('&' , $1, $3); }
544         |       exp '^' exp
545                         { $$ = exp_binop('^' , $1, $3); }
546         |       exp '|' exp
547                         { $$ = exp_binop('|' , $1, $3); }
548         |       exp '?' exp ':' exp
549                         { $$ = exp_trinop('?' , $1, $3, $5); }
550         |       exp ANDAND exp
551                         { $$ = exp_binop(ANDAND , $1, $3); }
552         |       exp OROR exp
553                         { $$ = exp_binop(OROR , $1, $3); }
554         |       DEFINED '(' NAME ')'
555                         { $$ = exp_nameop(DEFINED, $3); }
556         |       INT
557                         { $$ = exp_intop($1); }
558         |       SIZEOF_HEADERS
559                         { $$ = exp_nameop(SIZEOF_HEADERS,0); }
560
561         |       SIZEOF '(' NAME ')'
562                         { $$ = exp_nameop(SIZEOF,$3); }
563         |       ADDR '(' NAME ')'
564                         { $$ = exp_nameop(ADDR,$3); }
565         |       ABSOLUTE '(' exp ')'
566                         { $$ = exp_unop(ABSOLUTE, $3); }
567         |       ALIGN_K '(' exp ')'
568                         { $$ = exp_unop(ALIGN_K,$3); }
569         |       NAME
570                         { $$ = exp_nameop(NAME,$1); }
571         ;
572
573
574 opt_at:
575                 AT '(' exp ')' { $$ = $3; }
576         |       { $$ = 0; }
577         ;
578
579 section:        NAME            { ldlex_expression(); }
580                 opt_exp_with_type 
581                 opt_at          { ldlex_popstate(); }
582                 '{'
583                         {
584                         lang_enter_output_section_statement($1,$3,typebits,0,0,0,$4);
585                         }
586                 statement_list_opt      
587                 '}' {ldlex_expression();} memspec_opt fill_opt
588                 {
589                   ldlex_popstate();
590                   lang_leave_output_section_statement($12, $11);
591                 }
592 opt_comma
593
594         ;
595
596 type:
597            NOLOAD  { typebits = SEC_NEVER_LOAD; }
598         |  DSECT   { typebits = 0; }
599         |  COPY    { typebits = 0; }
600         |  INFO    { typebits = 0; }
601         |  OVERLAY { typebits = 0; }
602         | { typebits = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; }
603         ;
604
605
606 opt_exp_with_type:
607                 exp ':'                 { $$ = $1; typebits =0;}
608         |       exp '(' type ')' ':'    { $$ = $1; }
609         |       ':'                     { $$= (etree_type *)NULL; typebits = 0; }
610         |       '(' type ')' ':'        { $$= (etree_type *)NULL;  }
611         ;
612
613 memspec_opt:
614                 '>' NAME
615                 { $$ = $2; }
616         |       { $$ = "*default*"; }
617         ;
618 %%
619 void
620 yyerror(arg) 
621      const char *arg;
622
623   if (error_index > 0 && error_index < ERROR_NAME_MAX)
624      einfo("%P%F: %S %s in %s\n", arg, error_names[error_index-1]);
625   else
626      einfo("%P%F: %S %s\n", arg);
627 }