ldgram.y revision 60484
169408Sache/* A YACC grammer to parse a superset of the AT&T linker scripting languaue.
269408Sache   Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000
3100616Smp   Free Software Foundation, Inc.
4231990Smp   Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
5195609Smp
6100616SmpThis file is part of GNU ld.
7231990Smp
8100616SmpThis program is free software; you can redistribute it and/or modify
969408Sacheit under the terms of the GNU General Public License as published by
1069408Sachethe Free Software Foundation; either version 2 of the License, or
1169408Sache(at your option) any later version.
1269408Sache
1369408SacheThis program is distributed in the hope that it will be useful,
1469408Sachebut WITHOUT ANY WARRANTY; without even the implied warranty of
1569408SacheMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1669408SacheGNU General Public License for more details.
1769408Sache
1869408SacheYou should have received a copy of the GNU General Public License
1969408Sachealong with this program; if not, write to the Free Software
2069408SacheFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21195609Smp
22195609Smp%{
2369408Sache/*
2469408Sache
2569408Sache */
2669408Sache
2769408Sache#define DONTDECLARE_MALLOC
2869408Sache
29195609Smp#include "bfd.h"
30231990Smp#include "sysdep.h"
31231990Smp#include "bfdlink.h"
32231990Smp#include "ld.h"
3369408Sache#include "ldexp.h"
3469408Sache#include "ldver.h"
3569408Sache#include "ldlang.h"
3669408Sache#include "ldemul.h"
3769408Sache#include "ldfile.h"
38231990Smp#include "ldmisc.h"
39231990Smp#include "ldmain.h"
4069408Sache#include "mri.h"
41100616Smp#include "ldctor.h"
42100616Smp#include "ldlex.h"
43100616Smp
44100616Smp#ifndef YYDEBUG
45100616Smp#define YYDEBUG 1
46100616Smp#endif
47100616Smp
48100616Smpstatic enum section_type sectype;
49100616Smp
50100616Smplang_memory_region_type *region;
51100616Smp
52100616Smpstruct wildcard_spec current_file;
53100616Smpboolean ldgram_want_filename = true;
54100616Smpboolean had_script = false;
55100616Smpboolean force_make_executable = false;
56100616Smp
57100616Smpboolean ldgram_in_script = false;
58100616Smpboolean ldgram_had_equals = false;
59231990Smpboolean ldgram_had_keep = false;
60231990Smpchar *ldgram_vers_current_lang = NULL;
61231990Smp
62100616Smp#define ERROR_NAME_MAX 20
63100616Smpstatic char *error_names[ERROR_NAME_MAX];
64100616Smpstatic int error_index;
65100616Smp#define PUSH_ERROR(x) if (error_index < ERROR_NAME_MAX) error_names[error_index] = x; error_index++;
66100616Smp#define POP_ERROR()   error_index--;
67100616Smp%}
68100616Smp%union {
69100616Smp  bfd_vma integer;
70100616Smp  char *name;
71100616Smp  const char *cname;
72100616Smp  struct wildcard_spec wildcard;
73195609Smp  struct name_list *name_list;
74100616Smp  int token;
75195609Smp  union etree_union *etree;
76100616Smp  struct phdr_info
77195609Smp    {
78100616Smp      boolean filehdr;
79100616Smp      boolean phdrs;
80100616Smp      union etree_union *at;
81100616Smp      union etree_union *flags;
82100616Smp    } phdr;
83100616Smp  struct lang_nocrossref *nocrossref;
84100616Smp  struct lang_output_section_phdr_list *section_phdr;
85100616Smp  struct bfd_elf_version_deps *deflist;
86100616Smp  struct bfd_elf_version_expr *versyms;
87100616Smp  struct bfd_elf_version_tree *versnode;
88100616Smp}
89100616Smp
90100616Smp%type <etree> exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val
91100616Smp%type <etree> opt_exp_without_type
92100616Smp%type <integer> fill_opt
9383098Smp%type <name_list> exclude_name_list
9483098Smp%type <name> memspec_opt casesymlist
95100616Smp%type <name> memspec_at_opt
9683098Smp%type <cname> wildcard_name
97100616Smp%type <wildcard> wildcard_spec
98100616Smp%token <integer> INT
99100616Smp%token <name> NAME LNAME
100100616Smp%type <integer> length
101100616Smp%type <phdr> phdr_qualifiers
102100616Smp%type <nocrossref> nocrossref_list
103100616Smp%type <section_phdr> phdr_opt
104100616Smp%type <integer> opt_nocrossrefs
105195609Smp
106100616Smp%right <token> PLUSEQ MINUSEQ MULTEQ DIVEQ  '=' LSHIFTEQ RSHIFTEQ   ANDEQ OREQ
107195609Smp%right <token> '?' ':'
108195609Smp%left <token> OROR
109195609Smp%left <token>  ANDAND
110195609Smp%left <token> '|'
111195609Smp%left <token>  '^'
112195609Smp%left  <token> '&'
113195609Smp%left <token>  EQ NE
114195609Smp%left  <token> '<' '>' LE GE
115195609Smp%left  <token> LSHIFT RSHIFT
116195609Smp
117100616Smp%left  <token> '+' '-'
118100616Smp%left  <token> '*' '/' '%'
119100616Smp
120195609Smp%right UNARY
121100616Smp%token END
122100616Smp%left <token> '('
123100616Smp%token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE
124100616Smp%token SECTIONS PHDRS SORT
125100616Smp%token '{' '}'
126100616Smp%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
127100616Smp%token SIZEOF_HEADERS
128100616Smp%token INCLUDE
129100616Smp%token MEMORY DEFSYMEND
130195609Smp%token NOLOAD DSECT COPY INFO OVERLAY
131100616Smp%token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY
13269408Sache%token <integer> NEXT
133100616Smp%token SIZEOF ADDR LOADADDR MAX_K MIN_K
13469408Sache%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS
13569408Sache%token ORIGIN FILL
13669408Sache%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
13769408Sache%token ALIGNMOD AT PROVIDE
13869408Sache%type <token> assign_op atype attributes_opt
13969408Sache%type <name>  filename
140100616Smp%token CHIP LIST SECT ABSOLUTE  LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
14169408Sache%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
14269408Sache%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
14369408Sache%token <name> VERS_TAG VERS_IDENTIFIER
14469408Sache%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
14569408Sache%token KEEP
146100616Smp%token EXCLUDE_FILE
147100616Smp%type <versyms> vers_defns
148100616Smp%type <versnode> vers_tag
149100616Smp%type <deflist> verdep
150100616Smp
151100616Smp%%
152100616Smp
153100616Smpfile:
154100616Smp		INPUT_SCRIPT script_file
155100616Smp	|	INPUT_MRI_SCRIPT mri_script_file
156100616Smp	|	INPUT_VERSION_SCRIPT version_script_file
157100616Smp	|	INPUT_DEFSYM defsym_expr
158100616Smp	;
159100616Smp
160100616Smp
161100616Smpfilename:  NAME;
162100616Smp
163100616Smp
164100616Smpdefsym_expr:
165195609Smp		{ ldlex_defsym(); }
166100616Smp		NAME '=' exp
167100616Smp		{
168100616Smp		  ldlex_popstate();
169100616Smp		  lang_add_assignment(exp_assop($3,$2,$4));
170100616Smp		}
171100616Smp
172100616Smp/* SYNTAX WITHIN AN MRI SCRIPT FILE */
173100616Smpmri_script_file:
174195609Smp		{
175100616Smp		  ldlex_mri_script ();
176100616Smp		  PUSH_ERROR (_("MRI style script"));
177100616Smp		}
178100616Smp	     mri_script_lines
179100616Smp		{
180100616Smp		  ldlex_popstate ();
181100616Smp		  mri_draw_tree ();
182100616Smp		  POP_ERROR ();
183100616Smp		}
184100616Smp	;
185100616Smp
186100616Smpmri_script_lines:
187100616Smp		mri_script_lines mri_script_command NEWLINE
188195609Smp          |
189195609Smp	;
190195609Smp
191195609Smpmri_script_command:
192195609Smp		CHIP  exp
193195609Smp	|	CHIP  exp ',' exp
194195609Smp	|	NAME 	{
195195609Smp			einfo(_("%P%F: unrecognised keyword in MRI style script '%s'\n"),$1);
196195609Smp			}
197195609Smp	|	LIST  	{
198195609Smp			config.map_filename = "-";
199195609Smp			}
200100616Smp        |       ORDER ordernamelist
201100616Smp	|       ENDWORD
202100616Smp        |       PUBLIC NAME '=' exp
203100616Smp 			{ mri_public($2, $4); }
204195609Smp        |       PUBLIC NAME ',' exp
205100616Smp 			{ mri_public($2, $4); }
206195609Smp        |       PUBLIC NAME  exp
207195609Smp 			{ mri_public($2, $3); }
208195609Smp	| 	FORMAT NAME
209195609Smp			{ mri_format($2); }
210195609Smp	|	SECT NAME ',' exp
211195609Smp			{ mri_output_section($2, $4);}
212195609Smp	|	SECT NAME  exp
213195609Smp			{ mri_output_section($2, $3);}
214195609Smp	|	SECT NAME '=' exp
215195609Smp			{ mri_output_section($2, $4);}
216195609Smp	|	ALIGN_K NAME '=' exp
217195609Smp			{ mri_align($2,$4); }
218195609Smp	|	ALIGN_K NAME ',' exp
219195609Smp			{ mri_align($2,$4); }
220195609Smp	|	ALIGNMOD NAME '=' exp
22169408Sache			{ mri_alignmod($2,$4); }
222195609Smp	|	ALIGNMOD NAME ',' exp
223195609Smp			{ mri_alignmod($2,$4); }
22469408Sache	|	ABSOLUTE mri_abs_name_list
225195609Smp	|	LOAD	 mri_load_name_list
226195609Smp	|       NAMEWORD NAME
227195609Smp			{ mri_name($2); }
228195609Smp	|	ALIAS NAME ',' NAME
229195609Smp			{ mri_alias($2,$4,0);}
230195609Smp	|	ALIAS NAME ',' INT
231195609Smp			{ mri_alias($2,0,(int) $4);}
232195609Smp	|	BASE     exp
233195609Smp			{ mri_base($2); }
234195609Smp        |       TRUNCATE INT
235195609Smp		{  mri_truncate((unsigned int) $2); }
236195609Smp	|	CASE casesymlist
237195609Smp	|	EXTERN extern_name_list
238195609Smp	|	INCLUDE filename
239195609Smp		{ ldfile_open_command_file ($2); } mri_script_lines END
240195609Smp	|	START NAME
241195609Smp		{ lang_add_entry ($2, false); }
242195609Smp        |
243195609Smp	;
244195609Smp
245195609Smpordernamelist:
246195609Smp	      ordernamelist ',' NAME         { mri_order($3); }
247195609Smp	|     ordernamelist  NAME         { mri_order($2); }
248195609Smp      	|
249195609Smp	;
250195609Smp
251195609Smpmri_load_name_list:
252195609Smp		NAME
253195609Smp			{ mri_load($1); }
254195609Smp	|	mri_load_name_list ',' NAME { mri_load($3); }
255195609Smp	;
256195609Smp
257195609Smpmri_abs_name_list:
258195609Smp 		NAME
259195609Smp 			{ mri_only_load($1); }
260195609Smp	|	mri_abs_name_list ','  NAME
261195609Smp 			{ mri_only_load($3); }
262195609Smp	;
263195609Smp
264195609Smpcasesymlist:
265195609Smp	  /* empty */ { $$ = NULL; }
266195609Smp	| NAME
267195609Smp	| casesymlist ',' NAME
26869408Sache	;
26969408Sache
27069408Sacheextern_name_list:
27169408Sache	  NAME
272195609Smp			{ ldlang_add_undef ($1); }
273195609Smp	| extern_name_list NAME
27483098Smp			{ ldlang_add_undef ($2); }
27583098Smp	| extern_name_list ',' NAME
27683098Smp			{ ldlang_add_undef ($3); }
27783098Smp	;
27883098Smp
279195609Smpscript_file:
28069408Sache	{
28169408Sache	 ldlex_both();
282195609Smp	}
28369408Sache       ifile_list
284100616Smp	{
285195609Smp	ldlex_popstate();
28669408Sache	}
28769408Sache        ;
288195609Smp
289100616Smp
290100616Smpifile_list:
291195609Smp       ifile_list ifile_p1
29283098Smp        |
29383098Smp	;
294195609Smp
295195609Smp
296195609Smp
297195609Smpifile_p1:
298195609Smp		memory
299195609Smp	|	sections
300195609Smp	|	phdrs
30169408Sache	|	startup
30269408Sache	|	high_level_library
303195609Smp	|	low_level_library
304195609Smp	|	floating_point_support
305195609Smp	|	statement_anywhere
306195609Smp	|	version
307100616Smp        |	 ';'
30869408Sache	|	TARGET_K '(' NAME ')'
309195609Smp		{ lang_add_target($3); }
31083098Smp	|	SEARCH_DIR '(' filename ')'
31169408Sache		{ ldfile_add_library_path ($3, false); }
31269408Sache	|	OUTPUT '(' filename ')'
31369408Sache		{ lang_add_output($3, 1); }
31469408Sache        |	OUTPUT_FORMAT '(' NAME ')'
31569408Sache		  { lang_add_output_format ($3, (char *) NULL,
31669408Sache					    (char *) NULL, 1); }
317195609Smp	|	OUTPUT_FORMAT '(' NAME ',' NAME ',' NAME ')'
31883098Smp		  { lang_add_output_format ($3, $5, $7, 1); }
31969408Sache        |	OUTPUT_ARCH '(' NAME ')'
320195609Smp		  { ldfile_set_output_arch($3); }
321195609Smp	|	FORCE_COMMON_ALLOCATION
322195609Smp		{ command_line.force_common_definition = true ; }
323195609Smp	|	INPUT '(' input_list ')'
324195609Smp	|	GROUP
325100616Smp		  { lang_enter_group (); }
326195609Smp		    '(' input_list ')'
327100616Smp		  { lang_leave_group (); }
328195609Smp     	|	MAP '(' filename ')'
329195609Smp		{ lang_add_map($3); }
330195609Smp	|	INCLUDE filename
33169408Sache		{ ldfile_open_command_file($2); } ifile_list END
33269408Sache	|	NOCROSSREFS '(' nocrossref_list ')'
333195609Smp		{
33469408Sache		  lang_add_nocrossref ($3);
33569408Sache		}
336195609Smp	|	EXTERN '(' extern_name_list ')'
337231990Smp	;
338231990Smp
339231990Smpinput_list:
340195609Smp		NAME
341195609Smp		{ lang_add_input_file($1,lang_input_file_is_search_file_enum,
342195609Smp				 (char *)NULL); }
343195609Smp	|	input_list ',' NAME
344195609Smp		{ lang_add_input_file($3,lang_input_file_is_search_file_enum,
345195609Smp				 (char *)NULL); }
346195609Smp	|	input_list NAME
347195609Smp		{ lang_add_input_file($2,lang_input_file_is_search_file_enum,
348195609Smp				 (char *)NULL); }
349195609Smp	|	LNAME
350195609Smp		{ lang_add_input_file($1,lang_input_file_is_l_enum,
351195609Smp				 (char *)NULL); }
352195609Smp	|	input_list ',' LNAME
353195609Smp		{ lang_add_input_file($3,lang_input_file_is_l_enum,
354195609Smp				 (char *)NULL); }
355195609Smp	|	input_list LNAME
35669408Sache		{ lang_add_input_file($2,lang_input_file_is_l_enum,
35769408Sache				 (char *)NULL); }
35869408Sache	;
35969408Sache
36069408Sachesections:
361195609Smp		SECTIONS '{' sec_or_group_p1 '}'
36269408Sache	;
36369408Sache
36469408Sachesec_or_group_p1:
36569408Sache		sec_or_group_p1 section
36669408Sache	|	sec_or_group_p1 statement_anywhere
36769408Sache	|
36869408Sache	;
36969408Sache
370195609Smpstatement_anywhere:
37169408Sache		ENTRY '(' NAME ')'
37269408Sache		{ lang_add_entry ($3, false); }
373195609Smp	|	assignment end
37469408Sache	;
375100616Smp
37669408Sache/* The '*' and '?' cases are there because the lexer returns them as
37769408Sache   separate tokens rather than as NAME.  */
37869408Sachewildcard_name:
37969408Sache		NAME
38069408Sache			{
38169408Sache			  $$ = $1;
38269408Sache			}
38369408Sache	|	'*'
38469408Sache			{
385195609Smp			  $$ = "*";
38669408Sache			}
38769408Sache	|	'?'
388195609Smp			{
38983098Smp			  $$ = "?";
39083098Smp			}
391100616Smp	;
39283098Smp
39383098Smpwildcard_spec:
39483098Smp		wildcard_name
39583098Smp			{
39683098Smp			  $$.name = $1;
39783098Smp			  $$.sorted = false;
39883098Smp			  $$.exclude_name_list = NULL;
399195609Smp			}
40083098Smp	| 	EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name
40183098Smp			{
402195609Smp			  $$.name = $5;
40383098Smp			  $$.sorted = false;
40483098Smp			  $$.exclude_name_list = $3;
405195609Smp			}
40683098Smp	|	SORT '(' wildcard_name ')'
40783098Smp			{
408195609Smp			  $$.name = $3;
40983098Smp			  $$.sorted = true;
41083098Smp			  $$.exclude_name_list = NULL;
411195609Smp			}
41283098Smp	|	SORT '(' EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name ')'
41383098Smp			{
414195609Smp			  $$.name = $7;
415195609Smp			  $$.sorted = true;
416195609Smp			  $$.exclude_name_list = $5;
417195609Smp			}
41869408Sache	;
41969408Sache
420195609Smp
42169408Sache
42269408Sacheexclude_name_list:
423195609Smp		exclude_name_list wildcard_name
42469408Sache			{
42569408Sache			  struct name_list *tmp;
426195609Smp			  tmp = (struct name_list *) xmalloc (sizeof *tmp);
42769408Sache			  tmp->name = $2;
42869408Sache			  tmp->next = $1;
429195609Smp			  $$ = tmp;
43083098Smp			}
43169408Sache	|
432195609Smp		wildcard_name
43369408Sache			{
434100616Smp			  struct name_list *tmp;
43583098Smp			  tmp = (struct name_list *) xmalloc (sizeof *tmp);
43683098Smp			  tmp->name = $1;
437100616Smp			  tmp->next = NULL;
43883098Smp			  $$ = tmp;
43983098Smp			}
44083098Smp	;
44183098Smp
44269408Sachefile_NAME_list:
44369408Sache		wildcard_spec
44469408Sache			{
44569408Sache			  lang_add_wild ($1.name, $1.sorted,
44669408Sache					 current_file.name,
44769408Sache					 current_file.sorted,
44869408Sache					 ldgram_had_keep, $1.exclude_name_list);
44969408Sache			}
45069408Sache	|	file_NAME_list opt_comma wildcard_spec
45169408Sache			{
45269408Sache			  lang_add_wild ($3.name, $3.sorted,
45369408Sache					 current_file.name,
45469408Sache					 current_file.sorted,
45569408Sache					 ldgram_had_keep, $3.exclude_name_list);
456195609Smp			}
457195609Smp	;
458195609Smp
459195609Smpinput_section_spec_no_keep:
46069408Sache		NAME
461195609Smp			{
462100616Smp			  lang_add_wild (NULL, false, $1, false,
463100616Smp					 ldgram_had_keep, NULL);
464195609Smp			}
465195609Smp        |	'['
466100616Smp			{
467195609Smp			  current_file.name = NULL;
468195609Smp			  current_file.sorted = false;
469195609Smp			}
470195609Smp		file_NAME_list ']'
47169408Sache	|	wildcard_spec
47269408Sache			{
473195609Smp			  current_file = $1;
47469408Sache			  /* '*' matches any file name.  */
47569408Sache			  if (strcmp (current_file.name, "*") == 0)
476195609Smp			    current_file.name = NULL;
47769408Sache			}
47869408Sache		'(' file_NAME_list ')'
479195609Smp	;
48069408Sache
48169408Sacheinput_section_spec:
482195609Smp		input_section_spec_no_keep
48369408Sache	|	KEEP '('
48469408Sache			{ ldgram_had_keep = true; }
48569408Sache		input_section_spec_no_keep ')'
486100616Smp			{ ldgram_had_keep = false; }
48783098Smp	;
48883098Smp
48983098Smpstatement:
49083098Smp	  	assignment end
49169408Sache	|	CREATE_OBJECT_SYMBOLS
49283098Smp		{
49383098Smp 		lang_add_attribute(lang_object_symbols_statement_enum);
49483098Smp	      	}
49569408Sache        |	';'
49683098Smp        |	CONSTRUCTORS
49769408Sache		{
498195609Smp
49969408Sache		  lang_add_attribute(lang_constructors_statement_enum);
50069408Sache		}
501195609Smp	| SORT '(' CONSTRUCTORS ')'
50269408Sache		{
50369408Sache		  constructors_sorted = true;
50469408Sache		  lang_add_attribute (lang_constructors_statement_enum);
505195609Smp		}
50669408Sache	| input_section_spec
50769408Sache        | length '(' mustbe_exp ')'
508195609Smp        	        {
50969408Sache			lang_add_data((int) $1,$3);
51069408Sache			}
511195609Smp
51269408Sache	| FILL '(' mustbe_exp ')'
51369408Sache			{
514195609Smp			  lang_add_fill
51569408Sache			    (exp_get_value_int($3,
516195609Smp					       0,
517195609Smp					       "fill value",
518100616Smp					       lang_first_phase_enum));
51969408Sache			}
520195609Smp	;
521100616Smp
522100616Smpstatement_list:
523100616Smp		statement_list statement
524100616Smp  	|  	statement
525100616Smp	;
526100616Smp
527100616Smpstatement_list_opt:
528195609Smp		/* empty */
52969408Sache	|	statement_list
53069408Sache	;
531100616Smp
53283098Smplength:
53369408Sache		QUAD
53469408Sache			{ $$ = $1; }
53569408Sache	|	SQUAD
53669408Sache			{ $$ = $1; }
53769408Sache	|	LONG
53869408Sache			{ $$ = $1; }
53969408Sache	| 	SHORT
54069408Sache			{ $$ = $1; }
54169408Sache	|	BYTE
54269408Sache			{ $$ = $1; }
543195609Smp	;
544195609Smp
545195609Smpfill_opt:
546195609Smp          '=' mustbe_exp
547195609Smp		{
548195609Smp		  $$ =	 exp_get_value_int($2,
54969408Sache					   0,
55069408Sache					   "fill value",
55169408Sache					   lang_first_phase_enum);
55269408Sache		}
55369408Sache	| 	{ $$ = 0; }
554195609Smp	;
555195609Smp
556100616Smp
557100616Smp
55869408Sacheassign_op:
55969408Sache		PLUSEQ
56069408Sache			{ $$ = '+'; }
56169408Sache	|	MINUSEQ
56269408Sache			{ $$ = '-'; }
56369408Sache	| 	MULTEQ
56469408Sache			{ $$ = '*'; }
565100616Smp	| 	DIVEQ
56669408Sache			{ $$ = '/'; }
56769408Sache	| 	LSHIFTEQ
568195609Smp			{ $$ = LSHIFT; }
56969408Sache	| 	RSHIFTEQ
57069408Sache			{ $$ = RSHIFT; }
571195609Smp	| 	ANDEQ
57269408Sache			{ $$ = '&'; }
57369408Sache	| 	OREQ
574195609Smp			{ $$ = '|'; }
575100616Smp
57669408Sache	;
577195609Smp
57869408Sacheend:	';' | ','
57969408Sache	;
580195609Smp
58169408Sache
58269408Sacheassignment:
583195609Smp		NAME '=' mustbe_exp
58469408Sache		{
58569408Sache		  lang_add_assignment (exp_assop ($2, $1, $3));
586195609Smp		}
58769408Sache	|	NAME assign_op mustbe_exp
58869408Sache		{
589195609Smp		  lang_add_assignment (exp_assop ('=', $1,
59069408Sache						  exp_binop ($2,
591100616Smp							     exp_nameop (NAME,
59269408Sache									 $1),
59369408Sache							     $3)));
59469408Sache		}
59583098Smp	|	PROVIDE '(' NAME '=' mustbe_exp ')'
596100616Smp		{
597100616Smp		  lang_add_assignment (exp_provide ($3, $5));
598100616Smp		}
599100616Smp	;
600100616Smp
601100616Smp
602100616Smpopt_comma:
603100616Smp		','	|	;
604100616Smp
605100616Smp
606100616Smpmemory:
607100616Smp		MEMORY '{' memory_spec memory_spec_list '}'
608100616Smp	;
609100616Smp
610100616Smpmemory_spec_list:
611100616Smp		memory_spec_list memory_spec
612100616Smp	|	memory_spec_list ',' memory_spec
613100616Smp	|
614100616Smp	;
61569408Sache
61669408Sache
61783098Smpmemory_spec: 		NAME
61869408Sache			{ region = lang_memory_region_lookup($1); }
61969408Sache		attributes_opt ':'
62069408Sache		origin_spec opt_comma length_spec
62169408Sache
62283098Smp	; origin_spec:
62369408Sache	ORIGIN '=' mustbe_exp
62483098Smp		{ region->current =
62583098Smp		 region->origin =
62669408Sache		 exp_get_vma($3, 0L,"origin", lang_first_phase_enum);
62769408Sache}
62869408Sache	;
62983098Smp
63069408Sachelength_spec:
63183098Smp             LENGTH '=' mustbe_exp
63269408Sache               { region->length = exp_get_vma($3,
63369408Sache					       ~((bfd_vma)0),
63469408Sache					       "length",
63569408Sache					       lang_first_phase_enum);
63669408Sache		}
63769408Sache	;
63869408Sache
63983098Smpattributes_opt:
64069408Sache		/* empty */
64169408Sache		  { /* dummy action to avoid bison 1.25 error message */ }
64269408Sache	|	'(' attributes_list ')'
64369408Sache	;
64469408Sache
645195609Smpattributes_list:
646195609Smp		attributes_string
647100616Smp	|	attributes_list attributes_string
64869408Sache	;
649195609Smp
650195609Smpattributes_string:
651195609Smp		NAME
652195609Smp		  { lang_set_flags (region, $1, 0); }
653195609Smp	|	'!' NAME
654195609Smp		  { lang_set_flags (region, $2, 1); }
655195609Smp	;
656195609Smp
657195609Smpstartup:
658195609Smp	STARTUP '(' filename ')'
659195609Smp		{ lang_startup($3); }
660195609Smp	;
661195609Smp
662195609Smphigh_level_library:
663195609Smp		HLL '(' high_level_library_NAME_list ')'
664195609Smp	|	HLL '(' ')'
665195609Smp			{ ldemul_hll((char *)NULL); }
666195609Smp	;
667195609Smp
668195609Smphigh_level_library_NAME_list:
669195609Smp		high_level_library_NAME_list opt_comma filename
67069408Sache			{ ldemul_hll($3); }
671195609Smp	|	filename
672100616Smp			{ ldemul_hll($1); }
673100616Smp
674100616Smp	;
675195609Smp
67669408Sachelow_level_library:
677100616Smp	SYSLIB '(' low_level_library_NAME_list ')'
67883098Smp	; low_level_library_NAME_list:
67969408Sache		low_level_library_NAME_list opt_comma filename
68069408Sache			{ ldemul_syslib($3); }
68169408Sache	|
68269408Sache	;
68369408Sache
68469408Sachefloating_point_support:
68569408Sache		FLOAT
68669408Sache			{ lang_float(true); }
68769408Sache	|	NOFLOAT
68869408Sache			{ lang_float(false); }
68969408Sache	;
69069408Sache
69169408Sachenocrossref_list:
69269408Sache		/* empty */
69369408Sache		{
69469408Sache		  $$ = NULL;
69569408Sache		}
69669408Sache	|	NAME nocrossref_list
69769408Sache		{
69869408Sache		  struct lang_nocrossref *n;
69969408Sache
70069408Sache		  n = (struct lang_nocrossref *) xmalloc (sizeof *n);
70169408Sache		  n->name = $1;
70269408Sache		  n->next = $2;
703195609Smp		  $$ = n;
704195609Smp		}
70569408Sache	|	NAME ',' nocrossref_list
706195609Smp		{
70769408Sache		  struct lang_nocrossref *n;
70869408Sache
709195609Smp		  n = (struct lang_nocrossref *) xmalloc (sizeof *n);
71069408Sache		  n->name = $1;
71169408Sache		  n->next = $3;
712195609Smp		  $$ = n;
713100616Smp		}
71483098Smp	;
715195609Smp
71669408Sachemustbe_exp:		 { ldlex_expression(); }
71769408Sache		exp
718195609Smp			 { ldlex_popstate(); $$=$2;}
71969408Sache	;
72069408Sache
721195609Smpexp	:
722100616Smp		'-' exp %prec UNARY
72369408Sache			{ $$ = exp_unop('-', $2); }
72469408Sache	|	'(' exp ')'
72569408Sache			{ $$ = $2; }
72669408Sache	|	NEXT '(' exp ')' %prec UNARY
72769408Sache			{ $$ = exp_unop((int) $1,$3); }
728195609Smp	|	'!' exp %prec UNARY
72969408Sache			{ $$ = exp_unop('!', $2); }
73069408Sache	|	'+' exp %prec UNARY
731195609Smp			{ $$ = $2; }
73283098Smp	|	'~' exp %prec UNARY
73369408Sache			{ $$ = exp_unop('~', $2);}
734195609Smp
73583098Smp	|	exp '*' exp
73683098Smp			{ $$ = exp_binop('*', $1, $3); }
73769408Sache	|	exp '/' exp
73869408Sache			{ $$ = exp_binop('/', $1, $3); }
73969408Sache	|	exp '%' exp
740195609Smp			{ $$ = exp_binop('%', $1, $3); }
74183098Smp	|	exp '+' exp
74269408Sache			{ $$ = exp_binop('+', $1, $3); }
743195609Smp	|	exp '-' exp
74483098Smp			{ $$ = exp_binop('-' , $1, $3); }
74569408Sache	|	exp LSHIFT exp
746195609Smp			{ $$ = exp_binop(LSHIFT , $1, $3); }
74783098Smp	|	exp RSHIFT exp
74869408Sache			{ $$ = exp_binop(RSHIFT , $1, $3); }
749195609Smp	|	exp EQ exp
75069408Sache			{ $$ = exp_binop(EQ , $1, $3); }
751100616Smp	|	exp NE exp
752195609Smp			{ $$ = exp_binop(NE , $1, $3); }
75369408Sache	|	exp LE exp
75469408Sache			{ $$ = exp_binop(LE , $1, $3); }
75569408Sache  	|	exp GE exp
756100616Smp			{ $$ = exp_binop(GE , $1, $3); }
757100616Smp	|	exp '<' exp
758195609Smp			{ $$ = exp_binop('<' , $1, $3); }
75969408Sache	|	exp '>' exp
760100616Smp			{ $$ = exp_binop('>' , $1, $3); }
761195609Smp	|	exp '&' exp
76283098Smp			{ $$ = exp_binop('&' , $1, $3); }
763100616Smp	|	exp '^' exp
764195609Smp			{ $$ = exp_binop('^' , $1, $3); }
765100616Smp	|	exp '|' exp
766100616Smp			{ $$ = exp_binop('|' , $1, $3); }
767195609Smp	|	exp '?' exp ':' exp
768195609Smp			{ $$ = exp_trinop('?' , $1, $3, $5); }
769195609Smp	|	exp ANDAND exp
770195609Smp			{ $$ = exp_binop(ANDAND , $1, $3); }
771100616Smp	|	exp OROR exp
772100616Smp			{ $$ = exp_binop(OROR , $1, $3); }
77383098Smp	|	DEFINED '(' NAME ')'
77469408Sache			{ $$ = exp_nameop(DEFINED, $3); }
775100616Smp	|	INT
776195609Smp			{ $$ = exp_intop($1); }
777195609Smp        |	SIZEOF_HEADERS
778195609Smp			{ $$ = exp_nameop(SIZEOF_HEADERS,0); }
779195609Smp
780195609Smp	|	SIZEOF '(' NAME ')'
781195609Smp			{ $$ = exp_nameop(SIZEOF,$3); }
782100616Smp	|	ADDR '(' NAME ')'
78383098Smp			{ $$ = exp_nameop(ADDR,$3); }
784195609Smp	|	LOADADDR '(' NAME ')'
78569408Sache			{ $$ = exp_nameop(LOADADDR,$3); }
78669408Sache	|	ABSOLUTE '(' exp ')'
787195609Smp			{ $$ = exp_unop(ABSOLUTE, $3); }
78883098Smp	|	ALIGN_K '(' exp ')'
78983098Smp			{ $$ = exp_unop(ALIGN_K,$3); }
790195609Smp	|	BLOCK '(' exp ')'
79169408Sache			{ $$ = exp_unop(ALIGN_K,$3); }
792195609Smp	|	NAME
793195609Smp			{ $$ = exp_nameop(NAME,$1); }
794195609Smp	|	MAX_K '(' exp ',' exp ')'
795195609Smp			{ $$ = exp_binop (MAX_K, $3, $5 ); }
796195609Smp	|	MIN_K '(' exp ',' exp ')'
797195609Smp			{ $$ = exp_binop (MIN_K, $3, $5 ); }
798195609Smp	|	ASSERT_K '(' exp ',' NAME ')'
799195609Smp			{ $$ = exp_assert ($3, $5); }
800195609Smp	;
80169408Sache
80269408Sache
803195609Smpmemspec_at_opt:
804195609Smp                AT '>' NAME { $$ = $3; }
80569408Sache        |       { $$ = "*default*"; }
806195609Smp        ;
807195609Smp
808195609Smpopt_at:
809195609Smp		AT '(' exp ')' { $$ = $3; }
810195609Smp	|	{ $$ = 0; }
811100616Smp	;
812100616Smp
813195609Smpsection:	NAME 		{ ldlex_expression(); }
814231990Smp		opt_exp_with_type
815195609Smp		opt_at   	{ ldlex_popstate (); ldlex_script (); }
816195609Smp		'{'
817195609Smp			{
818195609Smp			  lang_enter_output_section_statement($1, $3,
819231990Smp							      sectype,
820195609Smp							      0, 0, 0, $4);
821195609Smp			}
822195609Smp		statement_list_opt
823195609Smp 		'}' { ldlex_popstate (); ldlex_expression (); }
824195609Smp		memspec_opt memspec_at_opt phdr_opt fill_opt
825195609Smp		{
826195609Smp		  ldlex_popstate ();
827195609Smp		  lang_leave_output_section_statement ($14, $11, $13, $12);
828195609Smp		}
829195609Smp		opt_comma
830195609Smp	|	OVERLAY
831195609Smp			{ ldlex_expression (); }
83283098Smp		opt_exp_without_type opt_nocrossrefs opt_at
83383098Smp			{ ldlex_popstate (); ldlex_script (); }
83483098Smp		'{'
83583098Smp			{
836195609Smp			  lang_enter_overlay ($3, $5, (int) $4);
837195609Smp			}
83883098Smp		overlay_section
83983098Smp		'}'
840195609Smp			{ ldlex_popstate (); ldlex_expression (); }
841195609Smp		memspec_opt memspec_at_opt phdr_opt fill_opt
842195609Smp			{
843195609Smp			  ldlex_popstate ();
84469408Sache			  lang_leave_overlay ($15, $12, $14, $13);
84569408Sache			}
846195609Smp		opt_comma
84769408Sache	|	/* The GROUP case is just enough to support the gcc
84869408Sache		   svr3.ifile script.  It is not intended to be full
849195609Smp		   support.  I'm not even sure what GROUP is supposed
85069408Sache		   to mean.  */
851195609Smp		GROUP { ldlex_expression (); }
85269408Sache		opt_exp_with_type
853195609Smp		{
854195609Smp		  ldlex_popstate ();
855195609Smp		  lang_add_assignment (exp_assop ('=', ".", $3));
856195609Smp		}
857195609Smp		'{' sec_or_group_p1 '}'
858100616Smp	;
859100616Smp
860195609Smptype:
861231990Smp	   NOLOAD  { sectype = noload_section; }
862231990Smp	|  DSECT   { sectype = dsect_section; }
863231990Smp	|  COPY    { sectype = copy_section; }
864231990Smp	|  INFO    { sectype = info_section; }
865231990Smp	|  OVERLAY { sectype = overlay_section; }
866231990Smp	;
867231990Smp
868231990Smpatype:
869231990Smp	 	'(' type ')'
870231990Smp  	| 	/* EMPTY */ { sectype = normal_section; }
871231990Smp  	| 	'(' ')' { sectype = normal_section; }
872231990Smp	;
873231990Smp
874231990Smpopt_exp_with_type:
875100616Smp		exp atype ':'		{ $$ = $1; }
876195609Smp	|	atype ':'		{ $$ = (etree_type *)NULL;  }
877195609Smp	|	/* The BIND cases are to support the gcc svr3.ifile
878195609Smp		   script.  They aren't intended to implement full
879195609Smp		   support for the BIND keyword.  I'm not even sure
880195609Smp		   what BIND is supposed to mean.  */
881195609Smp		BIND '(' exp ')' atype ':' { $$ = $3; }
882195609Smp	|	BIND '(' exp ')' BLOCK '(' exp ')' atype ':'
883195609Smp		{ $$ = $3; }
884195609Smp	;
885195609Smp
886100616Smpopt_exp_without_type:
887195609Smp		exp ':'		{ $$ = $1; }
888195609Smp	|	':'		{ $$ = (etree_type *) NULL;  }
889195609Smp	;
890195609Smp
891195609Smpopt_nocrossrefs:
892195609Smp		/* empty */
893195609Smp			{ $$ = 0; }
894195609Smp	|	NOCROSSREFS
895195609Smp			{ $$ = 1; }
896195609Smp	;
897231990Smp
898231990Smpmemspec_opt:
899231990Smp		'>' NAME
900231990Smp		{ $$ = $2; }
901231990Smp	|	{ $$ = "*default*"; }
902231990Smp	;
903231990Smp
904231990Smpphdr_opt:
905231990Smp		/* empty */
906231990Smp		{
907231990Smp		  $$ = NULL;
908100616Smp		}
909100616Smp	|	phdr_opt ':' NAME
910195609Smp		{
911195609Smp		  struct lang_output_section_phdr_list *n;
912195609Smp
913195609Smp		  n = ((struct lang_output_section_phdr_list *)
914100616Smp		       xmalloc (sizeof *n));
915100616Smp		  n->name = $3;
916195609Smp		  n->used = false;
917195609Smp		  n->next = $1;
918100616Smp		  $$ = n;
919100616Smp		}
920100616Smp	;
921195609Smp
922195609Smpoverlay_section:
923100616Smp		/* empty */
924195609Smp	|	overlay_section
925100616Smp		NAME
926100616Smp			{
927195609Smp			  ldlex_script ();
928100616Smp			  lang_enter_overlay_section ($2);
929100616Smp			}
930100616Smp		'{' statement_list_opt '}'
931100616Smp			{ ldlex_popstate (); ldlex_expression (); }
932100616Smp		phdr_opt fill_opt
933231990Smp			{
934195609Smp			  ldlex_popstate ();
935100616Smp			  lang_leave_overlay_section ($9, $8);
936195609Smp			}
937195609Smp		opt_comma
938195609Smp	;
939195609Smp
940195609Smpphdrs:
941195609Smp		PHDRS '{' phdr_list '}'
942231990Smp	;
943231990Smp
944231990Smpphdr_list:
945100616Smp		/* empty */
946100616Smp	|	phdr_list phdr
947100616Smp	;
948100616Smp
949100616Smpphdr:
950100616Smp		NAME { ldlex_expression (); }
951100616Smp		  phdr_type phdr_qualifiers { ldlex_popstate (); }
952195609Smp		  ';'
953231990Smp		{
954231990Smp		  lang_new_phdr ($1, $3, $4.filehdr, $4.phdrs, $4.at,
955195609Smp				 $4.flags);
956231990Smp		}
957231990Smp	;
958231990Smp
959100616Smpphdr_type:
960100616Smp		exp
961195609Smp		{
962195609Smp		  $$ = $1;
963195609Smp
964195609Smp		  if ($1->type.node_class == etree_name
965100616Smp		      && $1->type.node_code == NAME)
966100616Smp		    {
967195609Smp		      const char *s;
968100616Smp		      unsigned int i;
969100616Smp		      static const char * const phdr_types[] =
970195609Smp			{
971195609Smp			  "PT_NULL", "PT_LOAD", "PT_DYNAMIC",
972195609Smp			  "PT_INTERP", "PT_NOTE", "PT_SHLIB",
973195609Smp			  "PT_PHDR"
974100616Smp			};
975100616Smp
976195609Smp		      s = $1->name.name;
977195609Smp		      for (i = 0;
978195609Smp			   i < sizeof phdr_types / sizeof phdr_types[0];
979195609Smp			   i++)
980100616Smp			if (strcmp (s, phdr_types[i]) == 0)
981100616Smp			  {
982100616Smp			    $$ = exp_intop (i);
983100616Smp			    break;
98469408Sache			  }
985195609Smp		    }
986100616Smp		}
98769408Sache	;
98869408Sache
98969408Sachephdr_qualifiers:
99069408Sache		/* empty */
99169408Sache		{
99269408Sache		  memset (&$$, 0, sizeof (struct phdr_info));
993195609Smp		}
994195609Smp	|	NAME phdr_val phdr_qualifiers
995195609Smp		{
996195609Smp		  $$ = $3;
997195609Smp		  if (strcmp ($1, "FILEHDR") == 0 && $2 == NULL)
998195609Smp		    $$.filehdr = true;
999195609Smp		  else if (strcmp ($1, "PHDRS") == 0 && $2 == NULL)
1000195609Smp		    $$.phdrs = true;
1001195609Smp		  else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL)
1002195609Smp		    $$.flags = $2;
1003195609Smp		  else
1004195609Smp		    einfo (_("%X%P:%S: PHDRS syntax error at `%s'\n"), $1);
1005195609Smp		}
1006195609Smp	|	AT '(' exp ')' phdr_qualifiers
1007195609Smp		{
1008195609Smp		  $$ = $5;
1009195609Smp		  $$.at = $3;
1010195609Smp		}
1011195609Smp	;
1012195609Smp
1013195609Smpphdr_val:
1014100616Smp		/* empty */
101583098Smp		{
101669408Sache		  $$ = NULL;
101783098Smp		}
101869408Sache	| '(' exp ')'
101983098Smp		{
102069408Sache		  $$ = $2;
1021195609Smp		}
1022195609Smp	;
1023195609Smp
1024100616Smp/* This syntax is used within an external version script file.  */
1025100616Smp
1026100616Smpversion_script_file:
1027100616Smp		{
1028100616Smp		  ldlex_version_file ();
1029100616Smp		  PUSH_ERROR (_("VERSION script"));
1030195609Smp		}
1031100616Smp		vers_nodes
103269408Sache		{
103369408Sache		  ldlex_popstate ();
103469408Sache		  POP_ERROR ();
103569408Sache		}
1036100616Smp	;
1037100616Smp
1038100616Smp/* This is used within a normal linker script file.  */
103969408Sache
1040100616Smpversion:
104183098Smp		{
1042100616Smp		  ldlex_version_script ();
104383098Smp		}
104469408Sache		VERSIONK '{' vers_nodes '}'
104569408Sache		{
104669408Sache		  ldlex_popstate ();
104769408Sache		}
1048195609Smp	;
104969408Sache
1050100616Smpvers_nodes:
105169408Sache		vers_node
1052195609Smp	|	vers_nodes vers_node
1053195609Smp	;
1054195609Smp
1055195609Smpvers_node:
1056195609Smp		VERS_TAG '{' vers_tag '}' ';'
1057195609Smp		{
105869408Sache		  lang_register_vers_node ($1, $3, NULL);
105969408Sache		}
1060195609Smp	|	VERS_TAG '{' vers_tag '}' verdep ';'
106169408Sache		{
106269408Sache		  lang_register_vers_node ($1, $3, $5);
1063195609Smp		}
106469408Sache	;
106569408Sache
106669408Sacheverdep:
106769408Sache		VERS_TAG
106869408Sache		{
106969408Sache		  $$ = lang_add_vers_depend (NULL, $1);
1070195609Smp		}
107169408Sache	|	verdep VERS_TAG
107269408Sache		{
107369408Sache		  $$ = lang_add_vers_depend ($1, $2);
1074195609Smp		}
1075195609Smp	;
1076195609Smp
1077195609Smpvers_tag:
1078195609Smp		/* empty */
1079195609Smp		{
1080195609Smp		  $$ = lang_new_vers_node (NULL, NULL);
1081195609Smp		}
1082195609Smp	|	vers_defns ';'
1083195609Smp		{
108469408Sache		  $$ = lang_new_vers_node ($1, NULL);
108569408Sache		}
108669408Sache	|	GLOBAL ':' vers_defns ';'
108769408Sache		{
1088195609Smp		  $$ = lang_new_vers_node ($3, NULL);
108969408Sache		}
1090195609Smp	|	LOCAL ':' vers_defns ';'
109169408Sache		{
109269408Sache		  $$ = lang_new_vers_node (NULL, $3);
1093195609Smp		}
1094195609Smp	|	GLOBAL ':' vers_defns ';' LOCAL ':' vers_defns ';'
1095195609Smp		{
1096195609Smp		  $$ = lang_new_vers_node ($3, $7);
1097195609Smp		}
1098195609Smp	;
1099195609Smp
1100195609Smpvers_defns:
1101195609Smp		VERS_IDENTIFIER
1102195609Smp		{
1103195609Smp		  $$ = lang_new_vers_regex (NULL, $1, ldgram_vers_current_lang);
1104100616Smp		}
110569408Sache	|	vers_defns ';' VERS_IDENTIFIER
1106195609Smp		{
110769408Sache		  $$ = lang_new_vers_regex ($1, $3, ldgram_vers_current_lang);
110869408Sache		}
1109195609Smp	|	EXTERN NAME '{'
111069408Sache			{
111169408Sache			  $<name>$ = ldgram_vers_current_lang;
1112195609Smp			  ldgram_vers_current_lang = $2;
1113100616Smp			}
111469408Sache		vers_defns '}'
1115195609Smp			{
1116195609Smp			  ldgram_vers_current_lang = $<name>4;
1117100616Smp			}
1118195609Smp	;
111969408Sache
112069408Sache%%
1121195609Smpvoid
112283098Smpyyerror(arg)
112383098Smp     const char *arg;
1124195609Smp{
112569408Sache  if (ldfile_assumed_script)
112669408Sache    einfo (_("%P:%s: file format not recognized; treating as linker script\n"),
1127195609Smp	   ldfile_input_filename);
112869408Sache  if (error_index > 0 && error_index < ERROR_NAME_MAX)
112969408Sache     einfo ("%P%F:%S: %s in %s\n", arg, error_names[error_index-1]);
113069408Sache  else
113169408Sache     einfo ("%P%F:%S: %s\n", arg);
113269408Sache}
113369408Sache