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