ldgram.y revision 1.3
1/* A YACC grammer to parse a superset of the AT&T linker scripting languaue.
2   Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
3   Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
4
5This file is part of GNU ld.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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#ifndef YYDEBUG
43#define YYDEBUG 1
44#endif
45
46static enum section_type sectype;
47
48lang_memory_region_type *region;
49
50
51char *current_file;
52boolean ldgram_want_filename = true;
53boolean had_script = false;
54boolean force_make_executable = false;
55
56boolean ldgram_in_script = false;
57boolean ldgram_had_equals = false;
58
59
60#define ERROR_NAME_MAX 20
61static char *error_names[ERROR_NAME_MAX];
62static int error_index;
63#define PUSH_ERROR(x) if (error_index < ERROR_NAME_MAX) error_names[error_index] = x; error_index++;
64#define POP_ERROR()   error_index--;
65%}
66%union {
67  bfd_vma integer;
68  char *name;
69  int token;
70  union etree_union *etree;
71  struct phdr_info
72    {
73      boolean filehdr;
74      boolean phdrs;
75      union etree_union *at;
76      union etree_union *flags;
77    } phdr;
78  struct lang_nocrossref *nocrossref;
79  struct lang_output_section_phdr_list *section_phdr;
80}
81
82%type <etree> exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val
83%type <etree> opt_exp_without_type
84%type <integer> fill_opt
85%type <name> memspec_opt casesymlist
86%token <integer> INT
87%token <name> NAME LNAME
88%type <integer> length
89%type <phdr> phdr_qualifiers
90%type <nocrossref> nocrossref_list
91%type <section_phdr> phdr_opt
92%type <integer> opt_nocrossrefs
93
94%right <token> PLUSEQ MINUSEQ MULTEQ DIVEQ  '=' LSHIFTEQ RSHIFTEQ   ANDEQ OREQ
95%right <token> '?' ':'
96%left <token> OROR
97%left <token>  ANDAND
98%left <token> '|'
99%left <token>  '^'
100%left  <token> '&'
101%left <token>  EQ NE
102%left  <token> '<' '>' LE GE
103%left  <token> LSHIFT RSHIFT
104
105%left  <token> '+' '-'
106%left  <token> '*' '/' '%'
107
108%right UNARY
109%token END
110%left <token> '('
111%token <token> ALIGN_K BLOCK BIND QUAD LONG SHORT BYTE
112%token SECTIONS PHDRS
113%token '{' '}'
114%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
115%token SIZEOF_HEADERS
116%token INCLUDE
117%token MEMORY DEFSYMEND
118%token NOLOAD DSECT COPY INFO OVERLAY
119%token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY
120%token <integer> NEXT
121%token SIZEOF ADDR LOADADDR MAX MIN
122%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS
123%token ORIGIN FILL
124%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
125%token ALIGNMOD AT PROVIDE
126%type <token> assign_op atype
127%type <name>  filename
128%token CHIP LIST SECT ABSOLUTE  LOAD NEWLINE ENDWORD ORDER NAMEWORD
129%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
130%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
131
132%%
133
134file:
135		INPUT_SCRIPT script_file
136	|	INPUT_MRI_SCRIPT mri_script_file
137	|	INPUT_DEFSYM defsym_expr
138	;
139
140
141filename:  NAME;
142
143
144defsym_expr:
145		{ ldlex_defsym(); }
146		NAME '=' exp
147		{
148		  ldlex_popstate();
149		  lang_add_assignment(exp_assop($3,$2,$4));
150		}
151
152/* SYNTAX WITHIN AN MRI SCRIPT FILE */
153mri_script_file:
154		{
155		  ldlex_mri_script ();
156		  PUSH_ERROR ("MRI style script");
157		}
158	     mri_script_lines
159		{
160		  ldlex_popstate ();
161		  mri_draw_tree ();
162		  POP_ERROR ();
163		}
164	;
165
166mri_script_lines:
167		mri_script_lines mri_script_command NEWLINE
168          |
169	;
170
171mri_script_command:
172		CHIP  exp
173	|	CHIP  exp ',' exp
174	|	NAME 	{
175			einfo("%P%F: unrecognised keyword in MRI style script '%s'\n",$1);
176			}
177	|	LIST  	{
178			config.map_filename = "-";
179			}
180        |       ORDER ordernamelist
181	|       ENDWORD
182        |       PUBLIC NAME '=' exp
183 			{ mri_public($2, $4); }
184        |       PUBLIC NAME ',' exp
185 			{ mri_public($2, $4); }
186        |       PUBLIC NAME  exp
187 			{ mri_public($2, $3); }
188	| 	FORMAT NAME
189			{ mri_format($2); }
190	|	SECT NAME ',' exp
191			{ mri_output_section($2, $4);}
192	|	SECT NAME  exp
193			{ mri_output_section($2, $3);}
194	|	SECT NAME '=' exp
195			{ mri_output_section($2, $4);}
196	|	ALIGN_K NAME '=' exp
197			{ mri_align($2,$4); }
198	|	ALIGN_K NAME ',' exp
199			{ mri_align($2,$4); }
200	|	ALIGNMOD NAME '=' exp
201			{ mri_alignmod($2,$4); }
202	|	ALIGNMOD NAME ',' exp
203			{ mri_alignmod($2,$4); }
204	|	ABSOLUTE mri_abs_name_list
205	|	LOAD	 mri_load_name_list
206	|       NAMEWORD NAME
207			{ mri_name($2); }
208	|	ALIAS NAME ',' NAME
209			{ mri_alias($2,$4,0);}
210	|	ALIAS NAME ',' INT
211			{ mri_alias($2,0,(int) $4);}
212	|	BASE     exp
213			{ mri_base($2); }
214        |       TRUNCATE INT
215		{  mri_truncate((unsigned int) $2); }
216	|	CASE casesymlist
217	|	EXTERN extern_name_list
218	|	INCLUDE filename
219		{ ldfile_open_command_file ($2); } mri_script_lines END
220	|	START NAME
221		{ lang_add_entry ($2, false); }
222        |
223	;
224
225ordernamelist:
226	      ordernamelist ',' NAME         { mri_order($3); }
227	|     ordernamelist  NAME         { mri_order($2); }
228      	|
229	;
230
231mri_load_name_list:
232		NAME
233			{ mri_load($1); }
234	|	mri_load_name_list ',' NAME { mri_load($3); }
235	;
236
237mri_abs_name_list:
238 		NAME
239 			{ mri_only_load($1); }
240	|	mri_abs_name_list ','  NAME
241 			{ mri_only_load($3); }
242	;
243
244casesymlist:
245	  /* empty */ { $$ = NULL; }
246	| NAME
247	| casesymlist ',' NAME
248	;
249
250extern_name_list:
251	  NAME
252			{ ldlang_add_undef ($1); }
253	| extern_name_list ',' NAME
254			{ ldlang_add_undef ($3); }
255	;
256
257script_file:
258	{
259	 ldlex_both();
260	}
261       ifile_list
262	{
263	ldlex_popstate();
264	}
265        ;
266
267
268ifile_list:
269       ifile_list ifile_p1
270        |
271	;
272
273
274
275ifile_p1:
276		memory
277	|	sections
278	|	phdrs
279	|	startup
280	|	high_level_library
281	|	low_level_library
282	|	floating_point_support
283	|	statement_anywhere
284        |	 ';'
285	|	TARGET_K '(' NAME ')'
286		{ lang_add_target($3); }
287	|	SEARCH_DIR '(' filename ')'
288		{ ldfile_add_library_path ($3, false); }
289	|	OUTPUT '(' filename ')'
290		{ lang_add_output($3, 1); }
291        |	OUTPUT_FORMAT '(' NAME ')'
292		  { lang_add_output_format ($3, (char *) NULL,
293					    (char *) NULL, 1); }
294	|	OUTPUT_FORMAT '(' NAME ',' NAME ',' NAME ')'
295		  { lang_add_output_format ($3, $5, $7, 1); }
296        |	OUTPUT_ARCH '(' NAME ')'
297		  { ldfile_set_output_arch($3); }
298	|	FORCE_COMMON_ALLOCATION
299		{ command_line.force_common_definition = true ; }
300	|	INPUT '(' input_list ')'
301	|	GROUP
302		  { lang_enter_group (); }
303		    '(' input_list ')'
304		  { lang_leave_group (); }
305     	|	MAP '(' filename ')'
306		{ lang_add_map($3); }
307	|	INCLUDE filename
308		{ ldfile_open_command_file($2); } ifile_list END
309	|	NOCROSSREFS '(' nocrossref_list ')'
310		{
311		  lang_add_nocrossref ($3);
312		}
313	;
314
315input_list:
316		NAME
317		{ lang_add_input_file($1,lang_input_file_is_search_file_enum,
318				 (char *)NULL); }
319	|	input_list ',' NAME
320		{ lang_add_input_file($3,lang_input_file_is_search_file_enum,
321				 (char *)NULL); }
322	|	input_list NAME
323		{ lang_add_input_file($2,lang_input_file_is_search_file_enum,
324				 (char *)NULL); }
325	|	LNAME
326		{ lang_add_input_file($1,lang_input_file_is_l_enum,
327				 (char *)NULL); }
328	|	input_list ',' LNAME
329		{ lang_add_input_file($3,lang_input_file_is_l_enum,
330				 (char *)NULL); }
331	|	input_list LNAME
332		{ lang_add_input_file($2,lang_input_file_is_l_enum,
333				 (char *)NULL); }
334	;
335
336sections:
337		SECTIONS '{' sec_or_group_p1 '}'
338	;
339
340sec_or_group_p1:
341		sec_or_group_p1 section
342	|	sec_or_group_p1 statement_anywhere
343	|
344	;
345
346statement_anywhere:
347		ENTRY '(' NAME ')'
348		{ lang_add_entry ($3, false); }
349	|	assignment end
350	;
351
352/* The '*' and '?' cases are there because the lexer returns them as
353   separate tokens rather than as NAME.  */
354file_NAME_list:
355		NAME
356			{ lang_add_wild ($1, current_file); }
357	|	'*'
358			{ lang_add_wild ("*", current_file); }
359	|	'?'
360			{ lang_add_wild ("?", current_file); }
361	|	file_NAME_list opt_comma NAME
362			{ lang_add_wild ($3, current_file); }
363	|	file_NAME_list opt_comma '*'
364			{ lang_add_wild ("*", current_file); }
365	|	file_NAME_list opt_comma '?'
366			{ lang_add_wild ("?", current_file); }
367	;
368
369input_section_spec:
370		NAME
371		{
372		lang_add_wild((char *)NULL, $1);
373		}
374        |	'['
375			{
376			current_file = (char *)NULL;
377			}
378			file_NAME_list
379		']'
380	|	NAME
381			{
382			current_file = $1;
383			}
384		'(' file_NAME_list ')'
385	|	'?'
386		/* This case is needed because the lexer returns a
387                   single question mark as '?' rather than NAME.  */
388			{
389			current_file = "?";
390			}
391		'(' file_NAME_list ')'
392	|	'*'
393			{
394			current_file = (char *)NULL;
395			}
396		'(' file_NAME_list ')'
397	;
398
399statement:
400	  	assignment end
401	|	CREATE_OBJECT_SYMBOLS
402		{
403 		lang_add_attribute(lang_object_symbols_statement_enum);
404	      	}
405        |	';'
406        |	CONSTRUCTORS
407		{
408
409		  lang_add_attribute(lang_constructors_statement_enum);
410		}
411	| input_section_spec
412        | length '(' mustbe_exp ')'
413        	        {
414			lang_add_data((int) $1,$3);
415			}
416
417	| FILL '(' mustbe_exp ')'
418			{
419			  lang_add_fill
420			    (exp_get_value_int($3,
421					       0,
422					       "fill value",
423					       lang_first_phase_enum));
424			}
425	;
426
427statement_list:
428		statement_list statement
429  	|  	statement
430	;
431
432statement_list_opt:
433		/* empty */
434	|	statement_list
435	;
436
437length:
438		QUAD
439			{ $$ = $1; }
440	|	LONG
441			{ $$ = $1; }
442	| 	SHORT
443			{ $$ = $1; }
444	|	BYTE
445			{ $$ = $1; }
446	;
447
448fill_opt:
449          '=' mustbe_exp
450		{
451		  $$ =	 exp_get_value_int($2,
452					   0,
453					   "fill value",
454					   lang_first_phase_enum);
455		}
456	| 	{ $$ = 0; }
457	;
458
459
460
461assign_op:
462		PLUSEQ
463			{ $$ = '+'; }
464	|	MINUSEQ
465			{ $$ = '-'; }
466	| 	MULTEQ
467			{ $$ = '*'; }
468	| 	DIVEQ
469			{ $$ = '/'; }
470	| 	LSHIFTEQ
471			{ $$ = LSHIFT; }
472	| 	RSHIFTEQ
473			{ $$ = RSHIFT; }
474	| 	ANDEQ
475			{ $$ = '&'; }
476	| 	OREQ
477			{ $$ = '|'; }
478
479	;
480
481end:	';' | ','
482	;
483
484
485assignment:
486		NAME '=' mustbe_exp
487		{
488		  lang_add_assignment (exp_assop ($2, $1, $3));
489		}
490	|	NAME assign_op mustbe_exp
491		{
492		  lang_add_assignment (exp_assop ('=', $1,
493						  exp_binop ($2,
494							     exp_nameop (NAME,
495									 $1),
496							     $3)));
497		}
498	|	PROVIDE '(' NAME '=' mustbe_exp ')'
499		{
500		  lang_add_assignment (exp_provide ($3, $5));
501		}
502	;
503
504
505opt_comma:
506		','	|	;
507
508
509memory:
510		MEMORY '{' memory_spec memory_spec_list '}'
511	;
512
513memory_spec_list:
514		memory_spec_list memory_spec
515	|	memory_spec_list ',' memory_spec
516	|
517	;
518
519
520memory_spec: 		NAME
521			{ region = lang_memory_region_lookup($1); }
522		attributes_opt ':'
523		origin_spec opt_comma length_spec
524
525	; origin_spec:
526	ORIGIN '=' mustbe_exp
527		{ region->current =
528		 region->origin =
529		 exp_get_vma($3, 0L,"origin", lang_first_phase_enum);
530}
531	; length_spec:
532             LENGTH '=' mustbe_exp
533               { region->length = exp_get_vma($3,
534					       ~((bfd_vma)0),
535					       "length",
536					       lang_first_phase_enum);
537		}
538
539
540attributes_opt:
541		  '(' NAME ')'
542			{
543			lang_set_flags(&region->flags, $2);
544			}
545	|
546
547	;
548
549startup:
550	STARTUP '(' filename ')'
551		{ lang_startup($3); }
552	;
553
554high_level_library:
555		HLL '(' high_level_library_NAME_list ')'
556	|	HLL '(' ')'
557			{ ldemul_hll((char *)NULL); }
558	;
559
560high_level_library_NAME_list:
561		high_level_library_NAME_list opt_comma filename
562			{ ldemul_hll($3); }
563	|	filename
564			{ ldemul_hll($1); }
565
566	;
567
568low_level_library:
569	SYSLIB '(' low_level_library_NAME_list ')'
570	; low_level_library_NAME_list:
571		low_level_library_NAME_list opt_comma filename
572			{ ldemul_syslib($3); }
573	|
574	;
575
576floating_point_support:
577		FLOAT
578			{ lang_float(true); }
579	|	NOFLOAT
580			{ lang_float(false); }
581	;
582
583nocrossref_list:
584		/* empty */
585		{
586		  $$ = NULL;
587		}
588	|	NAME nocrossref_list
589		{
590		  struct lang_nocrossref *n;
591
592		  n = (struct lang_nocrossref *) xmalloc (sizeof *n);
593		  n->name = $1;
594		  n->next = $2;
595		  $$ = n;
596		}
597	|	NAME ',' nocrossref_list
598		{
599		  struct lang_nocrossref *n;
600
601		  n = (struct lang_nocrossref *) xmalloc (sizeof *n);
602		  n->name = $1;
603		  n->next = $3;
604		  $$ = n;
605		}
606	;
607
608mustbe_exp:		 { ldlex_expression(); }
609		exp
610			 { ldlex_popstate(); $$=$2;}
611	;
612
613exp	:
614		'-' exp %prec UNARY
615			{ $$ = exp_unop('-', $2); }
616	|	'(' exp ')'
617			{ $$ = $2; }
618	|	NEXT '(' exp ')' %prec UNARY
619			{ $$ = exp_unop((int) $1,$3); }
620	|	'!' exp %prec UNARY
621			{ $$ = exp_unop('!', $2); }
622	|	'+' exp %prec UNARY
623			{ $$ = $2; }
624	|	'~' exp %prec UNARY
625			{ $$ = exp_unop('~', $2);}
626
627	|	exp '*' exp
628			{ $$ = exp_binop('*', $1, $3); }
629	|	exp '/' exp
630			{ $$ = exp_binop('/', $1, $3); }
631	|	exp '%' exp
632			{ $$ = exp_binop('%', $1, $3); }
633	|	exp '+' exp
634			{ $$ = exp_binop('+', $1, $3); }
635	|	exp '-' exp
636			{ $$ = exp_binop('-' , $1, $3); }
637	|	exp LSHIFT exp
638			{ $$ = exp_binop(LSHIFT , $1, $3); }
639	|	exp RSHIFT exp
640			{ $$ = exp_binop(RSHIFT , $1, $3); }
641	|	exp EQ exp
642			{ $$ = exp_binop(EQ , $1, $3); }
643	|	exp NE exp
644			{ $$ = exp_binop(NE , $1, $3); }
645	|	exp LE exp
646			{ $$ = exp_binop(LE , $1, $3); }
647  	|	exp GE exp
648			{ $$ = exp_binop(GE , $1, $3); }
649	|	exp '<' exp
650			{ $$ = exp_binop('<' , $1, $3); }
651	|	exp '>' exp
652			{ $$ = exp_binop('>' , $1, $3); }
653	|	exp '&' exp
654			{ $$ = exp_binop('&' , $1, $3); }
655	|	exp '^' exp
656			{ $$ = exp_binop('^' , $1, $3); }
657	|	exp '|' exp
658			{ $$ = exp_binop('|' , $1, $3); }
659	|	exp '?' exp ':' exp
660			{ $$ = exp_trinop('?' , $1, $3, $5); }
661	|	exp ANDAND exp
662			{ $$ = exp_binop(ANDAND , $1, $3); }
663	|	exp OROR exp
664			{ $$ = exp_binop(OROR , $1, $3); }
665	|	DEFINED '(' NAME ')'
666			{ $$ = exp_nameop(DEFINED, $3); }
667	|	INT
668			{ $$ = exp_intop($1); }
669        |	SIZEOF_HEADERS
670			{ $$ = exp_nameop(SIZEOF_HEADERS,0); }
671
672	|	SIZEOF '(' NAME ')'
673			{ $$ = exp_nameop(SIZEOF,$3); }
674	|	ADDR '(' NAME ')'
675			{ $$ = exp_nameop(ADDR,$3); }
676	|	LOADADDR '(' NAME ')'
677			{ $$ = exp_nameop(LOADADDR,$3); }
678	|	ABSOLUTE '(' exp ')'
679			{ $$ = exp_unop(ABSOLUTE, $3); }
680	|	ALIGN_K '(' exp ')'
681			{ $$ = exp_unop(ALIGN_K,$3); }
682	|	BLOCK '(' exp ')'
683			{ $$ = exp_unop(ALIGN_K,$3); }
684	|	NAME
685			{ $$ = exp_nameop(NAME,$1); }
686	|	MAX '(' exp ',' exp ')'
687			{ $$ = exp_binop (MAX, $3, $5 ); }
688	|	MIN '(' exp ',' exp ')'
689			{ $$ = exp_binop (MIN, $3, $5 ); }
690	;
691
692
693opt_at:
694		AT '(' exp ')' { $$ = $3; }
695	|	{ $$ = 0; }
696	;
697
698section:	NAME 		{ ldlex_expression(); }
699		opt_exp_with_type
700		opt_at   	{ ldlex_popstate (); ldlex_script (); }
701		'{'
702			{
703			  lang_enter_output_section_statement($1, $3,
704							      sectype,
705							      0, 0, 0, $4);
706			}
707		statement_list_opt
708 		'}' { ldlex_popstate (); ldlex_expression (); }
709		memspec_opt phdr_opt fill_opt
710		{
711		  ldlex_popstate ();
712		  lang_leave_output_section_statement ($13, $11, $12);
713		}
714		opt_comma
715	|	OVERLAY
716			{ ldlex_expression (); }
717		opt_exp_without_type opt_nocrossrefs opt_at
718			{ ldlex_popstate (); ldlex_script (); }
719		'{'
720			{
721			  lang_enter_overlay ($3, $5, (int) $4);
722			}
723		overlay_section
724		'}'
725			{ ldlex_popstate (); ldlex_expression (); }
726		memspec_opt phdr_opt fill_opt
727			{
728			  ldlex_popstate ();
729			  lang_leave_overlay ($14, $12, $13);
730			}
731		opt_comma
732	|	/* The GROUP case is just enough to support the gcc
733		   svr3.ifile script.  It is not intended to be full
734		   support.  I'm not even sure what GROUP is supposed
735		   to mean.  */
736		GROUP { ldlex_expression (); }
737		opt_exp_with_type
738		{
739		  ldlex_popstate ();
740		  lang_add_assignment (exp_assop ('=', ".", $3));
741		}
742		'{' sec_or_group_p1 '}'
743	;
744
745type:
746	   NOLOAD  { sectype = noload_section; }
747	|  DSECT   { sectype = dsect_section; }
748	|  COPY    { sectype = copy_section; }
749	|  INFO    { sectype = info_section; }
750	|  OVERLAY { sectype = overlay_section; }
751	;
752
753atype:
754	 	'(' type ')'
755  	| 	/* EMPTY */ { sectype = normal_section; }
756	;
757
758opt_exp_with_type:
759		exp atype ':'		{ $$ = $1; }
760	|	atype ':'		{ $$ = (etree_type *)NULL;  }
761	|	/* The BIND cases are to support the gcc svr3.ifile
762		   script.  They aren't intended to implement full
763		   support for the BIND keyword.  I'm not even sure
764		   what BIND is supposed to mean.  */
765		BIND '(' exp ')' atype ':' { $$ = $3; }
766	|	BIND '(' exp ')' BLOCK '(' exp ')' atype ':'
767		{ $$ = $3; }
768	;
769
770opt_exp_without_type:
771		exp ':'		{ $$ = $1; }
772	|	':'		{ $$ = (etree_type *) NULL;  }
773	;
774
775opt_nocrossrefs:
776		/* empty */
777			{ $$ = 0; }
778	|	NOCROSSREFS
779			{ $$ = 1; }
780	;
781
782memspec_opt:
783		'>' NAME
784		{ $$ = $2; }
785	|	{ $$ = "*default*"; }
786	;
787
788phdr_opt:
789		/* empty */
790		{
791		  $$ = NULL;
792		}
793	|	phdr_opt ':' NAME
794		{
795		  struct lang_output_section_phdr_list *n;
796
797		  n = ((struct lang_output_section_phdr_list *)
798		       xmalloc (sizeof *n));
799		  n->name = $3;
800		  n->used = false;
801		  n->next = $1;
802		  $$ = n;
803		}
804	;
805
806overlay_section:
807		/* empty */
808	|	overlay_section
809		NAME
810			{
811			  ldlex_script ();
812			  lang_enter_overlay_section ($2);
813			}
814		'{' statement_list_opt '}'
815			{ ldlex_popstate (); ldlex_expression (); }
816		phdr_opt fill_opt
817			{
818			  ldlex_popstate ();
819			  lang_leave_overlay_section ($9, $8);
820			}
821		opt_comma
822	;
823
824phdrs:
825		PHDRS '{' phdr_list '}'
826	;
827
828phdr_list:
829		/* empty */
830	|	phdr_list phdr
831	;
832
833phdr:
834		NAME { ldlex_expression (); }
835		  phdr_type phdr_qualifiers { ldlex_popstate (); }
836		  ';'
837		{
838		  lang_new_phdr ($1, $3, $4.filehdr, $4.phdrs, $4.at,
839				 $4.flags);
840		}
841	;
842
843phdr_type:
844		exp
845		{
846		  $$ = $1;
847
848		  if ($1->type.node_class == etree_name
849		      && $1->type.node_code == NAME)
850		    {
851		      const char *s;
852		      unsigned int i;
853		      static const char * const phdr_types[] =
854			{
855			  "PT_NULL", "PT_LOAD", "PT_DYNAMIC",
856			  "PT_INTERP", "PT_NOTE", "PT_SHLIB",
857			  "PT_PHDR"
858			};
859
860		      s = $1->name.name;
861		      for (i = 0;
862			   i < sizeof phdr_types / sizeof phdr_types[0];
863			   i++)
864			if (strcmp (s, phdr_types[i]) == 0)
865			  {
866			    $$ = exp_intop (i);
867			    break;
868			  }
869		    }
870		}
871	;
872
873phdr_qualifiers:
874		/* empty */
875		{
876		  memset (&$$, 0, sizeof (struct phdr_info));
877		}
878	|	NAME phdr_val phdr_qualifiers
879		{
880		  $$ = $3;
881		  if (strcmp ($1, "FILEHDR") == 0 && $2 == NULL)
882		    $$.filehdr = true;
883		  else if (strcmp ($1, "PHDRS") == 0 && $2 == NULL)
884		    $$.phdrs = true;
885		  else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL)
886		    $$.flags = $2;
887		  else
888		    einfo ("%X%P:%S: PHDRS syntax error at `%s'\n", $1);
889		}
890	|	AT '(' exp ')' phdr_qualifiers
891		{
892		  $$ = $5;
893		  $$.at = $3;
894		}
895	;
896
897phdr_val:
898		/* empty */
899		{
900		  $$ = NULL;
901		}
902	| '(' exp ')'
903		{
904		  $$ = $2;
905		}
906	;
907
908%%
909void
910yyerror(arg)
911     const char *arg;
912{
913  if (ldfile_assumed_script)
914    einfo ("%P:%s: file format not recognized; treating as linker script\n",
915	   ldfile_input_filename);
916  if (error_index > 0 && error_index < ERROR_NAME_MAX)
917     einfo ("%P%F:%S: %s in %s\n", arg, error_names[error_index-1]);
918  else
919     einfo ("%P%F:%S: %s\n", arg);
920}
921