f6ea51
From 07ebe9c4fb1028d17e61caabe8c15abd0cd48983 Mon Sep 17 00:00:00 2001
f6ea51
From: Yves Orton <demerphq@gmail.com>
f6ea51
Date: Thu, 29 Jun 2017 11:31:14 +0200
f6ea51
Subject: [PATCH] Parse caret vars with subscripts the same as normal vars
f6ea51
 inside of ${..} escaping
f6ea51
MIME-Version: 1.0
f6ea51
Content-Type: text/plain; charset=UTF-8
f6ea51
Content-Transfer-Encoding: 8bit
f6ea51
f6ea51
This behavior is discussed in perl #131664, which complains that
f6ea51
"${^CAPTURE}[0]" does not work as expected. Abigail explains the
f6ea51
behavior is by design and Eirik Berg Hanssen expands on that explanation
f6ea51
pointing out that what /should/ work, "${^CAPTURE[0]}" does not,
f6ea51
which Sawyer then ruled was a bug.
f6ea51
f6ea51
So this patch makes "${^CAPTURE[0]}" (and "${^CAPTURE [0]}" [hi
f6ea51
abigial]) work the same as they would if the var was called @foo.
f6ea51
f6ea51
Petr Písař: Ported to 5.26.2-RC1.
f6ea51
f6ea51
Signed-off-by: Petr Písař <ppisar@redhat.com>
f6ea51
---
f6ea51
 t/base/lex.t | 28 +++++++++++++++++++++++++++-
f6ea51
 toke.c       | 46 +++++++++++++++++++++++++---------------------
f6ea51
 2 files changed, 52 insertions(+), 22 deletions(-)
f6ea51
f6ea51
diff --git a/t/base/lex.t b/t/base/lex.t
f6ea51
index 99fd3bb..ae17bbd 100644
f6ea51
--- a/t/base/lex.t
f6ea51
+++ b/t/base/lex.t
f6ea51
@@ -1,6 +1,6 @@
f6ea51
 #!./perl
f6ea51
 
f6ea51
-print "1..112\n";
f6ea51
+print "1..119\n";
f6ea51
 
f6ea51
 $x = 'x';
f6ea51
 
f6ea51
@@ -154,6 +154,32 @@ my $test = 31;
f6ea51
   print "not " unless index ($@, 'Can\'t use global $^XYZ in "my"') > -1;
f6ea51
   print "ok $test\n"; $test++;
f6ea51
 #  print "($@)\n" if $@;
f6ea51
+#
f6ea51
+  ${^TEST}= "splat";
f6ea51
+  @{^TEST}= ("foo", "bar");
f6ea51
+  %{^TEST}= ("foo" => "FOO", "bar" => "BAR" );
f6ea51
+
f6ea51
+  print "not " if "${^TEST}" ne "splat";
f6ea51
+  print "ok $test\n"; $test++;
f6ea51
+
f6ea51
+  print "not " if "${^TEST}[0]" ne "splat[0]";
f6ea51
+  print "ok $test\n"; $test++;
f6ea51
+
f6ea51
+  print "not " if "${^TEST[0]}" ne "foo";
f6ea51
+  print "ok $test\n"; $test++;
f6ea51
+
f6ea51
+  print "not " if "${ ^TEST [1] }" ne "bar";
f6ea51
+  print "ok $test\n"; $test++;
f6ea51
+
f6ea51
+  print "not " if "${^TEST}{foo}" ne "splat{foo}";
f6ea51
+  print "ok $test\n"; $test++;
f6ea51
+
f6ea51
+  print "not " if "${^TEST{foo}}" ne "FOO";
f6ea51
+  print "ok $test\n"; $test++;
f6ea51
+
f6ea51
+  print "not " if "${ ^TEST {bar} }" ne "BAR";
f6ea51
+  print "ok $test\n"; $test++;
f6ea51
+
f6ea51
 
f6ea51
 # Now let's make sure that caret variables are all forced into the main package.
f6ea51
   package Someother;
f6ea51
diff --git a/toke.c b/toke.c
f6ea51
index ee9c464..aff785b 100644
f6ea51
--- a/toke.c
f6ea51
+++ b/toke.c
f6ea51
@@ -9416,19 +9416,36 @@ S_scan_ident(pTHX_ char *s, char *dest, STRLEN destlen, I32 ck_uni)
f6ea51
         bool skip;
f6ea51
         char *s2;
f6ea51
         /* If we were processing {...} notation then...  */
f6ea51
-        if (isIDFIRST_lazy_if_safe(d, e, is_utf8)) {
f6ea51
-            /* if it starts as a valid identifier, assume that it is one.
f6ea51
-               (the later check for } being at the expected point will trap
f6ea51
-               cases where this doesn't pan out.)  */
f6ea51
-            d += is_utf8 ? UTF8SKIP(d) : 1;
f6ea51
-            parse_ident(&s, &d, e, 1, is_utf8, TRUE);
f6ea51
-	    *d = '\0';
f6ea51
+        if (isIDFIRST_lazy_if_safe(d, e, is_utf8)
f6ea51
+            || (!isPRINT(*d) /* isCNTRL(d), plus all non-ASCII */
f6ea51
+                 && isWORDCHAR(*s))
f6ea51
+        ) {
f6ea51
+            /* note we have to check for a normal identifier first,
f6ea51
+             * as it handles utf8 symbols, and only after that has
f6ea51
+             * been ruled out can we look at the caret words */
f6ea51
+            if (isIDFIRST_lazy_if_safe(d, e, is_utf8) ) {
f6ea51
+                /* if it starts as a valid identifier, assume that it is one.
f6ea51
+                   (the later check for } being at the expected point will trap
f6ea51
+                   cases where this doesn't pan out.)  */
f6ea51
+                d += is_utf8 ? UTF8SKIP(d) : 1;
f6ea51
+                parse_ident(&s, &d, e, 1, is_utf8, TRUE);
f6ea51
+                *d = '\0';
f6ea51
+            }
f6ea51
+            else { /* caret word: ${^Foo} ${^CAPTURE[0]} */
f6ea51
+                d++;
f6ea51
+                while (isWORDCHAR(*s) && d < e) {
f6ea51
+                    *d++ = *s++;
f6ea51
+                }
f6ea51
+                if (d >= e)
f6ea51
+                    Perl_croak(aTHX_ "%s", ident_too_long);
f6ea51
+                *d = '\0';
f6ea51
+            }
f6ea51
             tmp_copline = CopLINE(PL_curcop);
f6ea51
             if (s < PL_bufend && isSPACE(*s)) {
f6ea51
                 s = skipspace(s);
f6ea51
             }
f6ea51
 	    if ((*s == '[' || (*s == '{' && strNE(dest, "sub")))) {
f6ea51
-                /* ${foo[0]} and ${foo{bar}} notation.  */
f6ea51
+                /* ${foo[0]} and ${foo{bar}} and ${^CAPTURE[0]} notation.  */
f6ea51
 		if (ckWARN(WARN_AMBIGUOUS) && keyword(dest, d - dest, 0)) {
f6ea51
 		    const char * const brack =
f6ea51
 			(const char *)
f6ea51
@@ -9447,19 +9464,6 @@ S_scan_ident(pTHX_ char *s, char *dest, STRLEN destlen, I32 ck_uni)
f6ea51
 		return s;
f6ea51
 	    }
f6ea51
 	}
f6ea51
-	/* Handle extended ${^Foo} variables
f6ea51
-	 * 1999-02-27 mjd-perl-patch@plover.com */
f6ea51
-	else if (! isPRINT(*d) /* isCNTRL(d), plus all non-ASCII */
f6ea51
-		 && isWORDCHAR(*s))
f6ea51
-	{
f6ea51
-	    d++;
f6ea51
-	    while (isWORDCHAR(*s) && d < e) {
f6ea51
-		*d++ = *s++;
f6ea51
-	    }
f6ea51
-	    if (d >= e)
f6ea51
-		Perl_croak(aTHX_ "%s", ident_too_long);
f6ea51
-	    *d = '\0';
f6ea51
-	}
f6ea51
 
f6ea51
         if ( !tmp_copline )
f6ea51
             tmp_copline = CopLINE(PL_curcop);
f6ea51
-- 
f6ea51
2.14.3
f6ea51