Make __DATA__ use the right pkg
authorFather Chrysostomos <sprout@cpan.org>
Sun, 25 Aug 2013 00:50:52 +0000 (17:50 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 25 Aug 2013 19:12:35 +0000 (12:12 -0700)
__DATA__ is supposed to stuff the rest of the file into the DATA han-
dle belonging to the package in scope where __DATA__ is encountered.
That means this should always print 123:

print <DATA>;
__DATA__
123

But it fails if the package has been renamed through glob assignment:

package foo;
BEGIN{*foo::=*bar::}
print <DATA>;
__DATA__
123

(Prints nothing.)

The code for stuffing DATA was stringifying the package and then look-
ing it up again.  Not only is it more correct to avoid the stringifi-
cation, but faster, too.

t/io/data.t
toke.c

index 52c6bc0..abcdebc 100644 (file)
@@ -79,3 +79,12 @@ lotsa junk
 nothing
 EXPECT
 ok
+########
+# Which package is __DATA__ in?
+package foo;
+BEGIN{*foo::=*bar::}
+print <DATA>;
+__DATA__
+123
+EXPECT
+123
diff --git a/toke.c b/toke.c
index f032f12..165fb71 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -7567,21 +7567,12 @@ Perl_yylex(pTHX)
        case KEY___END__: {
            GV *gv;
            if (PL_rsfp && (!PL_in_eval || PL_tokenbuf[2] == 'D')) {
-               const char *pname = "main";
-               STRLEN plen = 4;
-               U32 putf8 = 0;
-               if (PL_tokenbuf[2] == 'D')
-               {
-                   HV * const stash =
-                       PL_curstash ? PL_curstash : PL_defstash;
-                   pname = HvNAME_get(stash);
-                   plen  = HvNAMELEN (stash);
-                   if(HvNAMEUTF8(stash)) putf8 = SVf_UTF8;
-               }
-               gv = gv_fetchpvn_flags(
-                       Perl_form(aTHX_ "%*s::DATA", (int)plen, pname),
-                       plen+6, GV_ADD|putf8, SVt_PVIO
-               );
+               HV * const stash = PL_tokenbuf[2] == 'D' && PL_curstash
+                                       ? PL_curstash
+                                       : PL_defstash;
+               gv = (GV *)*hv_fetchs(stash, "DATA", 1);
+               if (!isGV(gv))
+                   gv_init(gv,stash,"DATA",4,0);
                GvMULTI_on(gv);
                if (!GvIO(gv))
                    GvIOp(gv) = newIO();