-
Notifications
You must be signed in to change notification settings - Fork 558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"Scalar found where operator expected" on printing to indirect filehandle within s///e #16847
Comments
From @CorionCreated by corion@corion.netThis is a bug report for perl from corion@corion.net, ----------------------------------------------------------------- last week I (together with E. Choroba) stumbled on a weird syntax perl -wle "s/(.*)/print $fh $1/e" This surprisingly gives a syntax error, yet still seems to run the code: Scalar found where operator expected at -e line 1, near "$fh $1" The code even outputs 'foo' in the below version: perl -wle "my $fh = \*STDOUT; $_ = ''; s//print $fh 'foo'/e" The "fix" for this (highly unconventional) code is to use curly brackets perl -wle "my $fh = \*STDOUT; $_ = ''; s//print {$fh} 'foo'/e" I still think that the original code should parse without error, even Perl Info
|
From @tonycozOn Fri, 15 Feb 2019 11:37:16 -0800, corion@corion.net wrote:
This isn't a syntax error, but a warning (but still buggy). The code inside the replacement part of s///e is handled with a sublex, and the code that decides whether an operator or term is expected after C<print $fh> is mostly skipped for a sublex. The attached fixes that, doing the same checks for C<print $fh> in a sublex within brackets as for a normal parse. This fixes the same problem for C<< "... ${code} ..." >>. Tony |
From @tonycoz0001-perl-133850-fix-parsing-hints-for-print-fh-foo-in-s-.patchFrom 9e0f09ef2afa82ef1a96cba981d4fca094bba484 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Tue, 19 Feb 2019 15:38:39 +1100
Subject: (perl #133850) fix parsing hints for print $fh "foo" in s///e
The replacement code in s///e is parsed using a sublex, similarly
to double-quotish replacement.
The code that handles C< $id > tries to detect what the next token
should be, but only special cased code similar to C< print $fh ... >
in a non-sublex, so s/../print $fh $1/e set PL_expect to XOPERATOR
which caused the parser to complain when the $1 wasn't an operator.
The fix here handles two cases:
s/.../code here/e
In this case the code is inserted into a do {} block like:
do { code here }
so PL_lex_brackets ends up non-zero.
The second case is code like:
"xxx${code here}"
which had the same problem, which this also fixes.
---
t/lib/warnings/toke | 14 ++++++++++++++
toke.c | 2 +-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/t/lib/warnings/toke b/t/lib/warnings/toke
index 1c85d7bc44..a500856283 100644
--- a/t/lib/warnings/toke
+++ b/t/lib/warnings/toke
@@ -1675,3 +1675,17 @@ Execution of - aborted due to compilation errors.
use utf8;
qw���foo ��� ��� bar���
EXPECT
+########
+# NAME [perl #133850] print $fh $1 in s///e expression
+use warnings;
+my $fh = \*STDOUT;
+$_ = "abc";
+s/(x)/ print $fh $1 /e;
+EXPECT
+########
+# NAME [perl #133850] side case
+use warnings;
+my $fh = \*STDOUT;
+my $y = "";
+my $x = "${print $fh $y; \'x'}";
+EXPECT
diff --git a/toke.c b/toke.c
index 5a3fe78472..0eb63fcb55 100644
--- a/toke.c
+++ b/toke.c
@@ -6772,7 +6772,7 @@ Perl_yylex(pTHX)
}
PL_expect = XOPERATOR;
- if (PL_lex_state == LEX_NORMAL && isSPACE((char)tmp)) {
+ if ((PL_lex_state == LEX_NORMAL || PL_lex_brackets) && isSPACE((char)tmp)) {
const bool islop = (PL_last_lop == PL_oldoldbufptr);
if (!islop || PL_last_lop_op == OP_GREPSTART)
PL_expect = XOPERATOR;
--
2.11.0
|
The RT System itself - Status changed from 'new' to 'open' |
From @tonycozOn Mon, 18 Feb 2019 20:44:26 -0800, tonyc wrote:
There's some other similar cases - i.e. where PL_lex_state is checked for LEX_NORMAL but no other checks are made. The simplest I was able to reproduce was: $ ./perl -we '%x = qw(a b c d); $_ = ""; $_ = @x {a}' Kind of unlikely: tony@mars:.../git/perl$ ./perl -Ilib -we '{ my $x : shared = 1; }' Another: $ ./perl -we '$a = ${time}' Tony |
From @tonycozOn Mon, 18 Feb 2019 20:44:26 -0800, tonyc wrote:
Rebased on blead, and fixes for the related issues. I'll apply this in a few days. Tony |
From @tonycozsubparse-tokens.patchFrom cb43f46efc62573c3470f5c2de01ee0e5b6ffd4a Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Tue, 19 Feb 2019 15:38:39 +1100
Subject: (perl #133850) fix parsing hints for print $fh "foo" in s///e
The replacement code in s///e is parsed using a sublex, similarly
to double-quotish replacement.
The code that handles C< $id > tries to detect what the next token
should be, but only special cased code similar to C< print $fh ... >
in a non-sublex, so s/../print $fh $1/e set PL_expect to XOPERATOR
which caused the parser to complain when the $1 wasn't an operator.
The fix here handles two cases:
s/.../code here/e
In this case the code is inserted into a do {} block like:
do { code here }
so PL_lex_brackets ends up non-zero.
The second case is code like:
"xxx${code here}"
which had the same problem, which this also fixes.
---
t/lib/warnings/toke | 14 ++++++++++++++
toke.c | 2 +-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/t/lib/warnings/toke b/t/lib/warnings/toke
index 83641e5106..944e5d92f4 100644
--- a/t/lib/warnings/toke
+++ b/t/lib/warnings/toke
@@ -1691,3 +1691,17 @@ EXPECT
OPTION regex
Malformed UTF-8 character: .*non-continuation.*
The eval did not crash the program
+########
+# NAME [perl #133850] print $fh $1 in s///e expression
+use warnings;
+my $fh = \*STDOUT;
+$_ = "abc";
+s/(x)/ print $fh $1 /e;
+EXPECT
+########
+# NAME [perl #133850] side case
+use warnings;
+my $fh = \*STDOUT;
+my $y = "";
+my $x = "${print $fh $y; \'x'}";
+EXPECT
diff --git a/toke.c b/toke.c
index b0fa2c35ba..dc376f6beb 100644
--- a/toke.c
+++ b/toke.c
@@ -6838,7 +6838,7 @@ Perl_yylex(pTHX)
}
PL_expect = XOPERATOR;
- if (PL_lex_state == LEX_NORMAL && isSPACE((char)tmp)) {
+ if ((PL_lex_state == LEX_NORMAL || PL_lex_brackets) && isSPACE((char)tmp)) {
const bool islop = (PL_last_lop == PL_oldoldbufptr);
if (!islop || PL_last_lop_op == OP_GREPSTART)
PL_expect = XOPERATOR;
--
2.11.0
From 2b67caa9b5055eb7441998a9538af722639982af Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Wed, 29 May 2019 11:46:01 +1000
Subject: (perl #133850) warn on ${time} even in sub-parse
Code like:
$a = ${time}
warns with:
Ambiguous use of ${time} resolved to $time at ...
but:
s/^/ ${time} /e
didn't, since the parser is in a special state in sub-parses.
---
t/lib/warnings/toke | 8 ++++++++
toke.c | 2 +-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/t/lib/warnings/toke b/t/lib/warnings/toke
index 944e5d92f4..eab22fbbc9 100644
--- a/t/lib/warnings/toke
+++ b/t/lib/warnings/toke
@@ -1705,3 +1705,11 @@ my $fh = \*STDOUT;
my $y = "";
my $x = "${print $fh $y; \'x'}";
EXPECT
+########
+# NAME [perl #133850] another case
+use warnings;
+my $time = 1;
+$_ = "";
+s/^/ ${time} /e
+EXPECT
+Ambiguous use of ${time} resolved to $time at - line 4.
diff --git a/toke.c b/toke.c
index dc376f6beb..c42d4fd802 100644
--- a/toke.c
+++ b/toke.c
@@ -9660,7 +9660,7 @@ S_scan_ident(pTHX_ char *s, char *dest, STRLEN destlen, I32 ck_uni)
PL_lex_state = LEX_INTERPEND;
PL_expect = XREF;
}
- if (PL_lex_state == LEX_NORMAL) {
+ if (PL_lex_state == LEX_NORMAL || PL_lex_brackets) {
if (ckWARN(WARN_AMBIGUOUS)
&& (keyword(dest, d - dest, 0)
|| get_cvn_flags(dest, d - dest, is_utf8
--
2.11.0
From f623089c7b47c9de58667b70063be135948356bd Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Wed, 29 May 2019 13:47:36 +1000
Subject: (perl #133850) allow @x{...} with space in sub-parse
---
t/lib/warnings/toke | 8 ++++++++
toke.c | 2 +-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/t/lib/warnings/toke b/t/lib/warnings/toke
index eab22fbbc9..5dbef1ab62 100644
--- a/t/lib/warnings/toke
+++ b/t/lib/warnings/toke
@@ -1713,3 +1713,11 @@ $_ = "";
s/^/ ${time} /e
EXPECT
Ambiguous use of ${time} resolved to $time at - line 4.
+########
+# NAME [perl #133850] another case
+use warnings;
+%x = qw(a b c d);
+$_ = "";
+s/^/ @x {a} /e
+EXPECT
+Scalar value @x{"a"} better written as $x{"a"} at - line 4.
diff --git a/toke.c b/toke.c
index c42d4fd802..e1b163334f 100644
--- a/toke.c
+++ b/toke.c
@@ -6911,7 +6911,7 @@ Perl_yylex(pTHX)
if (!PL_tokenbuf[1]) {
PREREF('@');
}
- if (PL_lex_state == LEX_NORMAL)
+ if (PL_lex_state == LEX_NORMAL || PL_lex_brackets)
s = skipspace(s);
if ( (PL_expect != XREF || PL_oldoldbufptr == PL_last_lop)
&& intuit_more(s, PL_bufend))
--
2.11.0
From d50d49c97634fa03d472f06bf4e70fe7dfc17fd2 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Wed, 29 May 2019 14:37:25 +1000
Subject: (perl #133850) allow attributes in sub-parses
---
t/op/attrs.t | 3 +++
toke.c | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/t/op/attrs.t b/t/op/attrs.t
index 649525ce22..dd230b3fbd 100644
--- a/t/op/attrs.t
+++ b/t/op/attrs.t
@@ -507,4 +507,7 @@ BEGIN failed--compilation aborted at - line 1.
EOS
"attribute on our hash with sub of same name");
+fresh_perl_is('$_ = ""; s/^/ { my $x : shared = 1; } /e;', "", {},
+ "attributes in sub-parse");
+
done_testing();
diff --git a/toke.c b/toke.c
index e1b163334f..0b3b76fee3 100644
--- a/toke.c
+++ b/toke.c
@@ -5991,7 +5991,7 @@ Perl_yylex(pTHX)
switch (PL_expect) {
case XOPERATOR:
- if (!PL_in_my || PL_lex_state != LEX_NORMAL)
+ if (!PL_in_my || (PL_lex_state != LEX_NORMAL && !PL_lex_brackets))
break;
PL_bufptr = s; /* update in case we back off */
if (*s == '=') {
--
2.11.0
|
From @tonycozOn Tue, 28 May 2019 22:08:50 -0700, tonyc wrote:
Applied as eec8822 through 82de236. Tony |
@tonycoz - Status changed from 'open' to 'pending release' |
Migrated from rt.perl.org#133850 (status was 'pending release')
Searchable as RT133850$
The text was updated successfully, but these errors were encountered: