@q Copyright 2015-2022 Alexander Shibakov@>
@q Copyright 2002-2015 Free Software Foundation, Inc.@>
@q This file is part of SPLinT@>
@q SPLinT is free software: you can redistribute it and/or modify@>
@q it under the terms of the GNU General Public License as published by@>
@q the Free Software Foundation, either version 3 of the License, or@>
@q (at your option) any later version.@>
@q SPLinT is distributed in the hope that it will be useful,@>
@q but WITHOUT ANY WARRANTY; without even the implied warranty of@>
@q MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the@>
@q GNU General Public License for more details.@>
@q You should have received a copy of the GNU General Public License@>
@q along with SPLinT. If not, see <
http://www.gnu.org/licenses/>.@>
@*1 The original lexer. {\it Note that the \ld\ lexer was designed to accomodate
the syntax of various \flex\ flavors, such as the original \lex. The
options \prodstyle{\%a} and \prodstyle{\%o} are ignored by \flex\ and
are a leftover from the archaic days of the original scanner generator.}
@s input_type int
@<Original \ld\ lexer@>=
@G
@> @<Original \ld\ macros@> @=
%{@>@<Original \ld\ preamble@> @=%}
@> @<Miscellaneous \ld\ lexer options@> @=
@> @<Ignored options@> @=
%%
@> @<Original \ld\ regular expressions@> @=
%%
@> @<Original \ld\ postamble@> @=
@g
@ @<Miscellaneous \ld\ lexer options@>=
@G(fs1)
%option nounput
@g
@ @<Original \ld\ preamble@>=
#include "bfd.h"
#include "safe-ctype.h"
#include "bfdlink.h"
#include "ld.h"
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlang.h"
#include <ldgram.h>
#include "ldfile.h"
#include "ldlex.h"
#include "ldmain.h"
#include "libiberty.h"
input_type parser_input;/* The type of top-level parser input.
|yylex| and |yyparse| (indirectly) both check this. */
unsigned int lineno = 1;/* Line number in the current input file. */
const char *lex_string = NULL;/* The string we are currently lexing, or |NULL| if we are reading a
file. */
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result = yy_input (buf, max_size)
/* Support for \flex\ reading from more than one input file (stream).
|include_stack| is \flex's input state for each open file;
|file_name_stack| is the file names. |lineno_stack| is the current
line numbers.
If |include_stack_ptr| is 0, we haven't started reading anything yet.
Otherwise, stack elements 0 through |include_stack_ptr - 1| are valid. */
#ifndef YY_NO_UNPUT
#define YY_NO_UNPUT
#endif
#define MAX_INCLUDE_DEPTH 10
static YY_BUFFER_STATE@, @[include_stack[MAX_INCLUDE_DEPTH]@];
static const char *file_name_stack[MAX_INCLUDE_DEPTH];
static unsigned int lineno_stack[MAX_INCLUDE_DEPTH];
static unsigned int sysrooted_stack[MAX_INCLUDE_DEPTH];
static unsigned int include_stack_ptr = 0;
static int vers_node_nesting = 0;
static int yy_input (char *, int);
static void comment (void);
static void lex_warn_invalid (char *where, char *what);
#define RTOKEN(x) { yylval.token = x; return x; }
#ifndef yywrap
int yywrap (void) { return 1; }/* Some versions of \flex\ want this. */
#endif
@ @<Ignored options@>=
@G(fs1)
%a 4000
%o 5000
@g
@ {\it Some convenient abbreviations for regular expressions.}%
@<Original \ld\ macros@>=
@G(fs1)
CMDFILENAMECHAR [_a-zA-Z0-9\/\.\\_\+\$\:\[\]\\\,\=\&\!\<\>\-\~]
CMDFILENAMECHAR1 [_a-zA-Z0-9\/\.\\_\+\$\:\[\]\\\,\=\&\!\<\>\~]
FILENAMECHAR1 [_a-zA-Z\/\.\\\$\_\~]
SYMBOLCHARN [_a-zA-Z\/\.\\\$\_\~0-9]
FILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\=\$\:\[\]\\\,\~]
WILDCHAR [_a-zA-Z0-9\/\.\-\_\+\=\$\:\[\]\\\,\~\?\*\^\!]
WHITE [ \t\n\r]+
NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~]
V_TAG [.$_a-zA-Z][._a-zA-Z0-9]*
V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
@g
@ {%
\def\aterm{\item{\sqbullet}\ignorespaces}%
\setbox0=\hbox{\sqbullet\enspace}%
\parindent=0pt
\advance\parindent by \wd0
States:
\aterm |EXPRESSION| definitely in an expression
\aterm |SCRIPT| definitely in a script
\aterm |BOTH| either |EXPRESSION| or |SCRIPT|
\aterm |DEFSYMEXP| in an argument to \.{--defsym}
\aterm |MRI| in an \MRI\ script
\aterm |VERS_START| starting a Sun style mapfile
\aterm |VERS_SCRIPT| a Sun style mapfile
\aterm |VERS_NODE| a node within a Sun style mapfile
}%
\ifbootstrapmode\else\yyskipparsefalse\fi
@<\ld\ states@>=
@G(fs1)
%s SCRIPT
%s EXPRESSION
%s BOTH
%s DEFSYMEXP
%s MRI
%s VERS_START
%s VERS_SCRIPT
%s VERS_NODE
@g
@ @<Original \ld\ postamble@>=
if (parser_input != input_selected)
{
/* The first token of the input determines the initial parser state. */
input_type t = parser_input;
parser_input = input_selected;
switch (t)
{
case input_script: return INPUT_SCRIPT; break;
case input_mri_script: return INPUT_MRI_SCRIPT; break;
case input_version_script: return INPUT_VERSION_SCRIPT; break;
case input_dynamic_list: return INPUT_DYNAMIC_LIST; break;
case input_defsym: return INPUT_DEFSYM; break;
default: abort ();
}
}
@ @<Original \ld\ regular expressions@>=
@G(fs2)
@=<BOTH,SCRIPT,EXPRESSION,VERS_START,VERS_NODE,VERS_SCRIPT>"/*" {@> comment ();@+@=}@>@;
<DEFSYMEXP>"-" {@>@[RTOKEN('-');@]@=}
<DEFSYMEXP>"+" {@>@[RTOKEN('+');@]@=}
<DEFSYMEXP>{FILENAMECHAR1}{SYMBOLCHARN}* {@>@[yylval.name = xstrdup (yytext);@+return NAME;@]@=}
<DEFSYMEXP>"=" {@>@[RTOKEN('=');@]@=}
<MRI,EXPRESSION>"$"([0-9A-Fa-f])+ {
@O
yylval.integer = bfd_scan_vma (yytext + 1, 0, 16);
yylval.bigint.str = NULL;
return INT;
@o
}
@t}\vb{\insertraw{\insrulealign{\rulealigntemplate}{\cr\egroup\egroup}}}{@>
<MRI,EXPRESSION>@>@t}\vb{\insertraw{\insparensalign{&}{}}}{@>@=([0-9A-Fa-f])+@>@t}\vb{\insertraw{\insparensalign{\rlap{$\odot$}\cr&}{}}}{@>@=(H|h|X|x|B|b|O|o|D|d) {
@O
int ibase ;
switch (yytext[yyleng - 1]) {
case 'X':
case 'x':
case 'H':
case 'h':
ibase = 16;
break;
case 'O':
case 'o':
ibase = 8;
break;
case 'B':
case 'b':
ibase = 2;
break;
default:
ibase = 10;
}
yylval.integer = bfd_scan_vma (yytext, 0,
ibase);
yylval.bigint.str = NULL;
return INT;
@o
}
@t}\vb{\insertraw{\insrulealign{\rulealigntemplate}{\cr\egroup\egroup}}}{@>
<SCRIPT,DEFSYMEXP,MRI,BOTH,EXPRESSION>((("$"|0[xX])([0-9A-Fa-f])+)|(([0-9])+@>@t}\vb{\insertraw{\insparensalign{\rlap{$\odot$}\cr&}{}}}{@>@=)@>@t}\vb{\insertraw{\insparensalign{&}{}}}{@>@=)(M|K|m|k)? {
@O
char *s = yytext;
int ibase = 0;
if (*s == '$')
{
++s;
ibase = 16;
}
yylval.integer = bfd_scan_vma (s, 0, ibase);
yylval.bigint.str = NULL;
if (yytext[yyleng - 1] == 'M'
|| yytext[yyleng - 1] == 'm')
{
yylval.integer *= 1024 * 1024;
}
else if (yytext[yyleng - 1] == 'K'
|| yytext[yyleng - 1]=='k')
{
yylval.integer *= 1024;
}
else if (yytext[0] == '0'
&& (yytext[1] == 'x'
|| yytext[1] == 'X'))
{
yylval.bigint.str = xstrdup (yytext + 2);
}
return INT;
@o
}
<BOTH,SCRIPT,EXPRESSION,MRI>"]" {@>@[RTOKEN(']');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"[" {@>@[RTOKEN('[');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"<<=" {@>@[RTOKEN(LSHIFTEQ);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>">>=" {@>@[RTOKEN(RSHIFTEQ);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"||" {@>@[RTOKEN(OROR);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"==" {@>@[RTOKEN(EQ);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"!=" {@>@[RTOKEN(NE);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>">=" {@>@[RTOKEN(GE);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"<=" {@>@[RTOKEN(LE);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"<<" {@>@[RTOKEN(LSHIFT);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>">>" {@>@[RTOKEN(RSHIFT);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"+=" {@>@[RTOKEN(PLUSEQ);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"-=" {@>@[RTOKEN(MINUSEQ);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"*=" {@>@[RTOKEN(MULTEQ);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"/=" {@>@[RTOKEN(DIVEQ);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"&=" {@>@[RTOKEN(ANDEQ);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"|=" {@>@[RTOKEN(OREQ);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"&&" {@>@[RTOKEN(ANDAND);@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>">" {@>@[RTOKEN('>');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"," {@>@[RTOKEN(',');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"&" {@>@[RTOKEN('&');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"|" {@>@[RTOKEN('|');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"~" {@>@[RTOKEN('~');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"!" {@>@[RTOKEN('!');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"?" {@>@[RTOKEN('?');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"*" {@>@[RTOKEN('*');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"+" {@>@[RTOKEN('+');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"-" {@>@[RTOKEN('-');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"/" {@>@[RTOKEN('/');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"%" {@>@[RTOKEN('%');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"<" {@>@[RTOKEN('<');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"=" {@>@[RTOKEN('=');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"}" {@>@[RTOKEN('}') ; @]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"{" {@>@[RTOKEN('{'); @]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>")" {@>@[RTOKEN(')');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>"(" {@>@[RTOKEN('(');@]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>":" {@>@[RTOKEN(':'); @]@=}
<BOTH,SCRIPT,EXPRESSION,MRI>";" {@>@[RTOKEN(';');@]@=}
<BOTH,SCRIPT>"MEMORY" {@>@[RTOKEN(MEMORY);@]@=}
<BOTH,SCRIPT>"REGION_ALIAS" {@>@[RTOKEN(REGION_ALIAS);@]@=}
<BOTH,SCRIPT>"LD_FEATURE" {@>@[RTOKEN(LD_FEATURE);@]@=}
<BOTH,SCRIPT,EXPRESSION>"ORIGIN" {@>@[RTOKEN(ORIGIN);@]@=}
<BOTH,SCRIPT>"VERSION" {@>@[RTOKEN(VERSIONK);@]@=}
<EXPRESSION,BOTH,SCRIPT>"BLOCK" {@>@[RTOKEN(BLOCK);@]@=}
<EXPRESSION,BOTH,SCRIPT>"BIND" {@>@[RTOKEN(BIND);@]@=}
<BOTH,SCRIPT,EXPRESSION>"LENGTH" {@>@[RTOKEN(LENGTH);@]@=}
<EXPRESSION,BOTH,SCRIPT>"ALIGN" {@>@[RTOKEN(ALIGN_K);@]@=}
<EXPRESSION,BOTH,SCRIPT>"DATA_SEGMENT_ALIGN" {@>@[RTOKEN(DATA_SEGMENT_ALIGN);@]@=}
<EXPRESSION,BOTH,SCRIPT>"DATA_SEGMENT_RELRO_END" {@>@[RTOKEN(DATA_SEGMENT_RELRO_END);@]@=}
<EXPRESSION,BOTH,SCRIPT>"DATA_SEGMENT_END" {@>@[RTOKEN(DATA_SEGMENT_END);@]@=}
<EXPRESSION,BOTH,SCRIPT>"ADDR" {@>@[RTOKEN(ADDR);@]@=}
<EXPRESSION,BOTH,SCRIPT>"LOADADDR" {@>@[RTOKEN(LOADADDR);@]@=}
<EXPRESSION,BOTH,SCRIPT>"ALIGNOF" {@>@[RTOKEN(ALIGNOF); @]@=}
<EXPRESSION,BOTH>"MAX" {@>@[RTOKEN(MAX_K); @]@=}
<EXPRESSION,BOTH>"MIN" {@>@[RTOKEN(MIN_K); @]@=}
<EXPRESSION,BOTH>"LOG2CEIL" {@>@[RTOKEN(LOG2CEIL); @]@=}
<EXPRESSION,BOTH,SCRIPT>"ASSERT" {@>@[RTOKEN(ASSERT_K); @]@=}
<BOTH,SCRIPT>"ENTRY" {@>@[RTOKEN(ENTRY);@]@=}
<BOTH,SCRIPT,MRI>"EXTERN" {@>@[RTOKEN(EXTERN);@]@=}
<EXPRESSION,BOTH,SCRIPT>"NEXT" {@>@[RTOKEN(NEXT);@]@=}
<EXPRESSION,BOTH,SCRIPT>"sizeof_headers" {@>@[RTOKEN(SIZEOF_HEADERS);@]@=}
<EXPRESSION,BOTH,SCRIPT>"SIZEOF_HEADERS" {@>@[RTOKEN(SIZEOF_HEADERS);@]@=}
<EXPRESSION,BOTH,SCRIPT>"SEGMENT_START" {@>@[RTOKEN(SEGMENT_START);@]@=}
<BOTH,SCRIPT>"MAP" {@>@[RTOKEN(MAP);@]@=}
<EXPRESSION,BOTH,SCRIPT>"SIZEOF" {@>@[RTOKEN(SIZEOF);@]@=}
<BOTH,SCRIPT>"TARGET" {@>@[RTOKEN(TARGET_K);@]@=}
<BOTH,SCRIPT>"SEARCH_DIR" {@>@[RTOKEN(SEARCH_DIR);@]@=}
<BOTH,SCRIPT>"OUTPUT" {@>@[RTOKEN(OUTPUT);@]@=}
<BOTH,SCRIPT>"INPUT" {@>@[RTOKEN(INPUT);@]@=}
<EXPRESSION,BOTH,SCRIPT>"GROUP" {@>@[RTOKEN(GROUP);@]@=}
<EXPRESSION,BOTH,SCRIPT>"AS_NEEDED" {@>@[RTOKEN(AS_NEEDED);@]@=}
<EXPRESSION,BOTH,SCRIPT>"DEFINED" {@>@[RTOKEN(DEFINED);@]@=}
<BOTH,SCRIPT>"CREATE_OBJECT_SYMBOLS" {@>@[RTOKEN(CREATE_OBJECT_SYMBOLS);@]@=}
<BOTH,SCRIPT>"CONSTRUCTORS" {@>@[RTOKEN( CONSTRUCTORS);@]@=}
<BOTH,SCRIPT>"FORCE_COMMON_ALLOCATION" {@>@[RTOKEN(FORCE_COMMON_ALLOCATION);@]@=}
<BOTH,SCRIPT>"INHIBIT_COMMON_ALLOCATION" {@>@[RTOKEN(INHIBIT_COMMON_ALLOCATION);@]@=}
<BOTH,SCRIPT>"SECTIONS" {@>@[RTOKEN(SECTIONS);@]@=}
<BOTH,SCRIPT>"INSERT" {@>@[RTOKEN(INSERT_K);@]@=}
<BOTH,SCRIPT>"AFTER" {@>@[RTOKEN(AFTER);@]@=}
<BOTH,SCRIPT>"BEFORE" {@>@[RTOKEN(BEFORE);@]@=}
<BOTH,SCRIPT>"FILL" {@>@[RTOKEN(FILL);@]@=}
<BOTH,SCRIPT>"STARTUP" {@>@[RTOKEN(STARTUP);@]@=}
<BOTH,SCRIPT>"OUTPUT_FORMAT" {@>@[RTOKEN(OUTPUT_FORMAT);@]@=}
<BOTH,SCRIPT>"OUTPUT_ARCH" {@>@[RTOKEN( OUTPUT_ARCH);@]@=}
<BOTH,SCRIPT>"HLL" {@>@[RTOKEN(HLL);@]@=}
<BOTH,SCRIPT>"SYSLIB" {@>@[RTOKEN(SYSLIB);@]@=}
<BOTH,SCRIPT>"FLOAT" {@>@[RTOKEN(FLOAT);@]@=}
<BOTH,SCRIPT>"QUAD" {@>@[RTOKEN( QUAD);@]@=}
<BOTH,SCRIPT>"SQUAD" {@>@[RTOKEN( SQUAD);@]@=}
<BOTH,SCRIPT>"LONG" {@>@[RTOKEN( LONG);@]@=}
<BOTH,SCRIPT>"SHORT" {@>@[RTOKEN( SHORT);@]@=}
<BOTH,SCRIPT>"BYTE" {@>@[RTOKEN( BYTE);@]@=}
<BOTH,SCRIPT>"NOFLOAT" {@>@[RTOKEN(NOFLOAT);@]@=}
<EXPRESSION,BOTH,SCRIPT>"NOCROSSREFS" {@>@[RTOKEN(NOCROSSREFS);@]@=}
<BOTH,SCRIPT>"OVERLAY" {@>@[RTOKEN(OVERLAY); @]@=}
<BOTH,SCRIPT>"SORT_BY_NAME" {@>@[RTOKEN(SORT_BY_NAME); @]@=}
<BOTH,SCRIPT>"SORT_BY_ALIGNMENT" {@>@[RTOKEN(SORT_BY_ALIGNMENT); @]@=}
<BOTH,SCRIPT>"SORT" {@>@[RTOKEN(SORT_BY_NAME); @]@=}
<BOTH,SCRIPT>"SORT_BY_INIT_PRIORITY" {@>@[RTOKEN(SORT_BY_INIT_PRIORITY); @]@=}
<BOTH,SCRIPT>"SORT_NONE" {@>@[RTOKEN(SORT_NONE); @]@=}
<EXPRESSION,BOTH,SCRIPT>"NOLOAD" {@>@[RTOKEN(NOLOAD);@]@=}
<EXPRESSION,BOTH,SCRIPT>"DSECT" {@>@[RTOKEN(DSECT);@]@=}
<EXPRESSION,BOTH,SCRIPT>"COPY" {@>@[RTOKEN(COPY);@]@=}
<EXPRESSION,BOTH,SCRIPT>"INFO" {@>@[RTOKEN(INFO);@]@=}
<EXPRESSION,BOTH,SCRIPT>"OVERLAY" {@>@[RTOKEN(OVERLAY);@]@=}
<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RO" {@>@[RTOKEN(ONLY_IF_RO); @]@=}
<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RW" {@>@[RTOKEN(ONLY_IF_RW); @]@=}
<EXPRESSION,BOTH,SCRIPT>"SPECIAL" {@>@[RTOKEN(SPECIAL); @]@=}
<BOTH,SCRIPT>"o" {@>@[RTOKEN(ORIGIN);@]@=}
<BOTH,SCRIPT>"org" {@>@[RTOKEN(ORIGIN);@]@=}
<BOTH,SCRIPT>"l" {@>@[RTOKEN( LENGTH);@]@=}
<BOTH,SCRIPT>"len" {@>@[RTOKEN( LENGTH);@]@=}
<EXPRESSION,BOTH,SCRIPT>"INPUT_SECTION_FLAGS" {@>@[RTOKEN(INPUT_SECTION_FLAGS); @]@=}
<EXPRESSION,BOTH,SCRIPT>"INCLUDE" {@>@[RTOKEN(INCLUDE);@]@=}
<BOTH,SCRIPT>"PHDRS" {@>@[RTOKEN (PHDRS); @]@=}
<EXPRESSION,BOTH,SCRIPT>"AT" {@>@[RTOKEN(AT);@]@=}
<EXPRESSION,BOTH,SCRIPT>"ALIGN_WITH_INPUT" {@>@[RTOKEN(ALIGN_WITH_INPUT);@]@=}
<EXPRESSION,BOTH,SCRIPT>"SUBALIGN" {@>@[RTOKEN(SUBALIGN);@]@=}
<EXPRESSION,BOTH,SCRIPT>"HIDDEN" {@>@[RTOKEN(HIDDEN); @]@=}
<EXPRESSION,BOTH,SCRIPT>"PROVIDE" {@>@[RTOKEN(PROVIDE); @]@=}
<EXPRESSION,BOTH,SCRIPT>"PROVIDE_HIDDEN" {@>@[RTOKEN(PROVIDE_HIDDEN); @]@=}
<EXPRESSION,BOTH,SCRIPT>"KEEP" {@>@[RTOKEN(KEEP); @]@=}
<EXPRESSION,BOTH,SCRIPT>"EXCLUDE_FILE" {@>@[RTOKEN(EXCLUDE_FILE); @]@=}
<EXPRESSION,BOTH,SCRIPT>"CONSTANT" {@>@[RTOKEN(CONSTANT);@]@=}
<MRI>"#".*\n? {@>@[++ lineno; @]@=}
<MRI>"\n" {@> @[++lineno;@+RTOKEN(NEWLINE);@]@=}
<MRI>"*".* {@> /* \MRI\ comment line */ @=}
<MRI>";".* {@> /* \MRI\ comment line */ @=}
<MRI>"END" {@>@[RTOKEN(ENDWORD); @]@=}
<MRI>"ALIGNMOD" {@>@[RTOKEN(ALIGNMOD);@]@=}
<MRI>"ALIGN" {@>@[RTOKEN(ALIGN_K);@]@=}
<MRI>"CHIP" {@>@[RTOKEN(CHIP); @]@=}
<MRI>"BASE" {@>@[RTOKEN(BASE); @]@=}
<MRI>"ALIAS" {@>@[RTOKEN(ALIAS); @]@=}
<MRI>"TRUNCATE" {@>@[RTOKEN(TRUNCATE); @]@=}
<MRI>"LOAD" {@>@[RTOKEN(LOAD); @]@=}
<MRI>"PUBLIC" {@>@[RTOKEN(PUBLIC); @]@=}
<MRI>"ORDER" {@>@[RTOKEN(ORDER); @]@=}
<MRI>"NAME" {@>@[RTOKEN(NAMEWORD); @]@=}
<MRI>"FORMAT" {@>@[RTOKEN(FORMAT); @]@=}
<MRI>"CASE" {@>@[RTOKEN(CASE); @]@=}
<MRI>"START" {@>@[RTOKEN(START); @]@=}
<MRI>"LIST".* {@>@[RTOKEN(LIST);@]/* \prodstyle{LIST} and ignore to end of line */@=}
<MRI>"SECT" {@>@[RTOKEN(SECT); @]@=}
<EXPRESSION,BOTH,SCRIPT,MRI>"ABSOLUTE" {@>@[RTOKEN(ABSOLUTE); @]@=}
<MRI>"end" {@>@[RTOKEN(ENDWORD); @]@=}
<MRI>"alignmod" {@>@[RTOKEN(ALIGNMOD);@]@=}
<MRI>"align" {@>@[RTOKEN(ALIGN_K);@]@=}
<MRI>"chip" {@>@[RTOKEN(CHIP); @]@=}
<MRI>"base" {@>@[RTOKEN(BASE); @]@=}
<MRI>"alias" {@>@[RTOKEN(ALIAS); @]@=}
<MRI>"truncate" {@>@[RTOKEN(TRUNCATE); @]@=}
<MRI>"load" {@>@[RTOKEN(LOAD); @]@=}
<MRI>"public" {@>@[RTOKEN(PUBLIC); @]@=}
<MRI>"order" {@>@[RTOKEN(ORDER); @]@=}
<MRI>"name" {@>@[RTOKEN(NAMEWORD); @]@=}
<MRI>"format" {@>@[RTOKEN(FORMAT); @]@=}
<MRI>"case" {@>@[RTOKEN(CASE); @]@=}
<MRI>"extern" {@>@[RTOKEN(EXTERN); @]@=}
<MRI>"start" {@>@[RTOKEN(START); @]@=}
<MRI>"list".* {@>@[RTOKEN(LIST);@]/* \prodstyle{LIST} and ignore to end of line */@=}
<MRI>"sect" {@>@[RTOKEN(SECT); @]@=}
<EXPRESSION,BOTH,SCRIPT,MRI>"absolute" {@>@[RTOKEN(ABSOLUTE); @]@=}
<MRI>{FILENAMECHAR1}{NOCFILENAMECHAR}* {
@O
/* Filename without commas, needed to parse \MRI\ stuff */
yylval.name = xstrdup (yytext);
return NAME;
@o
}
<BOTH>{FILENAMECHAR1}{FILENAMECHAR}* {
@O
yylval.name = xstrdup (yytext);
return NAME;
@o
}
<BOTH>"-l"{FILENAMECHAR}+ {
@O
yylval.name = xstrdup (yytext + 2);
return LNAME;
@o
}
<EXPRESSION>{FILENAMECHAR1}{NOCFILENAMECHAR}* {
@O
yylval.name = xstrdup (yytext);
return NAME;
@o
}
<EXPRESSION>"-l"{NOCFILENAMECHAR}+ {
@O
yylval.name = xstrdup (yytext + 2);
return LNAME;
@o
}
<SCRIPT>{WILDCHAR}* {
@O
@t}\C{Annoyingly, this pattern can match comments,}\6{@>
@t}\C{and we have longest match issues to consider.}\6{@>
@t}\C{So if the first two characters are a comment}\6{@>
@t}\C{opening, put the input back and try again.}\6{@>
if (yytext[0] == '/' && yytext[1] == '*')
{
yyless (2);
comment ();
}
else
{
yylval.name = xstrdup (yytext);
return NAME;
}
@o
}
<EXPRESSION,BOTH,SCRIPT,VERS_NODE>"\""[^\"]*"\"" {
@O
/* No matter the state, quotes
give what's inside */
yylval.name = xstrdup (yytext + 1);
yylval.name[yyleng - 2] = 0;
return NAME;
@o
}
<BOTH,SCRIPT,EXPRESSION>"\n" {@>@[lineno++;@]@=}
<MRI,BOTH,SCRIPT,EXPRESSION>[ \t\r]+ {}
<VERS_NODE,VERS_SCRIPT>[:,;] {@>@[return *yytext; @]@=}
<VERS_NODE>global {@>@[RTOKEN(GLOBAL); @]@=}
<VERS_NODE>local {@>@[RTOKEN(LOCAL); @]@=}
<VERS_NODE>extern {@>@[RTOKEN(EXTERN); @]@=}
<VERS_NODE>{V_IDENTIFIER} {
@O
yylval.name = xstrdup (yytext);
return VERS_IDENTIFIER;
@o
}
<VERS_SCRIPT>{V_TAG} {
@O
yylval.name = xstrdup (yytext);
return VERS_TAG;
@o
}
<VERS_START>"{" {@>@[BEGIN(VERS_SCRIPT);@+return *yytext;@]@=}
<VERS_SCRIPT>"{" {
@O
BEGIN(VERS_NODE);
vers_node_nesting = 0;
return *yytext;
@o
}
<VERS_SCRIPT>"}" {@>@[return *yytext;@]@=}
<VERS_NODE>"{" {@>@[vers_node_nesting++;@+return *yytext;@]@=}
<VERS_NODE>"}" {
@O
if (--vers_node_nesting < 0)
BEGIN(VERS_SCRIPT);
return *yytext;
@o
}
<VERS_START,VERS_NODE,VERS_SCRIPT>[\n] {@>@[lineno++;@]@=}
<VERS_START,VERS_NODE,VERS_SCRIPT>#.* {@>@[;@]/* Eat up comments */@=}
<VERS_START,VERS_NODE,VERS_SCRIPT>[ \t\r]+ {@>@[;@]/* Eat up whitespace */@=}
<<EOF>> {@>@=
@O
include_stack_ptr--;
if (include_stack_ptr == 0)
yyterminate ();
else
yy_switch_to_buffer (include_stack[include_stack_ptr]);
lineno = lineno_stack[include_stack_ptr];
input_flags.sysrooted = sysrooted_stack[include_stack_ptr];
return END;
@o
}
<SCRIPT,MRI,VERS_START,VERS_SCRIPT,VERS_NODE>. @>@[lex_warn_invalid (" in script", yytext);@]
<EXPRESSION,DEFSYMEXP,BOTH>. @>@[lex_warn_invalid (" in expression", yytext);@]
@g
@ Switch \flex\ to reading script file |name|, open on |file|,
saving the current input info on the include stack.
@<Supporting \Cee\ code@>=
void
lex_push_file (FILE *file, const char *name, unsigned int sysrooted)
{
if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
{
einfo ("%F:includes nested too deeply\n");
}
file_name_stack[include_stack_ptr] = name;
lineno_stack[include_stack_ptr] = lineno;
sysrooted_stack[include_stack_ptr] = input_flags.sysrooted;
include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
include_stack_ptr++;
lineno = 1;
input_flags.sysrooted = sysrooted;
yyin = file;
yy_switch_to_buffer (yy_create_buffer (yyin, YY_BUF_SIZE));
}
@ Return a newly created \flex\ input buffer containing |string|,
which is |size| bytes long.
@<Supporting \Cee\ code@>=
static YY_BUFFER_STATE
yy_create_string_buffer (const char *string, size_t size)
{
YY_BUFFER_STATE b;
b = malloc (sizeof (struct yy_buffer_state));/* Calls to |malloc| get turned by sed into |xmalloc|. */
b->yy_input_file = 0;
b->yy_buf_size = size;
b->yy_ch_buf = malloc ((unsigned) (b->yy_buf_size + 3));
/* |yy_ch_buf| has to be 2 characters longer than the size given because
we need to put in 2 end-of-buffer characters. */
b->yy_ch_buf[0] = '\n';
strcpy (b->yy_ch_buf+1, string);
b->yy_ch_buf[size+1] = YY_END_OF_BUFFER_CHAR;
b->yy_ch_buf[size+2] = YY_END_OF_BUFFER_CHAR;
b->yy_n_chars = size+1;
b->yy_buf_pos = &b->yy_ch_buf[1];
b->yy_is_our_buffer = 1;
b->yy_is_interactive = 0;
b->yy_at_bol = 1;
b->yy_fill_buffer = 0;
#ifdef YY_BUFFER_NEW
b->yy_buffer_status = YY_BUFFER_NEW;
#else
b->yy_eof_status = EOF_NOT_SEEN;
#endif
return b;
}
@ Switch \flex\ to reading from |string|, saving the current input info
on the include stack.
@<Supporting \Cee\ code@>=
void
lex_redirect (const char *string, const char *fake_filename, unsigned int count)
{
YY_BUFFER_STATE tmp;
yy_init = 0;
if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
{
einfo("%F: macros nested too deeply\n");
}
file_name_stack[include_stack_ptr] = fake_filename;
lineno_stack[include_stack_ptr] = lineno;
include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
include_stack_ptr++;
lineno = count;
tmp = yy_create_string_buffer (string, strlen (string));
yy_switch_to_buffer (tmp);
}
@ Functions to switch to a different \flex\ start condition,
saving the current start condition on |state_stack|.
@<Supporting \Cee\ code@>=
static int state_stack[MAX_INCLUDE_DEPTH * 2];
static int *state_stack_p = state_stack;
void
ldlex_script (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (SCRIPT);
}
void
ldlex_mri_script (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (MRI);
}
void
ldlex_version_script (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (VERS_START);
}
void
ldlex_version_file (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (VERS_SCRIPT);
}
void
ldlex_defsym (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (DEFSYMEXP);
}
void
ldlex_expression (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (EXPRESSION);
}
void
ldlex_both (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (BOTH);
}
void
ldlex_popstate (void)
{
yy_start = *(--state_stack_p);
}
@ Return the current file name, or the previous file if no file is
current.
@<Supporting \Cee\ code@>=
const char*
ldlex_filename (void)
{
return file_name_stack[include_stack_ptr - (include_stack_ptr != 0)];
}
@ Place up to |max_size| characters in |buf| and return
either the number of characters read, or 0 to indicate |EOF|.
@<Supporting \Cee\ code@>=
static int
yy_input (char *buf, int max_size)
{
int result = 0;
if (YY_CURRENT_BUFFER->yy_input_file)
{
if (yyin)
{
result = fread (buf, 1, max_size, yyin);
if (result < max_size && ferror (yyin))
einfo ("%F%P: read in flex scanner failed\n");
}
}
return result;
}
@ Eat the rest of a \Cee-style comment.
@<Supporting \Cee\ code@>=
static void
comment (void)
{
int c;
while (1)
{
c = input();
while (c != '*' && c != EOF)
{
if (c == '\n')
lineno++;
c = input();
}
if (c == '*')
{
c = input();
while (c == '*')
c = input();
if (c == '/')
break; /* found the end */
}
if (c == '\n')
lineno++;
if (c == EOF)
{
einfo( "%F%P: EOF in comment\n");
break;
}
}
}
@ Warn the user about a garbage character |what| in the input
in context |where|.
@<Supporting \Cee\ code@>=
static void
lex_warn_invalid (char *where, char *what)
{
char buf[5];
if (ldfile_assumed_script)
{ /* If we have found an input file whose format we do not recognize,
and we are therefore treating it as a linker script, and we find
an invalid character, then most likely this is a real object file
of some different format. Treat it as such. */
bfd_set_error (bfd_error_file_not_recognized);
einfo ("%F%s: file not recognized: %E\n", ldlex_filename ());
}
if (! ISPRINT (*what))
{
sprintf (buf, "\\%03o", *(unsigned char *) what);
what = buf;
}
einfo ("%P:%S: ignoring invalid character `%s'%s\n", NULL, what, where);
}