Make eval "#line" account for ${"_<foo"} changes
authorFather Chrysostomos <sprout@cpan.org>
Mon, 5 Aug 2013 07:13:40 +0000 (00:13 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Mon, 5 Aug 2013 09:23:33 +0000 (02:23 -0700)
If a BEGIN block in the eval modifies the ${"_<foo"} scalar where
‘foo’ is the file name in the eval, then subsequent #line directives
that change the file name won’t cause the lines to be copied to
@{"_<newname"}.  (This copying usually happens under the debugger.)

Just use the name of the GV itself, rather than CopFILESV, since the
GV name cannot be changed from Perl space.

t/comp/retainedlines.t
toke.c

index 01557a6..4dc69a2 100644 (file)
@@ -6,7 +6,7 @@
 # we've not yet verified that use works.
 # use strict;
 
-print "1..74\n";
+print "1..75\n";
 my $test = 0;
 
 sub failed {
@@ -161,3 +161,16 @@ for (0xA, 0) {
   is $::{"_<doggo"}[85], " labadalabada()\n",
    'subsequent #line 42 "foo" in a string eval updates @{"_<foo"}';
 }
+
+# Modifying ${"_<foo"} should not stop lines from being retained.
+{
+  local $^P = 0x400|0x100|0x10;
+  eval <<'end';
+#line 42 "copfilesv-modification"
+    BEGIN{ ${"_<copfilesv-modification"} = \1 }
+#line 52 "copfilesv-modified"
+    abcdefg();
+end
+  is $::{"_<copfilesv-modified"}[52], "    abcdefg();\n",
+   '#line 42 "foo" in a str eval is not confused by ${"_<foo"} changing';
+}
diff --git a/toke.c b/toke.c
index d891372..3689422 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -1753,27 +1753,19 @@ S_incline(pTHX_ const char *s)
 
     if (t - s > 0) {
        const STRLEN len = t - s;
-       if (!PL_rsfp && !PL_parser->filtered) {
+       GV * const cfgv = CopFILEGV(PL_curcop);
+
+       if (cfgv && !PL_rsfp && !PL_parser->filtered) {
            /* must copy *{"::_<(eval N)[oldfilename:L]"}
             * to *{"::_<newfilename"} */
            /* However, the long form of evals is only turned on by the
               debugger - usually they're "(eval %lu)" */
-           SV *const temp_sv = CopFILESV(PL_curcop);
-           const char *cf;
-           STRLEN tmplen;
+           const char *cf = GvNAME(cfgv)+2;
+           STRLEN tmplen = GvNAMELEN(cfgv)-2;
            char smallbuf[128];
            char *tmpbuf;
            GV **gvp;
            STRLEN tmplen2 = len;
-
-           if (temp_sv) {
-               cf = SvPVX(temp_sv);
-               tmplen = SvCUR(temp_sv);
-           } else {
-               cf = NULL;
-               tmplen = 0;
-           }
-
            if (tmplen + 2 <= sizeof smallbuf)
                tmpbuf = smallbuf;
            else