On Wed Nov 30 17:49:48 2011, sprout wrote:
> On Wed Nov 30 13:39:47 2011, l.mai@web.de wrote:
> > % perl -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)"
> > } } "a" =~ /(?<X>.)/ or die; print "$+{X}"'
> > IO::File::DESTROY(IO::File=IO(0x9447790)) at -e line 1.
> > Use of uninitialized value $+{"X"} in string at -e line 1.
> >
> > % perl -wle '%- if 0; { package UNIVERSAL; sub AUTOLOAD { warn
> > "$AUTOLOAD(@_)" } } "a" =~ /(?<X>.)/ or die; print "$+{X}"'
> > IO::File::DESTROY(IO::File=IO(0x823f798)) at -e line 1.
> > a
> >
>
Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fba8))
> > at -e line 1 during global destruction.
> >
>
Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fca8))
> > at -e line 1 during global destruction.
> > IO::File::DESTROY(IO::File=IO(0x823f078)) at -e line 1 during global
> > destruction.
> > IO::File::DESTROY(IO::File=IO(0x823f0f8)) at -e line 1 during global
> > destruction.
> > IO::File::DESTROY(IO::File=IO(0x823f178)) at -e line 1 during global
> > destruction.
> >
> >
> > So apparently just creating UNIVERSAL::AUTOLOAD is enough to break %+,
> > even if
> > AUTOLOAD is never called. But (for some reason) letting the parser see
> > %+ early
> > makes things work as expected.
> >
> > As far as I can tell this is broken in 5.12 and 5.10 but works in
> > 5.14,
> > probably because Tie::Hash::NamedCapture is a real (XS) module there.
> >
> > Any idea what's going on?
>
> It was indeed this commit that made the difference, but I cannot
> understand why:
>
> commit 8dcfe2e99a72fe7951b4d15325e1541232823204
> Author: Nicholas Clark <nick@ccl4.org>
> Date: Thu Oct 14 15:34:03 2010 +0100
>
> Move remaining Tie::Hash::NamedCapture XS code to NamedCapture.xs
>
> Now all the support code for %+ and %- is contained in the module in
> ext/
>
I’ve just figured it out. In gv.c:
S_require_tie_mod(pTHX_ GV *gv, const char *varpv, SV* namesv, const
char *methpv,const U32 flags)
{
dVAR;
HV* stash = gv_stashsv(namesv, 0);
PERL_ARGS_ASSERT_REQUIRE_TIE_MOD;
if (!stash || !(gv_fetchmethod(stash, methpv))) {
In gv.h:
#define gv_fetchmethod(stash, name) gv_fetchmethod_autoload(stash, name,
TRUE)
So, if either the stash does not exist (as in 5.14; in 5.12 parts of it
are in core), or the method (TIEHASH in this case) cannot be found, even
by autoloading, then the module is loaded.
That means the problem still persists in 5.14. You just have to mention
the package (e.g., ‘Tie::Hash::NamedCapture::Googoo() if 0’) and the
presence of a universal autoload sub will stop (compilation of) %- and
%+ from loading the module.
S_require_tie_mod probably should not be autoloading.
Errno and arybase have the same problem:
$ ./perl -Ilib -le 'arybase::Googoo() if 0; { package UNIVERSAL; sub
AUTOLOAD { warn "$AUTOLOAD(@_)" } } $[ = 1; print qw(a b c)[2]'
IO::File::DESTROY(IO::File=IO(0x823220)) at -e line 1.
c
(should print b)
$ ./perl -Ilib -le 'Errno::onrrE() if 0; { package UNIVERSAL; sub
AUTOLOAD { warn "$AUTOLOAD(@_)" } } $!=20; print $!{ENOTDIR}'
IO::File::DESTROY(IO::File=IO(0x823220)) at -e line 1.
(should print 20, on Unix at least)
--
Father Chrysostomos
Thread Previous
|
Thread Next