xref: /netbsd-src/external/gpl3/binutils/dist/ld/ldlex.l (revision dd7241df2fae9da4ea2bd20a68f001fa86ecf909)
1 %option nounput noyywrap
2 
3 %{
4 
5 /* Copyright (C) 1991-2024 Free Software Foundation, Inc.
6    Written by Steve Chamberlain of Cygnus Support.
7 
8    This file is part of the GNU Binutils.
9 
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23    MA 02110-1301, USA.  */
24 
25 #include "bfd.h"
26 #include "safe-ctype.h"
27 #include "bfdlink.h"
28 #include "ctf-api.h"
29 #include "ld.h"
30 #include "ldmisc.h"
31 #include "ldexp.h"
32 #include "ldlang.h"
33 #include <ldgram.h>
34 #include "ldfile.h"
35 #include "ldlex.h"
36 #include "ldmain.h"
37 #include "libiberty.h"
38 
39 /* The type of top-level parser input.
40    yylex and yyparse (indirectly) both check this.  */
41 input_type parser_input;
42 
43 /* Line number in the current input file.  */
44 unsigned int lineno;
45 
46 /* The string we are currently lexing, or NULL if we are reading a
47    file.  */
48 const char *lex_string = NULL;
49 
50 /* Support for flex reading from more than one input file (stream).
51    `include_stack' is flex's input state for each open file;
52    `file_name_stack' is the file names.  `lineno_stack' is the current
53    line numbers.
54 
55    If `include_stack_ptr' is 0, we haven't started reading anything yet.
56    Otherwise, stack elements 0 through `include_stack_ptr - 1' are valid.  */
57 
58 #undef YY_INPUT
59 #define YY_INPUT(buf,result,max_size) result = yy_input (buf, max_size)
60 
61 #define MAX_INCLUDE_DEPTH 10
62 static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
63 static const char *file_name_stack[MAX_INCLUDE_DEPTH];
64 static unsigned int lineno_stack[MAX_INCLUDE_DEPTH];
65 static unsigned int sysrooted_stack[MAX_INCLUDE_DEPTH];
66 static unsigned int include_stack_ptr = 0;
67 static int vers_node_nesting = 0;
68 
69 static int yy_input (char *, int);
70 static void comment (void);
71 static void lex_warn_invalid (char *where, char *what);
72 
73 /* STATES
74 	EXPRESSION	in an expression
75 	SCRIPT		in a script
76 	INPUTLIST	in a script, a filename-list
77 	MRI		in an MRI script
78 	WILD		inside the braces of an output section or overlay,
79 			for input section wildcards
80 	VERS_START	starting a Sun style mapfile
81 	VERS_SCRIPT	a Sun style mapfile
82 	VERS_NODE	a node within a Sun style mapfile
83 */
84 #define RTOKEN(x)  {  yylval.token = x; return x; }
85 
86 %}
87 
88 %option nounput
89 
90 %a 4000
91 %o 5000
92 
93 WILDCHAR	[_a-zA-Z0-9\/\.\\\$\~\-\+\:\[\]\,\=\?\*\^\!]
94 FILENAMECHAR	[_a-zA-Z0-9\/\.\\\$\~\-\+\:\[\]\,\=]
95 NOCFILENAMECHAR	[_a-zA-Z0-9\/\.\\\$\~\-\+\:\[\]]
96 SYMBOLNAMECHAR  [_a-zA-Z0-9\/\.\\\$\~]
97 FILENAMECHAR1	[_a-zA-Z\/\.\\\$\~]
98 SYMBOLNAMECHAR1	[_a-zA-Z\.\\\$]
99 WHITE		[ \t\n\r]+
100 
101 V_TAG [.$_a-zA-Z][._a-zA-Z0-9]*
102 V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
103 
104 %s SCRIPT
105 %s INPUTLIST
106 %s EXPRESSION
107 %s MRI
108 %s WILD
109 %s VERS_START
110 %s VERS_SCRIPT
111 %s VERS_NODE
112 %%
113 
114   if (parser_input != input_selected)
115     {
116       /* The first token of the input determines the initial parser state.  */
117       input_type t = parser_input;
118       parser_input = input_selected;
119       switch (t)
120 	{
121 	case input_script: return INPUT_SCRIPT; break;
122 	case input_mri_script: return INPUT_MRI_SCRIPT; break;
123 	case input_version_script: return INPUT_VERSION_SCRIPT; break;
124 	case input_dynamic_list: return INPUT_DYNAMIC_LIST; break;
125 	case input_defsym: return INPUT_DEFSYM; break;
126 	default: abort ();
127 	}
128     }
129 
130 <SCRIPT,EXPRESSION,VERS_START,VERS_NODE,VERS_SCRIPT,INPUTLIST>"/*" {
131 				comment (); }
132 
133 <MRI,EXPRESSION>"$"([0-9A-Fa-f])+ {
134 				yylval.integer = strtoull (yytext + 1, 0, 16);
135 				yylval.bigint.str = NULL;
136 				return INT;
137 			}
138 
139 <MRI,EXPRESSION>([0-9A-Fa-f])+(H|h|X|x|B|b|O|o|D|d) {
140 				   int ibase ;
141 				   switch (yytext[yyleng - 1]) {
142 				    case 'X':
143 				    case 'x':
144 				    case 'H':
145 				    case 'h':
146 				     ibase = 16;
147 				     break;
148 				    case 'O':
149 				    case 'o':
150 				     ibase = 8;
151 				     break;
152 				    case 'B':
153 				    case 'b':
154 				     ibase = 2;
155 				     break;
156 				    default:
157 				     ibase = 10;
158 				   }
159 				   yylval.integer = strtoull (yytext, 0, ibase);
160 				   yylval.bigint.str = NULL;
161 				   return INT;
162 				 }
163 <SCRIPT,MRI,EXPRESSION>((("$"|0[xX])([0-9A-Fa-f])+)|(([0-9])+))(M|K|m|k)? {
164 				  char *s = yytext;
165 				  int ibase = 0;
166 
167 				  if (*s == '$')
168 				    {
169 				      ++s;
170 				      ibase = 16;
171 				    }
172 				  yylval.integer = strtoull (s, 0, ibase);
173 				  yylval.bigint.str = NULL;
174 				  if (yytext[yyleng - 1] == 'M'
175 				      || yytext[yyleng - 1] == 'm')
176 				    {
177 				      yylval.integer *= 1024 * 1024;
178 				    }
179 				  else if (yytext[yyleng - 1] == 'K'
180 				      || yytext[yyleng - 1]=='k')
181 				    {
182 				      yylval.integer *= 1024;
183 				    }
184 				  else if (yytext[0] == '0'
185 					   && (yytext[1] == 'x'
186 					       || yytext[1] == 'X'))
187 				    {
188 				      yylval.bigint.str = xstrdup (yytext + 2);
189 				    }
190 				  return INT;
191 				}
192 
193   /* Some tokens that only appear in expressions must be enabled for
194      states other than EXPRESSION, since parser lookahead means they
195      must be recognised before the parser switches the lexer out of
196      SCRIPT or WILD state into EXPRESSION state.
197 
198      This sort of thing happens for example with NAME in ldgram.y
199      "section" rule, which is immediately followed by ldlex_expression.
200      However, if you follow the grammar from "sec_or_group_p1" you see
201      "assignment" appearing in "statement_anywhere".  Now,
202      "assignment" also has NAME as its first token, just like
203      "section".  So the parser can't know whether it is in the
204      "section" or the "assignment" rule until it has scanned the next
205      token to find an assignment operator.  Thus the next token after
206      NAME in the "section" rule may be lexed before the lexer is
207      switched to EXPRESSION state, and there are quite a number of
208      optional components.  The first token in all those components
209      must be able to be lexed in SCRIPT state, as well as the
210      assignment operators.  In fact, due to "opt_exp_with_type",
211      anything that can appear on the left hand side of "exp" might
212      need to be lexed in SCRIPT state.
213 
214      MRI mode tends to cover everything in MRI scripts.
215   */
216 <MRI,WILD>"]"				{ RTOKEN(']'); }
217 <MRI,WILD>"["				{ RTOKEN('['); }
218 <SCRIPT,EXPRESSION,MRI,WILD>"<<="	{ RTOKEN(LSHIFTEQ); }
219 <SCRIPT,EXPRESSION,MRI,WILD>">>="	{ RTOKEN(RSHIFTEQ); }
220 <EXPRESSION,MRI>"||"			{ RTOKEN(OROR); }
221 <EXPRESSION,MRI>"=="			{ RTOKEN(EQ); }
222 <EXPRESSION,MRI>"!="			{ RTOKEN(NE); }
223 <EXPRESSION,MRI>">="			{ RTOKEN(GE); }
224 <EXPRESSION,MRI>"<="			{ RTOKEN(LE); }
225 <EXPRESSION,MRI>"<<"			{ RTOKEN(LSHIFT); }
226 <EXPRESSION,MRI>">>"			{ RTOKEN(RSHIFT); }
227 <SCRIPT,EXPRESSION,MRI,WILD>"+="	{ RTOKEN(PLUSEQ); }
228 <SCRIPT,EXPRESSION,MRI,WILD>"-="	{ RTOKEN(MINUSEQ); }
229 <SCRIPT,EXPRESSION,MRI,WILD>"*="	{ RTOKEN(MULTEQ); }
230 <SCRIPT,EXPRESSION,MRI,WILD>"/="	{ RTOKEN(DIVEQ); }
231 <SCRIPT,EXPRESSION,MRI,WILD>"&="	{ RTOKEN(ANDEQ); }
232 <SCRIPT,EXPRESSION,MRI,WILD>"|="	{ RTOKEN(OREQ); }
233 <SCRIPT,EXPRESSION,MRI,WILD>"^="	{ RTOKEN(XOREQ); }
234 <EXPRESSION,MRI>"&&"			{ RTOKEN(ANDAND); }
235 <SCRIPT,EXPRESSION,MRI>">"		{ RTOKEN('>'); }
236 <SCRIPT,EXPRESSION,MRI,INPUTLIST>","	{ RTOKEN(','); }
237 <EXPRESSION,MRI,WILD>"&"		{ RTOKEN('&'); }
238 <EXPRESSION,MRI>"|"			{ RTOKEN('|'); }
239 <SCRIPT,EXPRESSION,MRI>"~"		{ RTOKEN('~'); }
240 <SCRIPT,EXPRESSION,MRI>"!"		{ RTOKEN('!'); }
241 <EXPRESSION,MRI>"?"			{ RTOKEN('?'); }
242 <EXPRESSION,MRI>"*"			{ RTOKEN('*'); }
243 <SCRIPT,EXPRESSION,MRI>"+"		{ RTOKEN('+'); }
244 <SCRIPT,EXPRESSION,MRI>"-"		{ RTOKEN('-'); }
245 <EXPRESSION,MRI>"/"			{ RTOKEN('/'); }
246 <EXPRESSION,MRI>"%"			{ RTOKEN('%'); }
247 <EXPRESSION,MRI>"<"			{ RTOKEN('<'); }
248 <EXPRESSION,MRI>"^"			{ RTOKEN('^'); }
249 <SCRIPT,EXPRESSION,MRI,WILD>"="		{ RTOKEN('='); }
250 <SCRIPT,EXPRESSION,MRI,WILD>"}"		{ RTOKEN('}'); }
251 <SCRIPT,EXPRESSION,MRI,WILD>"{"		{ RTOKEN('{'); }
252 <SCRIPT,EXPRESSION,MRI,WILD,INPUTLIST>")" { RTOKEN(')'); }
253 <SCRIPT,EXPRESSION,MRI,WILD,INPUTLIST>"(" { RTOKEN('('); }
254 <SCRIPT,EXPRESSION,MRI>":"		{ RTOKEN(':'); }
255 <SCRIPT,EXPRESSION,MRI,WILD>";"		{ RTOKEN(';'); }
256 <SCRIPT>"MEMORY"			{ RTOKEN(MEMORY); }
257 <SCRIPT>"REGION_ALIAS"			{ RTOKEN(REGION_ALIAS); }
258 <SCRIPT>"LD_FEATURE"			{ RTOKEN(LD_FEATURE); }
259 <SCRIPT,EXPRESSION>"ORIGIN"		{ RTOKEN(ORIGIN); }
260 <SCRIPT>"VERSION"			{ RTOKEN(VERSIONK); }
261 <SCRIPT,EXPRESSION>"BLOCK"		{ RTOKEN(BLOCK); }
262 <SCRIPT,EXPRESSION>"BIND"		{ RTOKEN(BIND); }
263 <SCRIPT,EXPRESSION>"LENGTH"		{ RTOKEN(LENGTH); }
264 <SCRIPT,EXPRESSION>"ALIGN"		{ RTOKEN(ALIGN_K); }
265 <SCRIPT,EXPRESSION>"DATA_SEGMENT_ALIGN"	{ RTOKEN(DATA_SEGMENT_ALIGN); }
266 <SCRIPT,EXPRESSION>"DATA_SEGMENT_RELRO_END" { RTOKEN(DATA_SEGMENT_RELRO_END); }
267 <SCRIPT,EXPRESSION>"DATA_SEGMENT_END"	{ RTOKEN(DATA_SEGMENT_END); }
268 <SCRIPT,EXPRESSION>"ADDR"		{ RTOKEN(ADDR); }
269 <SCRIPT,EXPRESSION>"LOADADDR"		{ RTOKEN(LOADADDR); }
270 <SCRIPT,EXPRESSION>"ALIGNOF"		{ RTOKEN(ALIGNOF); }
271 <SCRIPT,EXPRESSION>"ABSOLUTE"		{ RTOKEN(ABSOLUTE); }
272 <SCRIPT,EXPRESSION>"MAX"		{ RTOKEN(MAX_K); }
273 <SCRIPT,EXPRESSION>"MIN"		{ RTOKEN(MIN_K); }
274 <SCRIPT,EXPRESSION>"LOG2CEIL"		{ RTOKEN(LOG2CEIL); }
275 <SCRIPT,EXPRESSION,WILD>"ASSERT"	{ RTOKEN(ASSERT_K); }
276 <SCRIPT>"ENTRY"				{ RTOKEN(ENTRY); }
277 <SCRIPT,MRI>"EXTERN"			{ RTOKEN(EXTERN); }
278 <SCRIPT,EXPRESSION>"NEXT"		{ RTOKEN(NEXT); }
279 <SCRIPT,EXPRESSION>"SIZEOF_HEADERS"	{ RTOKEN(SIZEOF_HEADERS); }
280 <SCRIPT,EXPRESSION>"SEGMENT_START"	{ RTOKEN(SEGMENT_START); }
281 <SCRIPT>"MAP"				{ RTOKEN(MAP); }
282 <SCRIPT,EXPRESSION>"SIZEOF"		{ RTOKEN(SIZEOF); }
283 <SCRIPT>"TARGET"			{ RTOKEN(TARGET_K); }
284 <SCRIPT>"SEARCH_DIR"			{ RTOKEN(SEARCH_DIR); }
285 <SCRIPT>"OUTPUT"			{ RTOKEN(OUTPUT); }
286 <SCRIPT>"INPUT"				{ RTOKEN(INPUT); }
287 <SCRIPT>"GROUP"				{ RTOKEN(GROUP); }
288 <INPUTLIST>"AS_NEEDED"			{ RTOKEN(AS_NEEDED); }
289 <SCRIPT,EXPRESSION>"DEFINED"		{ RTOKEN(DEFINED); }
290 <WILD>"CREATE_OBJECT_SYMBOLS"		{ RTOKEN(CREATE_OBJECT_SYMBOLS); }
291 <WILD>"CONSTRUCTORS"			{ RTOKEN(CONSTRUCTORS); }
292 <SCRIPT>"FORCE_COMMON_ALLOCATION"	{ RTOKEN(FORCE_COMMON_ALLOCATION); }
293 <SCRIPT>"FORCE_GROUP_ALLOCATION"	{ RTOKEN(FORCE_GROUP_ALLOCATION); }
294 <SCRIPT>"INHIBIT_COMMON_ALLOCATION"	{ RTOKEN(INHIBIT_COMMON_ALLOCATION); }
295 <SCRIPT>"SECTIONS"			{ RTOKEN(SECTIONS); }
296 <SCRIPT>"INSERT"			{ RTOKEN(INSERT_K); }
297 <SCRIPT>"AFTER"				{ RTOKEN(AFTER); }
298 <SCRIPT>"BEFORE"			{ RTOKEN(BEFORE); }
299 <WILD>"FILL"				{ RTOKEN(FILL); }
300 <SCRIPT>"STARTUP"			{ RTOKEN(STARTUP); }
301 <SCRIPT>"OUTPUT_FORMAT"			{ RTOKEN(OUTPUT_FORMAT); }
302 <SCRIPT>"OUTPUT_ARCH"			{ RTOKEN(OUTPUT_ARCH); }
303 <SCRIPT>"HLL"				{ RTOKEN(HLL); }
304 <SCRIPT>"SYSLIB"			{ RTOKEN(SYSLIB); }
305 <SCRIPT>"FLOAT"				{ RTOKEN(FLOAT); }
306 <WILD>"QUAD"				{ RTOKEN(QUAD); }
307 <WILD>"SQUAD"				{ RTOKEN(SQUAD); }
308 <WILD>"LONG"				{ RTOKEN(LONG); }
309 <WILD>"SHORT"				{ RTOKEN(SHORT); }
310 <WILD>"BYTE"				{ RTOKEN(BYTE); }
311 <WILD>"ASCIZ"				{ RTOKEN(ASCIZ); }
312 <WILD>"LINKER_VERSION"			{ RTOKEN(LINKER_VERSION); }
313 <SCRIPT>"NOFLOAT"			{ RTOKEN(NOFLOAT); }
314 <SCRIPT,EXPRESSION>"NOCROSSREFS"	{ RTOKEN(NOCROSSREFS); }
315 <SCRIPT,EXPRESSION>"NOCROSSREFS_TO"	{ RTOKEN(NOCROSSREFS_TO); }
316 <SCRIPT,EXPRESSION>"OVERLAY"		{ RTOKEN(OVERLAY); }
317 <WILD>"SORT_BY_NAME"			{ RTOKEN(SORT_BY_NAME); }
318 <WILD>"SORT_BY_ALIGNMENT"		{ RTOKEN(SORT_BY_ALIGNMENT); }
319 <WILD>"SORT"				{ RTOKEN(SORT_BY_NAME); }
320 <WILD>"SORT_BY_INIT_PRIORITY"		{ RTOKEN(SORT_BY_INIT_PRIORITY); }
321 <WILD>"SORT_NONE"			{ RTOKEN(SORT_NONE); }
322 <WILD>"REVERSE"				{ RTOKEN(REVERSE); }
323 <EXPRESSION>"NOLOAD"			{ RTOKEN(NOLOAD); }
324 <EXPRESSION>"READONLY"			{ RTOKEN(READONLY); }
325 <EXPRESSION>"DSECT"			{ RTOKEN(DSECT); }
326 <EXPRESSION>"COPY"			{ RTOKEN(COPY); }
327 <EXPRESSION>"INFO"			{ RTOKEN(INFO); }
328 <EXPRESSION>"TYPE"			{ RTOKEN(TYPE); }
329 <SCRIPT,EXPRESSION>"ONLY_IF_RO"		{ RTOKEN(ONLY_IF_RO); }
330 <SCRIPT,EXPRESSION>"ONLY_IF_RW"		{ RTOKEN(ONLY_IF_RW); }
331 <SCRIPT,EXPRESSION>"SPECIAL"		{ RTOKEN(SPECIAL); }
332 <SCRIPT>"o"				{ RTOKEN(ORIGIN); }
333 <SCRIPT>"org"				{ RTOKEN(ORIGIN); }
334 <SCRIPT>"l"				{ RTOKEN(LENGTH); }
335 <SCRIPT>"len"				{ RTOKEN(LENGTH); }
336 <WILD>"INPUT_SECTION_FLAGS"		{ RTOKEN(INPUT_SECTION_FLAGS); }
337 <SCRIPT,EXPRESSION,WILD,MRI>"INCLUDE"	{ RTOKEN(INCLUDE);}
338 <SCRIPT>"PHDRS"				{ RTOKEN(PHDRS); }
339 <SCRIPT,EXPRESSION,WILD>"AT"		{ RTOKEN(AT);}
340 <SCRIPT,EXPRESSION>"ALIGN_WITH_INPUT"	{ RTOKEN(ALIGN_WITH_INPUT);}
341 <SCRIPT,EXPRESSION>"SUBALIGN"		{ RTOKEN(SUBALIGN);}
342 <SCRIPT,EXPRESSION,WILD>"HIDDEN"	{ RTOKEN(HIDDEN); }
343 <SCRIPT,EXPRESSION,WILD>"PROVIDE"	{ RTOKEN(PROVIDE); }
344 <SCRIPT,EXPRESSION,WILD>"PROVIDE_HIDDEN" { RTOKEN(PROVIDE_HIDDEN); }
345 <WILD>"KEEP"				{ RTOKEN(KEEP); }
346 <WILD>"EXCLUDE_FILE"			{ RTOKEN(EXCLUDE_FILE); }
347 <SCRIPT,EXPRESSION>"CONSTANT"		{ RTOKEN(CONSTANT);}
348 
349 <MRI>"#".*\n?			{ ++ lineno; }
350 <MRI>"\n"			{ ++ lineno;  RTOKEN(NEWLINE); }
351 <MRI>"*".*			{ /* Mri comment line */ }
352 <MRI>";".*			{ /* Mri comment line */ }
353 <MRI>"END"			{ RTOKEN(ENDWORD); }
354 <MRI>"ABSOLUTE"			{ RTOKEN(ABSOLUTE); }
355 <MRI>"ALIGNMOD"			{ RTOKEN(ALIGNMOD);}
356 <MRI>"ALIGN"			{ RTOKEN(ALIGN_K);}
357 <MRI>"CHIP"			{ RTOKEN(CHIP); }
358 <MRI>"BASE"			{ RTOKEN(BASE); }
359 <MRI>"ALIAS"			{ RTOKEN(ALIAS); }
360 <MRI>"TRUNCATE"			{ RTOKEN(TRUNCATE); }
361 <MRI>"LOAD"			{ RTOKEN(LOAD); }
362 <MRI>"PUBLIC"			{ RTOKEN(PUBLIC); }
363 <MRI>"ORDER"			{ RTOKEN(ORDER); }
364 <MRI>"NAME"			{ RTOKEN(NAMEWORD); }
365 <MRI>"FORMAT"			{ RTOKEN(FORMAT); }
366 <MRI>"CASE"			{ RTOKEN(CASE); }
367 <MRI>"START"			{ RTOKEN(START); }
368 <MRI>"LIST".*			{ RTOKEN(LIST); /* LIST and ignore to end of line */ }
369 <MRI>"SECT"			{ RTOKEN(SECT); }
370 <MRI>"end"			{ RTOKEN(ENDWORD); }
371 <MRI>"absolute"			{ RTOKEN(ABSOLUTE); }
372 <MRI>"alignmod"			{ RTOKEN(ALIGNMOD);}
373 <MRI>"align"			{ RTOKEN(ALIGN_K);}
374 <MRI>"chip"			{ RTOKEN(CHIP); }
375 <MRI>"base"			{ RTOKEN(BASE); }
376 <MRI>"alias"			{ RTOKEN(ALIAS); }
377 <MRI>"truncate"			{ RTOKEN(TRUNCATE); }
378 <MRI>"load"			{ RTOKEN(LOAD); }
379 <MRI>"public"			{ RTOKEN(PUBLIC); }
380 <MRI>"order"			{ RTOKEN(ORDER); }
381 <MRI>"name"			{ RTOKEN(NAMEWORD); }
382 <MRI>"format"			{ RTOKEN(FORMAT); }
383 <MRI>"case"			{ RTOKEN(CASE); }
384 <MRI>"extern"			{ RTOKEN(EXTERN); }
385 <MRI>"start"			{ RTOKEN(START); }
386 <MRI>"list".*			{ RTOKEN(LIST); /* LIST and ignore to end of line */ }
387 <MRI>"sect"			{ RTOKEN(SECT); }
388 
389 <MRI>{FILENAMECHAR1}{NOCFILENAMECHAR}*	{
390 /* Filename without commas, needed to parse mri stuff */
391 				  yylval.name = xstrdup (yytext);
392 				  return NAME;
393 				}
394 
395 
396 <SCRIPT,INPUTLIST>{FILENAMECHAR1}{FILENAMECHAR}*	{
397 				  yylval.name = xstrdup (yytext);
398 				  return NAME;
399 				}
400 <INPUTLIST>"="{FILENAMECHAR1}{FILENAMECHAR}*	{
401 /* Filename to be prefixed by --sysroot or when non-sysrooted, nothing.  */
402 				  yylval.name = xstrdup (yytext);
403 				  return NAME;
404 				}
405 <INPUTLIST>"-l"{FILENAMECHAR}+ {
406 				  yylval.name = xstrdup (yytext + 2);
407 				  return LNAME;
408 				}
409 <EXPRESSION>{SYMBOLNAMECHAR1}{SYMBOLNAMECHAR}* {
410 				  yylval.name = xstrdup (yytext);
411 				  return NAME;
412 				}
413   /* The following rule is to prevent a fill expression on the output
414      section before /DISCARD/ interpreting the '/' as a divide.  */
415 <EXPRESSION>"/DISCARD/"		{
416 				  yylval.name = xstrdup (yytext);
417 				  return NAME;
418 				}
419 <WILD>{WILDCHAR}* {
420 		/* Annoyingly, this pattern can match comments, and we have
421 		   longest match issues to consider.  So if the first two
422 		   characters are a comment opening, put the input back and
423 		   try again.  */
424 		if (yytext[0] == '/' && yytext[1] == '*')
425 		  {
426 		    yyless (2);
427 		    comment ();
428 		  }
429 		else
430 		  {
431 		    yylval.name = xstrdup (yytext);
432 		    return NAME;
433 		  }
434 	}
435 
436 <SCRIPT,EXPRESSION,WILD,VERS_NODE,INPUTLIST>"\""[^\"]*"\"" {
437 		/* No matter the state, quotes give what's inside.  */
438 		yylval.name = xmemdup (yytext + 1, yyleng - 2, yyleng - 1);
439 		return NAME;
440 	}
441 
442 <SCRIPT,EXPRESSION,WILD,VERS_START,VERS_NODE,VERS_SCRIPT,INPUTLIST>"\n" {
443 				lineno++; }
444 <MRI,SCRIPT,EXPRESSION,WILD,VERS_START,VERS_NODE,VERS_SCRIPT,INPUTLIST>[ \t\r]+ {
445 				/* Eat up whitespace */ }
446 <SCRIPT,EXPRESSION,WILD,VERS_START,VERS_NODE,VERS_SCRIPT>#.* {
447 				/* Eat up comments */ }
448 
449 <VERS_NODE,VERS_SCRIPT>[:,;]	{ return *yytext; }
450 
451 <VERS_NODE>global		{ RTOKEN(GLOBAL); }
452 
453 <VERS_NODE>local		{ RTOKEN(LOCAL); }
454 
455 <VERS_NODE>extern		{ RTOKEN(EXTERN); }
456 
457 <VERS_NODE>{V_IDENTIFIER}	{ yylval.name = xstrdup (yytext);
458 				  return VERS_IDENTIFIER; }
459 
460 <VERS_SCRIPT>{V_TAG}		{ yylval.name = xstrdup (yytext);
461 				  return VERS_TAG; }
462 
463 <VERS_START>"{"			{ BEGIN(VERS_SCRIPT); return *yytext; }
464 
465 <VERS_SCRIPT>"{"		{ BEGIN(VERS_NODE);
466 				  vers_node_nesting = 0;
467 				  return *yytext;
468 				}
469 <VERS_SCRIPT>"}"		{ return *yytext; }
470 <VERS_NODE>"{"			{ vers_node_nesting++; return *yytext; }
471 <VERS_NODE>"}"			{ if (--vers_node_nesting < 0)
472 				    BEGIN(VERS_SCRIPT);
473 				  return *yytext;
474 				}
475 
476 <<EOF>> {
477   include_stack_ptr--;
478   if (include_stack_ptr == 0)
479     {
480       lineno = 0;
481       yyterminate ();
482     }
483   else
484     yy_switch_to_buffer (include_stack[include_stack_ptr]);
485 
486   lineno = lineno_stack[include_stack_ptr];
487   input_flags.sysrooted = sysrooted_stack[include_stack_ptr];
488 
489   return END;
490 }
491 
492 <SCRIPT,WILD,MRI,VERS_START,VERS_SCRIPT,VERS_NODE>.	lex_warn_invalid (_(" in script"), yytext);
493 <EXPRESSION>.	lex_warn_invalid (_(" in expression"), yytext);
494 
495 %%
496 
497 
498 /* Switch flex to reading script file NAME, open on FILE,
499    saving the current input info on the include stack.  */
500 
501 void
502 lex_push_file (FILE *file, const char *name, unsigned int sysrooted)
503 {
504   if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
505     {
506       einfo (_("%F:includes nested too deeply\n"));
507     }
508   file_name_stack[include_stack_ptr] = name;
509   lineno_stack[include_stack_ptr] = lineno;
510   sysrooted_stack[include_stack_ptr] = input_flags.sysrooted;
511   include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
512 
513   include_stack_ptr++;
514   lineno = 1;
515   input_flags.sysrooted = sysrooted;
516   yyin = file;
517   yy_switch_to_buffer (yy_create_buffer (yyin, YY_BUF_SIZE));
518 }
519 
520 /* Return a newly created flex input buffer containing STRING,
521    which is SIZE bytes long.  */
522 
523 static YY_BUFFER_STATE
524 yy_create_string_buffer (const char *string, size_t size)
525 {
526   YY_BUFFER_STATE b;
527 
528   b = xmalloc (sizeof (struct yy_buffer_state));
529   b->yy_input_file = 0;
530   b->yy_buf_size = size;
531 
532   /* yy_ch_buf has to be 2 characters longer than the size given because
533      we need to put in 2 end-of-buffer characters.  */
534   b->yy_ch_buf = xmalloc ((size_t) b->yy_buf_size + 3);
535 
536   b->yy_ch_buf[0] = '\n';
537   strcpy (b->yy_ch_buf+1, string);
538   b->yy_ch_buf[size+1] = YY_END_OF_BUFFER_CHAR;
539   b->yy_ch_buf[size+2] = YY_END_OF_BUFFER_CHAR;
540   b->yy_n_chars = size+1;
541   b->yy_buf_pos = &b->yy_ch_buf[1];
542 
543   b->yy_is_our_buffer = 1;
544   b->yy_is_interactive = 0;
545   b->yy_at_bol = 1;
546   b->yy_fill_buffer = 0;
547 
548   /* flex 2.4.7 changed the interface.  FIXME: We should not be using
549      a flex internal interface in the first place!  */
550 #ifdef YY_BUFFER_NEW
551   b->yy_buffer_status = YY_BUFFER_NEW;
552 #else
553   b->yy_eof_status = EOF_NOT_SEEN;
554 #endif
555 
556   return b;
557 }
558 
559 /* Switch flex to reading from STRING, saving the current input info
560    on the include stack.  */
561 
562 void
563 lex_redirect (const char *string, const char *fake_filename, unsigned int count)
564 {
565   YY_BUFFER_STATE tmp;
566 
567   yy_init = 0;
568   if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
569     {
570       einfo (_("%F: macros nested too deeply\n"));
571     }
572   file_name_stack[include_stack_ptr] = fake_filename;
573   lineno_stack[include_stack_ptr] = lineno;
574   include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
575   include_stack_ptr++;
576   lineno = count;
577   tmp = yy_create_string_buffer (string, strlen (string));
578   yy_switch_to_buffer (tmp);
579 }
580 
581 /* Functions to switch to a different flex start condition,
582    saving the current start condition on `state_stack'.  */
583 
584 static int state_stack[MAX_INCLUDE_DEPTH * 2];
585 static int *state_stack_p = state_stack;
586 
587 void
588 ldlex_script (void)
589 {
590   *(state_stack_p)++ = yy_start;
591   BEGIN (SCRIPT);
592 }
593 
594 void
595 ldlex_inputlist (void)
596 {
597   *(state_stack_p)++ = yy_start;
598   BEGIN (INPUTLIST);
599 }
600 
601 void
602 ldlex_mri_script (void)
603 {
604   *(state_stack_p)++ = yy_start;
605   BEGIN (MRI);
606 }
607 
608 void
609 ldlex_version_script (void)
610 {
611   *(state_stack_p)++ = yy_start;
612   BEGIN (VERS_START);
613 }
614 
615 void
616 ldlex_version_file (void)
617 {
618   *(state_stack_p)++ = yy_start;
619   BEGIN (VERS_SCRIPT);
620 }
621 
622 void
623 ldlex_expression (void)
624 {
625   *(state_stack_p)++ = yy_start;
626   BEGIN (EXPRESSION);
627 }
628 
629 void
630 ldlex_wild (void)
631 {
632   *(state_stack_p)++ = yy_start;
633   BEGIN (WILD);
634 }
635 
636 void
637 ldlex_popstate (void)
638 {
639   yy_start = *(--state_stack_p);
640 }
641 
642 /* In cases where the parser needs to look ahead and the context
643    changes from expression to script or vice-versa, throw away a
644    NAME.  What constitutes a NAME depends on context.  */
645 
646 void
647 ldlex_backup (void)
648 {
649   yyless (0);
650 }
651 
652 /* Return the current file name, or the previous file if no file is
653    current.  */
654 
655 const char*
656 ldlex_filename (void)
657 {
658   return file_name_stack[include_stack_ptr - (include_stack_ptr != 0)];
659 }
660 
661 
662 /* Place up to MAX_SIZE characters in BUF and return
663    either the number of characters read, or 0 to indicate EOF.  */
664 
665 static int
666 yy_input (char *buf, int max_size)
667 {
668   int result = 0;
669   if (YY_CURRENT_BUFFER != NULL && YY_CURRENT_BUFFER->yy_input_file)
670     {
671       if (yyin)
672 	{
673 	  result = fread (buf, 1, max_size, yyin);
674 	  if (result < max_size && ferror (yyin))
675 	    einfo (_("%F%P: read in flex scanner failed\n"));
676 	}
677     }
678   return result;
679 }
680 
681 /* Eat the rest of a C-style comment.  */
682 
683 static void
684 comment (void)
685 {
686   int c;
687 
688   while (1)
689     {
690       c = input();
691       while (c != '*' && c != 0)
692 	{
693 	  if (c == '\n')
694 	    lineno++;
695 	  c = input();
696 	}
697 
698       if (c == '*')
699 	{
700 	  c = input();
701 	  while (c == '*')
702 	    c = input();
703 	  if (c == '/')
704 	    break;			/* found the end */
705 	}
706 
707       if (c == '\n')
708 	lineno++;
709 
710       if (c == 0)
711 	{
712 	  einfo (_("%F%P: EOF in comment\n"));
713 	  break;
714 	}
715     }
716 }
717 
718 /* Warn the user about a garbage character WHAT in the input
719    in context WHERE.  */
720 
721 static void
722 lex_warn_invalid (char *where, char *what)
723 {
724   char buf[5];
725 
726   /* If we have found an input file whose format we do not recognize,
727      and we are therefore treating it as a linker script, and we find
728      an invalid character, then most likely this is a real object file
729      of some different format.  Treat it as such.  */
730   if (ldfile_assumed_script)
731     {
732       bfd_set_error (bfd_error_file_not_recognized);
733       einfo (_("%F%s: file not recognized: %E\n"), ldlex_filename ());
734     }
735 
736   if (! ISPRINT (*what))
737     {
738       sprintf (buf, "\\%03o", *(unsigned char *) what);
739       what = buf;
740     }
741 
742   einfo (_("%P:%pS: ignoring invalid character `%s'%s\n"), NULL, what, where);
743 }
744