Make IO::Handle::getline(s) respect the open pragma
authorFather Chrysostomos <sprout@cpan.org>
Sat, 17 Sep 2011 19:09:22 +0000 (12:09 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 17 Sep 2011 19:12:30 +0000 (12:12 -0700)
commit986a805c4b258067b82c4f1254518e53cdb1acdf
treedc39cc8a91d0c4e01761d4e86182ab92ff7a3de5
parent7d167fe7dcb6293d9ee9583171a52b3da77f87a2
Make IO::Handle::getline(s) respect the open pragma

See <https://rt.cpan.org/Ticket/Display.html?id=66474>.  Also, this
came up in <https://rt.perl.org/rt3/Ticket/Display.html?id=92728>.

The <> operator, when reading from the magic ARGV handle, automatic-
ally opens the next file.  Layers set by the lexical open pragma are
applied, if they are in scope at the point where <> is used.

This works almost all the time, because the common convention is:

    use open ":utf8";

    while(<>) {
        ...
    }

IO::Handle’s getline and getlines methods are Perl subroutines
that call <> themselves.  But that happens within the scope of
IO/Handle.pm, so the caller’s I/O layer settings are ignored.  That
means that these two expressions are not equivalent within in a
‘use open’ scope:

    <>
    *ARGV->getline

The latter will open the next file with no layers applied.

This commit solves that by putting PL_check hooks in place in
IO::Handle before compiling the getline and getlines subroutines.
Those hooks cause every state op (nextstate, or dbstate under the
debugger) to have a custom pp function that saves the previous value
of PL_curcop, calls the default pp function, and then restores
PL_curcop.

That means that getline and getlines run with the caller’s compile-
time hints.  Another way to see it is that getline and getlines’s own
lexical hints are never activated.

(A state op carries all the lexical pragmata.  Every statement
has one.  When any op executes, it’s ‘pp’ function is called.
pp_nextstate and pp_dbstate both set PL_curcop to the op itself.  Any
code that checks hints looks at PL_curcop, which contains the current
run-time hints.)
MANIFEST
dist/IO/IO.pm
dist/IO/IO.xs
dist/IO/lib/IO/Handle.pm
dist/IO/t/IO.t
dist/IO/t/io_utf8argv.t [new file with mode: 0644]
pod/perldelta.pod