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