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