Nice bit of code. I thought I would play with it to allow for a couple of different cases. First, if someone didn't fully qualify the name, I used caller to determine the calling package and prepend that to the name. Second, what if someone passes you a bogus sub name? Then, the CODE slot in the typeglob should be undef and you get "use of unitialized value" warnings. Here's what I used to fix it and get a segfault.
package One;
use strict;
use warnings;
use constant FOO => 1;
sub bar { 1 };
foreach ( qw/ FOO One::FOO Two::FOO bar / ) {
if ( Two::is_constant( $_ ) ) {
print "Yes\n";
} else {
print "No\n";
}
}
package Two;
=pod
is_constant($sub_name) - returns true if subroutine is a
constant, false if not. $sub_name must be the fully
qualified name (Package::name) of a subroutine.
=cut
sub is_constant {
no strict 'refs';
my $name = shift;
if ( $name !~ /::/ ) {
$name = (caller)[0]."::$name";
}
my $code = *{$name}{CODE};
# must have any empty prototype to be a constant
my $proto;
#print "->$code<-\n";
if ( ref $code ) {
$proto = prototype($code);
}
return 0 if defined $proto and length $proto;
# attempt to redefine to itself - this will cause a
# warning for a real constant that starts with "Constant"
my $is_const;
{
local $SIG{__WARN__} = sub { $is_const = 1 if $_[0] =~ /^Const
+ant/ };
eval { *{$name} = sub () { "TEST" } };
}
# set it back
{
no warnings;
eval { *{$name} = $code; };
}
# all done
return $is_const;
}
If you look closely, you'll see that print "->$code<-\n"; has been commented out. If it's commented out, I get a segfault. If I uncomment it, merely printing the value allows the program to continue. Anyone see anything that I am missing? I get the problem running Win98 (5.6.0) and Cygwin under Win98 (5.6.1).
Cheers,
Ovid
Join the Perlmonks Setiathome Group or just click on the the link and check out our stats. |