PR28217, Syntax error when memory region contains a hyphen

Message ID YRXgxRiA5FlDlemH@squeak.grove.modra.org
State New
Headers show
Series
  • PR28217, Syntax error when memory region contains a hyphen
Related show

Commit Message

Alan Modra via Binutils Aug. 13, 2021, 3:02 a.m.
The saga of commit 40726f16a8d7 continues.  This attacks the problem
of switching between SCRIPT and EXPRESSION state lexing by removing
the need to do so for phdrs like ":text".  Instead {WILDCHAR}*
matching, the reason why ":text" lexed as one token, is restricted to
within the braces of a section or overlay statement.  The new WILD
lexer state is switched at the non-optional brace tokens, so
ldlex_backup is no longer needed.  I've also removed the BOTH state,
which doesn't seem to be needed any more.  Besides rules involving
error reporting, there was just one place where SCRIPT appeared
without BOTH, the {WILDCHAR}* rule, three where BOTH appears without
SCRIPT for tokens that only need EXPRESSION state, and two where BOTH
appears alongside INPUT_LIST.  (Since I'm editing the wild and
filename rules, removing BOTH and adding WILD can also be seen as
renaming the old BOTH state to SCRIPT and renaming the old SCRIPT
state to WILD with a reduced scope.)

As a followup, I'll look at removing EXPRESSION state from some lexer
rules that no longer need it due to this cleanup.

	PR 28217
	* ldgram.y (exp <ORIGIN, LENGTH>): Use paren_script_name.
	(section): Parse within braces of section in wild mode, and
	after brace back in script mode.  Remove ldlex_backup call.
	Similarly for OVERLAY.
	(overlay_section): Similarly.
	(script_file): Replace ldlex_both with ldlex_script.
	* ldlex.h (ldlex_wild): Declare.
	(ldlex_both): Delete.
	* ldlex.l (BOTH): Delete.  Remove state from all rules.
	(WILD): New state.  Enable many tokens in this state.
	Enable filename match in SCRIPT mode.  Enable WILDCHAR match
	in WILD state, disable in SCRIPT mode.
	(ldlex_wild): New function.
	* ldfile.c (ldfile_try_open_bfd): Replace ldlex_both call with
	ldlex_script.


-- 
Alan Modra
Australia Development Lab, IBM

Comments

Alan Modra via Binutils Aug. 13, 2021, 11:29 a.m. | #1
I discovered some more errors when tightening up the lexer rules.
Just because we INCLUDE a file doesn't mean we've switched states.

	PR 28217
	* ldgram.y (statement): Don't switch lexer state on INCLUDE.
	(mri_script_command, ifile_p1, memory_spec, section): Likewise.

diff --git a/ld/ldgram.y b/ld/ldgram.y
index 4910e17ab4a..794cf284a7b 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -248,9 +248,8 @@ mri_script_command:
 	|	CASE casesymlist
 	|	EXTERN extern_name_list
 	|	INCLUDE filename
-		{ ldlex_script (); ldfile_open_command_file($2); }
+		{ ldfile_open_command_file ($2); }
 		mri_script_lines END
-		{ ldlex_popstate (); }
 	|	START NAME
 		{ lang_add_entry ($2, false); }
 	|
@@ -346,9 +345,8 @@ ifile_p1:
 	|	MAP '(' filename ')'
 		{ lang_add_map($3); }
 	|	INCLUDE filename
-		{ ldlex_script (); ldfile_open_command_file($2); }
+		{ ldfile_open_command_file ($2); }
 		ifile_list END
-		{ ldlex_popstate (); }
 	|	NOCROSSREFS '(' nocrossref_list ')'
 		{
 		  lang_add_nocrossref ($3);
@@ -697,11 +695,9 @@ statement:
 		}
 	| INCLUDE filename
 		{
-		  ldlex_script ();
 		  ldfile_open_command_file ($2);
 		}
 	  statement_list_opt END
-		{ ldlex_popstate (); }
 	;
 
 statement_list:
@@ -814,9 +810,8 @@ memory_spec:	NAME
 		origin_spec opt_comma length_spec
 		{}
 	|	INCLUDE filename
-		{ ldlex_script (); ldfile_open_command_file($2); }
+		{ ldfile_open_command_file ($2); }
 		memory_spec_list_opt END
-		{ ldlex_popstate (); }
 	;
 
 origin_spec:
@@ -1117,11 +1112,9 @@ section:	NAME
 		'{' sec_or_group_p1 '}'
 	|	INCLUDE filename
 			{
-			  ldlex_script ();
 			  ldfile_open_command_file ($2);
 			}
 		sec_or_group_p1 END
-			{ ldlex_popstate (); }
 	;
 
 type:

-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/ld/ldfile.c b/ld/ldfile.c
index 43b1116b1d5..22271fd6810 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -193,7 +193,7 @@  ldfile_try_open_bfd (const char *attempt,
 
 		  ldfile_assumed_script = true;
 		  parser_input = input_selected;
-		  ldlex_both ();
+		  ldlex_script ();
 		  token = INPUT_SCRIPT;
 		  while (token != 0)
 		    {
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 77442818587..4910e17ab4a 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -297,9 +297,9 @@  extern_name_list_body:
 	;
 
 script_file:
-	{ ldlex_both(); }
+	{ ldlex_script (); }
 	ifile_list
-	{ ldlex_popstate(); }
+	{ ldlex_popstate (); }
 	;
 
 ifile_list:
@@ -1021,10 +1021,10 @@  exp	:
 			{ $$ = exp_binop (MIN_K, $3, $5 ); }
 	|	ASSERT_K '(' exp ',' NAME ')'
 			{ $$ = exp_assert ($3, $5); }
-	|	ORIGIN '(' NAME ')'
-			{ $$ = exp_nameop (ORIGIN, $3); }
-	|	LENGTH '(' NAME ')'
-			{ $$ = exp_nameop (LENGTH, $3); }
+	|	ORIGIN paren_script_name
+			{ $$ = exp_nameop (ORIGIN, $2); }
+	|	LENGTH paren_script_name
+			{ $$ = exp_nameop (LENGTH, $2); }
 	|	LOG2CEIL '(' exp ')'
 			{ $$ = exp_unop (LOG2CEIL, $3); }
 	;
@@ -1069,50 +1069,38 @@  section:	NAME
 		opt_align
 		opt_align_with_input
 		opt_subalign
-			{ ldlex_popstate (); ldlex_script (); }
 		sect_constraint
-		'{'
 			{
+			  ldlex_popstate ();
+			  ldlex_wild ();
 			  lang_enter_output_section_statement($1, $3, sectype,
 							      $5, $7, $4,
-							      $9, $6);
+							      $8, $6);
 			}
+		'{'
 		statement_list_opt
 		'}'
-			{ ldlex_popstate (); ldlex_expression (); }
+			{ ldlex_popstate (); }
 		memspec_opt memspec_at_opt phdr_opt fill_opt
 			{
-			  if (yychar == NAME)
-			    {
-			      yyclearin;
-			      ldlex_backup ();
-			    }
-			  ldlex_popstate ();
-			  lang_leave_output_section_statement ($18, $15,
-							       $17, $16);
+			  lang_leave_output_section_statement ($17, $14,
+							       $16, $15);
 			}
 		opt_comma
 	|	OVERLAY
 			{ ldlex_expression (); }
 		opt_exp_without_type opt_nocrossrefs opt_at opt_subalign
-			{ ldlex_popstate (); ldlex_script (); }
+			{ ldlex_popstate (); }
 		'{'
 			{
 			  lang_enter_overlay ($3, $6);
 			}
 		overlay_section
 		'}'
-			{ ldlex_popstate (); ldlex_expression (); }
 		memspec_opt memspec_at_opt phdr_opt fill_opt
 			{
-			  if (yychar == NAME)
-			    {
-			      yyclearin;
-			      ldlex_backup ();
-			    }
-			  ldlex_popstate ();
 			  lang_leave_overlay ($5, (int) $4,
-					      $16, $13, $15, $14);
+					      $15, $12, $14, $13);
 			}
 		opt_comma
 	|	/* The GROUP case is just enough to support the gcc
@@ -1204,18 +1192,15 @@  overlay_section:
 	|	overlay_section
 		NAME
 			{
+			  ldlex_wild ();
 			  lang_enter_overlay_section ($2);
 			}
-		'{' statement_list_opt '}'
-			{ ldlex_expression (); }
+		'{'
+		statement_list_opt
+		'}'
+			{ ldlex_popstate (); }
 		phdr_opt fill_opt
 			{
-			  if (yychar == NAME)
-			    {
-			      yyclearin;
-			      ldlex_backup ();
-			    }
-			  ldlex_popstate ();
 			  lang_leave_overlay_section ($9, $8);
 			}
 		opt_comma
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 9707d57caf8..04ee0e40dc1 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -191,7 +191,7 @@  extern void ldlex_mri_script (void);
 extern void ldlex_version_script (void);
 extern void ldlex_version_file (void);
 extern void ldlex_expression (void);
-extern void ldlex_both (void);
+extern void ldlex_wild (void);
 extern void ldlex_popstate (void);
 extern void ldlex_backup (void);
 extern const char* ldlex_filename (void);
diff --git a/ld/ldlex.l b/ld/ldlex.l
index f588bd3adc5..dfe8382d0bb 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -75,11 +75,12 @@  static void comment (void);
 static void lex_warn_invalid (char *where, char *what);
 
 /* STATES
-	EXPRESSION	definitely in an expression
-	SCRIPT		definitely in a script
-	INPUTLIST	definitely in a script, a filename-list
-	BOTH		either EXPRESSION or SCRIPT
+	EXPRESSION	in an expression
+	SCRIPT		in a script
+	INPUTLIST	in a script, a filename-list
 	MRI		in an MRI script
+	WILD		inside the braces of an output section or overlay,
+			for input section wildcards
 	VERS_START	starting a Sun style mapfile
 	VERS_SCRIPT	a Sun style mapfile
 	VERS_NODE	a node within a Sun style mapfile
@@ -105,8 +106,8 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 %s SCRIPT
 %s INPUTLIST
 %s EXPRESSION
-%s BOTH
 %s MRI
+%s WILD
 %s VERS_START
 %s VERS_SCRIPT
 %s VERS_NODE
@@ -128,8 +129,8 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 	}
     }
 
-<BOTH,SCRIPT,EXPRESSION,VERS_START,VERS_NODE,VERS_SCRIPT,INPUTLIST>"/*"	{ comment (); }
-
+<SCRIPT,EXPRESSION,VERS_START,VERS_NODE,VERS_SCRIPT,INPUTLIST>"/*" {
+				comment (); }
 
 <MRI,EXPRESSION>"$"([0-9A-Fa-f])+ {
 				yylval.integer = bfd_scan_vma (yytext + 1, 0, 16);
@@ -162,7 +163,7 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 				   yylval.bigint.str = NULL;
 				   return INT;
 				 }
-<SCRIPT,MRI,BOTH,EXPRESSION>((("$"|0[xX])([0-9A-Fa-f])+)|(([0-9])+))(M|K|m|k)? {
+<SCRIPT,MRI,EXPRESSION>((("$"|0[xX])([0-9A-Fa-f])+)|(([0-9])+))(M|K|m|k)? {
 				  char *s = yytext;
 				  int ibase = 0;
 
@@ -191,133 +192,134 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 				    }
 				  return INT;
 				}
-<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,INPUTLIST>","		{ 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,INPUTLIST>")"		{ RTOKEN(')');}
-<BOTH,SCRIPT,EXPRESSION,MRI,INPUTLIST>"("		{ 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,INPUTLIST>"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>"FORCE_GROUP_ALLOCATION"	{ RTOKEN(FORCE_GROUP_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);}
-<EXPRESSION,BOTH,SCRIPT>"NOCROSSREFS_TO" { RTOKEN(NOCROSSREFS_TO);}
-<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>"READONLY"	{ RTOKEN(READONLY);}
-<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);}
+<SCRIPT,EXPRESSION,MRI,WILD>"]"		{ RTOKEN(']');}
+<SCRIPT,EXPRESSION,MRI,WILD>"["		{ RTOKEN('[');}
+<SCRIPT,EXPRESSION,MRI,WILD>"<<="	{ RTOKEN(LSHIFTEQ);}
+<SCRIPT,EXPRESSION,MRI,WILD>">>="	{ RTOKEN(RSHIFTEQ);}
+<SCRIPT,EXPRESSION,MRI>"||"		{ RTOKEN(OROR);}
+<SCRIPT,EXPRESSION,MRI>"=="		{ RTOKEN(EQ);}
+<SCRIPT,EXPRESSION,MRI>"!="		{ RTOKEN(NE);}
+<SCRIPT,EXPRESSION,MRI>">="		{ RTOKEN(GE);}
+<SCRIPT,EXPRESSION,MRI>"<="		{ RTOKEN(LE);}
+<SCRIPT,EXPRESSION,MRI>"<<"		{ RTOKEN(LSHIFT);}
+<SCRIPT,EXPRESSION,MRI>">>"		{ RTOKEN(RSHIFT);}
+<SCRIPT,EXPRESSION,MRI,WILD>"+="	{ RTOKEN(PLUSEQ);}
+<SCRIPT,EXPRESSION,MRI,WILD>"-="	{ RTOKEN(MINUSEQ);}
+<SCRIPT,EXPRESSION,MRI,WILD>"*="	{ RTOKEN(MULTEQ);}
+<SCRIPT,EXPRESSION,MRI,WILD>"/="	{ RTOKEN(DIVEQ);}
+<SCRIPT,EXPRESSION,MRI,WILD>"&="	{ RTOKEN(ANDEQ);}
+<SCRIPT,EXPRESSION,MRI,WILD>"|="	{ RTOKEN(OREQ);}
+<SCRIPT,EXPRESSION,MRI>"&&"		{ RTOKEN(ANDAND);}
+<SCRIPT,EXPRESSION,MRI>">"		{ RTOKEN('>');}
+<SCRIPT,EXPRESSION,MRI,INPUTLIST>","	{ RTOKEN(',');}
+<SCRIPT,EXPRESSION,MRI,WILD>"&"		{ RTOKEN('&');}
+<SCRIPT,EXPRESSION,MRI>"|"		{ RTOKEN('|');}
+<SCRIPT,EXPRESSION,MRI>"~"		{ RTOKEN('~');}
+<SCRIPT,EXPRESSION,MRI>"!"		{ RTOKEN('!');}
+<SCRIPT,EXPRESSION,MRI>"?"		{ RTOKEN('?');}
+<SCRIPT,EXPRESSION,MRI>"*"		{ RTOKEN('*');}
+<SCRIPT,EXPRESSION,MRI>"+"		{ RTOKEN('+');}
+<SCRIPT,EXPRESSION,MRI>"-"		{ RTOKEN('-');}
+<SCRIPT,EXPRESSION,MRI>"/"		{ RTOKEN('/');}
+<SCRIPT,EXPRESSION,MRI>"%"		{ RTOKEN('%');}
+<SCRIPT,EXPRESSION,MRI>"<"		{ RTOKEN('<');}
+<SCRIPT,EXPRESSION,MRI,WILD>"="		{ RTOKEN('=');}
+<SCRIPT,EXPRESSION,MRI,WILD>"}"		{ RTOKEN('}'); }
+<SCRIPT,EXPRESSION,MRI,WILD>"{"		{ RTOKEN('{'); }
+<SCRIPT,EXPRESSION,MRI,WILD,INPUTLIST>")" { RTOKEN(')');}
+<SCRIPT,EXPRESSION,MRI,WILD,INPUTLIST>"(" { RTOKEN('(');}
+<SCRIPT,EXPRESSION,MRI>":"		{ RTOKEN(':'); }
+<SCRIPT,EXPRESSION,MRI,WILD>";"		{ RTOKEN(';');}
+<SCRIPT>"MEMORY"			{ RTOKEN(MEMORY);}
+<SCRIPT>"REGION_ALIAS"			{ RTOKEN(REGION_ALIAS);}
+<SCRIPT>"LD_FEATURE"			{ RTOKEN(LD_FEATURE);}
+<SCRIPT,EXPRESSION>"ORIGIN"		{ RTOKEN(ORIGIN);}
+<SCRIPT>"VERSION"			{ RTOKEN(VERSIONK);}
+<SCRIPT,EXPRESSION>"BLOCK"		{ RTOKEN(BLOCK);}
+<SCRIPT,EXPRESSION>"BIND"		{ RTOKEN(BIND);}
+<SCRIPT,EXPRESSION>"LENGTH"		{ RTOKEN(LENGTH);}
+<SCRIPT,EXPRESSION>"ALIGN"		{ RTOKEN(ALIGN_K);}
+<SCRIPT,EXPRESSION>"DATA_SEGMENT_ALIGN"	{ RTOKEN(DATA_SEGMENT_ALIGN);}
+<SCRIPT,EXPRESSION>"DATA_SEGMENT_RELRO_END" { RTOKEN(DATA_SEGMENT_RELRO_END);}
+<SCRIPT,EXPRESSION>"DATA_SEGMENT_END"	{ RTOKEN(DATA_SEGMENT_END);}
+<SCRIPT,EXPRESSION>"ADDR"		{ RTOKEN(ADDR);}
+<SCRIPT,EXPRESSION>"LOADADDR"		{ RTOKEN(LOADADDR);}
+<SCRIPT,EXPRESSION>"ALIGNOF"		{ RTOKEN(ALIGNOF); }
+<EXPRESSION>"MAX"			{ RTOKEN(MAX_K); }
+<EXPRESSION>"MIN"			{ RTOKEN(MIN_K); }
+<EXPRESSION>"LOG2CEIL"			{ RTOKEN(LOG2CEIL); }
+<SCRIPT,EXPRESSION,WILD>"ASSERT"	{ RTOKEN(ASSERT_K); }
+<SCRIPT,WILD>"ENTRY"			{ RTOKEN(ENTRY);}
+<SCRIPT,MRI>"EXTERN"			{ RTOKEN(EXTERN);}
+<SCRIPT,EXPRESSION>"NEXT"		{ RTOKEN(NEXT);}
+<SCRIPT,EXPRESSION>"sizeof_headers"	{ RTOKEN(SIZEOF_HEADERS);}
+<SCRIPT,EXPRESSION>"SIZEOF_HEADERS"	{ RTOKEN(SIZEOF_HEADERS);}
+<SCRIPT,EXPRESSION>"SEGMENT_START"	{ RTOKEN(SEGMENT_START);}
+<SCRIPT>"MAP"				{ RTOKEN(MAP);}
+<SCRIPT,EXPRESSION>"SIZEOF"		{ RTOKEN(SIZEOF);}
+<SCRIPT>"TARGET"			{ RTOKEN(TARGET_K);}
+<SCRIPT>"SEARCH_DIR"			{ RTOKEN(SEARCH_DIR);}
+<SCRIPT>"OUTPUT"			{ RTOKEN(OUTPUT);}
+<SCRIPT>"INPUT"				{ RTOKEN(INPUT);}
+<SCRIPT,EXPRESSION,WILD>"GROUP"		{ RTOKEN(GROUP);}
+<SCRIPT,EXPRESSION,INPUTLIST>"AS_NEEDED" { RTOKEN(AS_NEEDED);}
+<SCRIPT,EXPRESSION>"DEFINED"		{ RTOKEN(DEFINED);}
+<SCRIPT,WILD>"CREATE_OBJECT_SYMBOLS"	{ RTOKEN(CREATE_OBJECT_SYMBOLS);}
+<SCRIPT,WILD>"CONSTRUCTORS"		{ RTOKEN(CONSTRUCTORS);}
+<SCRIPT>"FORCE_COMMON_ALLOCATION"	{ RTOKEN(FORCE_COMMON_ALLOCATION);}
+<SCRIPT>"FORCE_GROUP_ALLOCATION"	{ RTOKEN(FORCE_GROUP_ALLOCATION);}
+<SCRIPT>"INHIBIT_COMMON_ALLOCATION"	{ RTOKEN(INHIBIT_COMMON_ALLOCATION);}
+<SCRIPT>"SECTIONS"			{ RTOKEN(SECTIONS);}
+<SCRIPT>"INSERT"			{ RTOKEN(INSERT_K);}
+<SCRIPT>"AFTER"				{ RTOKEN(AFTER);}
+<SCRIPT>"BEFORE"			{ RTOKEN(BEFORE);}
+<SCRIPT,WILD>"FILL"			{ RTOKEN(FILL);}
+<SCRIPT>"STARTUP"			{ RTOKEN(STARTUP);}
+<SCRIPT>"OUTPUT_FORMAT"			{ RTOKEN(OUTPUT_FORMAT);}
+<SCRIPT>"OUTPUT_ARCH"			{ RTOKEN(OUTPUT_ARCH);}
+<SCRIPT>"HLL"				{ RTOKEN(HLL);}
+<SCRIPT>"SYSLIB"			{ RTOKEN(SYSLIB);}
+<SCRIPT>"FLOAT"				{ RTOKEN(FLOAT);}
+<SCRIPT,WILD>"QUAD"			{ RTOKEN( QUAD);}
+<SCRIPT,WILD>"SQUAD"			{ RTOKEN( SQUAD);}
+<SCRIPT,WILD>"LONG"			{ RTOKEN( LONG);}
+<SCRIPT,WILD>"SHORT"			{ RTOKEN( SHORT);}
+<SCRIPT,WILD>"BYTE"			{ RTOKEN( BYTE);}
+<SCRIPT>"NOFLOAT"			{ RTOKEN(NOFLOAT);}
+<SCRIPT,EXPRESSION>"NOCROSSREFS"	{ RTOKEN(NOCROSSREFS);}
+<SCRIPT,EXPRESSION>"NOCROSSREFS_TO"	{ RTOKEN(NOCROSSREFS_TO);}
+<SCRIPT>"OVERLAY"			{ RTOKEN(OVERLAY); }
+<SCRIPT,WILD>"SORT_BY_NAME"		{ RTOKEN(SORT_BY_NAME); }
+<SCRIPT,WILD>"SORT_BY_ALIGNMENT"	{ RTOKEN(SORT_BY_ALIGNMENT); }
+<SCRIPT,WILD>"SORT"			{ RTOKEN(SORT_BY_NAME); }
+<SCRIPT,WILD>"SORT_BY_INIT_PRIORITY"	{ RTOKEN(SORT_BY_INIT_PRIORITY); }
+<SCRIPT,WILD>"SORT_NONE"		{ RTOKEN(SORT_NONE); }
+<SCRIPT,EXPRESSION>"NOLOAD"		{ RTOKEN(NOLOAD);}
+<SCRIPT,EXPRESSION>"READONLY"		{ RTOKEN(READONLY);}
+<SCRIPT,EXPRESSION>"DSECT"		{ RTOKEN(DSECT);}
+<SCRIPT,EXPRESSION>"COPY"		{ RTOKEN(COPY);}
+<SCRIPT,EXPRESSION>"INFO"		{ RTOKEN(INFO);}
+<SCRIPT,EXPRESSION>"OVERLAY"		{ RTOKEN(OVERLAY);}
+<EXPRESSION>"ONLY_IF_RO"		{ RTOKEN(ONLY_IF_RO); }
+<EXPRESSION>"ONLY_IF_RW"		{ RTOKEN(ONLY_IF_RW); }
+<EXPRESSION>"SPECIAL"			{ RTOKEN(SPECIAL); }
+<SCRIPT>"o"				{ RTOKEN(ORIGIN);}
+<SCRIPT>"org"				{ RTOKEN(ORIGIN);}
+<SCRIPT>"l"				{ RTOKEN( LENGTH);}
+<SCRIPT>"len"				{ RTOKEN( LENGTH);}
+<SCRIPT,EXPRESSION,WILD>"INPUT_SECTION_FLAGS" { RTOKEN(INPUT_SECTION_FLAGS); }
+<SCRIPT,EXPRESSION,WILD>"INCLUDE"	{ RTOKEN(INCLUDE);}
+<SCRIPT>"PHDRS"				{ RTOKEN (PHDRS); }
+<SCRIPT,EXPRESSION,WILD>"AT"		{ RTOKEN(AT);}
+<SCRIPT,EXPRESSION>"ALIGN_WITH_INPUT"	{ RTOKEN(ALIGN_WITH_INPUT);}
+<SCRIPT,EXPRESSION>"SUBALIGN"		{ RTOKEN(SUBALIGN);}
+<SCRIPT,EXPRESSION,WILD>"HIDDEN"	{ RTOKEN(HIDDEN); }
+<SCRIPT,EXPRESSION,WILD>"PROVIDE"	{ RTOKEN(PROVIDE); }
+<SCRIPT,EXPRESSION,WILD>"PROVIDE_HIDDEN" { RTOKEN(PROVIDE_HIDDEN); }
+<SCRIPT,EXPRESSION,WILD>"KEEP"		{ RTOKEN(KEEP); }
+<SCRIPT,EXPRESSION,WILD>"EXCLUDE_FILE"	{ RTOKEN(EXCLUDE_FILE); }
+<SCRIPT,EXPRESSION>"CONSTANT"		{ RTOKEN(CONSTANT);}
+
 <MRI>"#".*\n?			{ ++ lineno; }
 <MRI>"\n"			{ ++ lineno;  RTOKEN(NEWLINE); }
 <MRI>"*".*			{ /* Mri comment line */ }
@@ -338,7 +340,7 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 <MRI>"START"			{ RTOKEN(START); }
 <MRI>"LIST".*			{ RTOKEN(LIST); /* LIST and ignore to end of line */ }
 <MRI>"SECT"			{ RTOKEN(SECT); }
-<EXPRESSION,BOTH,SCRIPT,MRI>"ABSOLUTE"			{ RTOKEN(ABSOLUTE); }
+<SCRIPT,EXPRESSION,MRI>"ABSOLUTE"			{ RTOKEN(ABSOLUTE); }
 <MRI>"end"			{ RTOKEN(ENDWORD); }
 <MRI>"alignmod"			{ RTOKEN(ALIGNMOD);}
 <MRI>"align"			{ RTOKEN(ALIGN_K);}
@@ -356,7 +358,7 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 <MRI>"start"			{ RTOKEN(START); }
 <MRI>"list".*			{ RTOKEN(LIST); /* LIST and ignore to end of line */ }
 <MRI>"sect"			{ RTOKEN(SECT); }
-<EXPRESSION,BOTH,SCRIPT,MRI>"absolute"			{ RTOKEN(ABSOLUTE); }
+<SCRIPT,EXPRESSION,MRI>"absolute"			{ RTOKEN(ABSOLUTE); }
 
 <MRI>{FILENAMECHAR1}{NOCFILENAMECHAR}*	{
 /* Filename without commas, needed to parse mri stuff */
@@ -365,7 +367,7 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 				}
 
 
-<BOTH,INPUTLIST>{FILENAMECHAR1}{FILENAMECHAR}*	{
+<SCRIPT,INPUTLIST>{FILENAMECHAR1}{FILENAMECHAR}*	{
 				  yylval.name = xstrdup (yytext);
 				  return NAME;
 				}
@@ -374,7 +376,7 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 				  yylval.name = xstrdup (yytext);
 				  return NAME;
 				}
-<BOTH,INPUTLIST>"-l"{FILENAMECHAR}+ {
+<INPUTLIST>"-l"{FILENAMECHAR}+ {
 				  yylval.name = xstrdup (yytext + 2);
 				  return LNAME;
 				}
@@ -390,7 +392,7 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 				  yylval.name = xstrdup (yytext + 2);
 				  return LNAME;
 				}
-<SCRIPT>{WILDCHAR}* {
+<WILD>{WILDCHAR}* {
 		/* Annoyingly, this pattern can match comments, and we have
 		   longest match issues to consider.  So if the first two
 		   characters are a comment opening, put the input back and
@@ -407,7 +409,7 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 		  }
 	}
 
-<EXPRESSION,BOTH,SCRIPT,VERS_NODE,INPUTLIST>"\""[^\"]*"\"" {
+<SCRIPT,EXPRESSION,WILD,VERS_NODE,INPUTLIST>"\""[^\"]*"\"" {
 					/* No matter the state, quotes
 					   give what's inside.  */
 					bfd_size_type len;
@@ -421,11 +423,11 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 					return NAME;
 				}
 
-<BOTH,SCRIPT,EXPRESSION,VERS_START,VERS_NODE,VERS_SCRIPT,INPUTLIST>"\n" {
+<SCRIPT,EXPRESSION,WILD,VERS_START,VERS_NODE,VERS_SCRIPT,INPUTLIST>"\n" {
 				lineno++; }
-<MRI,BOTH,SCRIPT,EXPRESSION,VERS_START,VERS_NODE,VERS_SCRIPT,INPUTLIST>[ \t\r]+ {
+<MRI,SCRIPT,EXPRESSION,WILD,VERS_START,VERS_NODE,VERS_SCRIPT,INPUTLIST>[ \t\r]+ {
 				/* Eat up whitespace */ }
-<BOTH,SCRIPT,EXPRESSION,VERS_START,VERS_NODE,VERS_SCRIPT>#.* {
+<SCRIPT,EXPRESSION,WILD,VERS_START,VERS_NODE,VERS_SCRIPT>#.* {
 				/* Eat up comments */ }
 
 <VERS_NODE,VERS_SCRIPT>[:,;]	{ return *yytext; }
@@ -472,7 +474,7 @@  V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 }
 
 <SCRIPT,MRI,VERS_START,VERS_SCRIPT,VERS_NODE>.	lex_warn_invalid (" in script", yytext);
-<EXPRESSION,BOTH>.	lex_warn_invalid (" in expression", yytext);
+<EXPRESSION>.	lex_warn_invalid (" in expression", yytext);
 
 %%
 
@@ -609,10 +611,10 @@  ldlex_expression (void)
 }
 
 void
-ldlex_both (void)
+ldlex_wild (void)
 {
   *(state_stack_p)++ = yy_start;
-  BEGIN (BOTH);
+  BEGIN (WILD);
 }
 
 void