|
Packit |
b48d6e |
package Devel::Symdump;
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
use 5.003;
|
|
Packit |
b48d6e |
use Carp ();
|
|
Packit |
b48d6e |
use strict;
|
|
Packit |
b48d6e |
use vars qw($Defaults $VERSION *ENTRY $MAX_RECURSION);
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
$VERSION = '2.18';
|
|
Packit |
b48d6e |
$MAX_RECURSION = 97;
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
$Defaults = {
|
|
Packit |
b48d6e |
'RECURS' => 0,
|
|
Packit |
b48d6e |
'AUTOLOAD' => {
|
|
Packit |
b48d6e |
'packages' => 1,
|
|
Packit |
b48d6e |
'scalars' => 1,
|
|
Packit |
b48d6e |
'arrays' => 1,
|
|
Packit |
b48d6e |
'hashes' => 1,
|
|
Packit |
b48d6e |
'functions' => 1,
|
|
Packit |
b48d6e |
'ios' => 1,
|
|
Packit |
b48d6e |
'unknowns' => 1,
|
|
Packit |
b48d6e |
},
|
|
Packit |
b48d6e |
'SEEN' => {},
|
|
Packit |
b48d6e |
};
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub rnew {
|
|
Packit |
b48d6e |
my($class,@packages) = @_;
|
|
Packit |
b48d6e |
no strict "refs";
|
|
Packit |
b48d6e |
my $self = bless {%${"$class\::Defaults"}}, $class;
|
|
Packit |
b48d6e |
$self->{RECURS}++;
|
|
Packit |
b48d6e |
$self->_doit(@packages);
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub new {
|
|
Packit |
b48d6e |
my($class,@packages) = @_;
|
|
Packit |
b48d6e |
no strict "refs";
|
|
Packit |
b48d6e |
my $self = bless {%${"$class\::Defaults"}}, $class;
|
|
Packit |
b48d6e |
$self->_doit(@packages);
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub _doit {
|
|
Packit |
b48d6e |
my($self,@packages) = @_;
|
|
Packit |
b48d6e |
@packages = ("main") unless @packages;
|
|
Packit |
b48d6e |
$self->{RESULT} = $self->_symdump(@packages);
|
|
Packit |
b48d6e |
return $self;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub _symdump {
|
|
Packit |
b48d6e |
my($self,@packages) = @_ ;
|
|
Packit |
b48d6e |
my($key,$val,$num,$pack,@todo,$tmp);
|
|
Packit |
b48d6e |
my $result = {};
|
|
Packit |
b48d6e |
foreach $pack (@packages){
|
|
Packit |
b48d6e |
no strict;
|
|
Packit |
b48d6e |
while (($key,$val) = each(%{*{"$pack\::"}})) {
|
|
Packit |
b48d6e |
my $gotone = 0;
|
|
Packit |
b48d6e |
local(*ENTRY) = $val;
|
|
Packit |
b48d6e |
#### SCALAR ####
|
|
Packit |
b48d6e |
if (defined $val && defined *ENTRY{SCALAR}) {
|
|
Packit |
b48d6e |
$result->{$pack}{SCALARS}{$key}++;
|
|
Packit |
b48d6e |
$gotone++;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
#### ARRAY ####
|
|
Packit |
b48d6e |
if (defined $val && defined *ENTRY{ARRAY}) {
|
|
Packit |
b48d6e |
$result->{$pack}{ARRAYS}{$key}++;
|
|
Packit |
b48d6e |
$gotone++;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
#### HASH ####
|
|
Packit |
b48d6e |
if (defined $val && defined *ENTRY{HASH} && $key !~ /::/) {
|
|
Packit |
b48d6e |
$result->{$pack}{HASHES}{$key}++;
|
|
Packit |
b48d6e |
$gotone++;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
#### PACKAGE ####
|
|
Packit |
b48d6e |
if (defined $val && defined *ENTRY{HASH} && $key =~ /::$/ &&
|
|
Packit |
b48d6e |
$key ne "main::" && $key ne "<none>::") {
|
|
Packit |
b48d6e |
my($p) = $pack ne "main" ? "$pack\::" : "";
|
|
Packit |
b48d6e |
($p .= $key) =~ s/::$//;
|
|
Packit |
b48d6e |
$result->{$pack}{PACKAGES}{$p}++;
|
|
Packit |
b48d6e |
$gotone++;
|
|
Packit |
b48d6e |
if (++$self->{SEEN}{*$val} > $Devel::Symdump::MAX_RECURSION){
|
|
Packit |
b48d6e |
next;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
push @todo, $p;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
#### FUNCTION ####
|
|
Packit |
b48d6e |
if (defined $val && defined *ENTRY{CODE}) {
|
|
Packit |
b48d6e |
$result->{$pack}{FUNCTIONS}{$key}++;
|
|
Packit |
b48d6e |
$gotone++;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
#### IO #### had to change after 5.003_10
|
|
Packit |
b48d6e |
if ($] > 5.003_10){
|
|
Packit |
b48d6e |
if (defined $val && defined *ENTRY{IO}){ # fileno and telldir...
|
|
Packit |
b48d6e |
$result->{$pack}{IOS}{$key}++;
|
|
Packit |
b48d6e |
$gotone++;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
} else {
|
|
Packit |
b48d6e |
#### FILEHANDLE ####
|
|
Packit |
b48d6e |
if (defined fileno(ENTRY)){
|
|
Packit |
b48d6e |
$result->{$pack}{IOS}{$key}++;
|
|
Packit |
b48d6e |
$gotone++;
|
|
Packit |
b48d6e |
} elsif (defined telldir(ENTRY)){
|
|
Packit |
b48d6e |
#### DIRHANDLE ####
|
|
Packit |
b48d6e |
$result->{$pack}{IOS}{$key}++;
|
|
Packit |
b48d6e |
$gotone++;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
#### SOMETHING ELSE ####
|
|
Packit |
b48d6e |
unless ($gotone) {
|
|
Packit |
b48d6e |
$result->{$pack}{UNKNOWNS}{$key}++;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
return (@todo && $self->{RECURS})
|
|
Packit |
b48d6e |
? { %$result, %{$self->_symdump(@todo)} }
|
|
Packit |
b48d6e |
: $result;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub _partdump {
|
|
Packit |
b48d6e |
my($self,$part)=@_;
|
|
Packit |
b48d6e |
my ($pack, @result);
|
|
Packit |
b48d6e |
my $prepend = "";
|
|
Packit |
b48d6e |
foreach $pack (keys %{$self->{RESULT}}){
|
|
Packit |
b48d6e |
$prepend = "$pack\::" unless $part eq 'PACKAGES';
|
|
Packit |
b48d6e |
push @result, map {"$prepend$_"} keys %{$self->{RESULT}{$pack}{$part} || {}};
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
return @result;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
# this is needed so we don't try to AUTOLOAD the DESTROY method
|
|
Packit |
b48d6e |
sub DESTROY {}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub as_string {
|
|
Packit |
b48d6e |
my $self = shift;
|
|
Packit |
b48d6e |
my($type,@m);
|
|
Packit |
b48d6e |
for $type (sort keys %{$self->{'AUTOLOAD'}}) {
|
|
Packit |
b48d6e |
push @m, $type;
|
|
Packit |
b48d6e |
push @m, "\t" . join "\n\t", map {
|
|
Packit |
b48d6e |
s/([\000-\037\177])/ '^' . pack('c', ord($1) ^ 64) /eg;
|
|
Packit |
b48d6e |
$_;
|
|
Packit |
b48d6e |
} sort $self->_partdump(uc $type);
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
return join "\n", @m;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub as_HTML {
|
|
Packit |
b48d6e |
my $self = shift;
|
|
Packit |
b48d6e |
my($type,@m);
|
|
Packit |
b48d6e |
push @m, "";
|
|
Packit |
b48d6e |
for $type (sort keys %{$self->{'AUTOLOAD'}}) {
|
|
Packit |
b48d6e |
push @m, "$type";
|
|
Packit |
b48d6e |
push @m, "" . join ", ", map {
|
|
Packit |
b48d6e |
s/([\000-\037\177])/ '^' .
|
|
Packit |
b48d6e |
pack('c', ord($1) ^ 64)
|
|
Packit |
b48d6e |
/eg; $_;
|
|
Packit |
b48d6e |
} sort $self->_partdump(uc $type);
|
|
Packit |
b48d6e |
push @m, "";
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
push @m, "";
|
|
Packit |
b48d6e |
return join "\n", @m;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub diff {
|
|
Packit |
b48d6e |
my($self,$second) = @_;
|
|
Packit |
b48d6e |
my($type,@m);
|
|
Packit |
b48d6e |
for $type (sort keys %{$self->{'AUTOLOAD'}}) {
|
|
Packit |
b48d6e |
my(%first,%second,%all,$symbol);
|
|
Packit |
b48d6e |
foreach $symbol ($self->_partdump(uc $type)){
|
|
Packit |
b48d6e |
$first{$symbol}++;
|
|
Packit |
b48d6e |
$all{$symbol}++;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
foreach $symbol ($second->_partdump(uc $type)){
|
|
Packit |
b48d6e |
$second{$symbol}++;
|
|
Packit |
b48d6e |
$all{$symbol}++;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
my(@typediff);
|
|
Packit |
b48d6e |
foreach $symbol (sort keys %all){
|
|
Packit |
b48d6e |
next if $first{$symbol} && $second{$symbol};
|
|
Packit |
b48d6e |
push @typediff, "- $symbol" unless $second{$symbol};
|
|
Packit |
b48d6e |
push @typediff, "+ $symbol" unless $first{$symbol};
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
foreach (@typediff) {
|
|
Packit |
b48d6e |
s/([\000-\037\177])/ '^' . pack('c', ord($1) ^ 64) /eg;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
push @m, $type, @typediff if @typediff;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
return join "\n", @m;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub inh_tree {
|
|
Packit |
b48d6e |
my($self) = @_;
|
|
Packit |
b48d6e |
return $self->{INHTREE} if ref $self && defined $self->{INHTREE};
|
|
Packit |
b48d6e |
my($inherited_by) = {};
|
|
Packit |
b48d6e |
my($m)="";
|
|
Packit |
b48d6e |
my(@isa) = grep /\bISA$/, Devel::Symdump->rnew->arrays;
|
|
Packit |
b48d6e |
my $isa;
|
|
Packit |
b48d6e |
foreach $isa (sort @isa) {
|
|
Packit |
b48d6e |
$isa =~ s/::ISA$//;
|
|
Packit |
b48d6e |
my($isaisa);
|
|
Packit |
b48d6e |
no strict 'refs';
|
|
Packit |
b48d6e |
foreach $isaisa (@{"$isa\::ISA"}){
|
|
Packit |
b48d6e |
$inherited_by->{$isaisa}{$isa}++;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
my $item;
|
|
Packit |
b48d6e |
foreach $item (sort keys %$inherited_by) {
|
|
Packit |
b48d6e |
$m .= "$item\n";
|
|
Packit |
b48d6e |
$m .= _inh_tree($item,$inherited_by);
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
$self->{INHTREE} = $m if ref $self;
|
|
Packit |
b48d6e |
$m;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub _inh_tree {
|
|
Packit |
b48d6e |
my($package,$href,$depth) = @_;
|
|
Packit |
b48d6e |
return unless defined $href;
|
|
Packit |
b48d6e |
$depth ||= 0;
|
|
Packit |
b48d6e |
$depth++;
|
|
Packit |
b48d6e |
if ($depth > 100){
|
|
Packit |
b48d6e |
warn "Deep recursion in ISA\n";
|
|
Packit |
b48d6e |
return;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
my($m) = "";
|
|
Packit |
b48d6e |
# print "DEBUG: package[$package]depth[$depth]\n";
|
|
Packit |
b48d6e |
my $i;
|
|
Packit |
b48d6e |
foreach $i (sort keys %{$href->{$package}}) {
|
|
Packit |
b48d6e |
$m .= qq{\t} x $depth;
|
|
Packit |
b48d6e |
$m .= qq{$i\n};
|
|
Packit |
b48d6e |
$m .= _inh_tree($i,$href,$depth);
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
$m;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub isa_tree{
|
|
Packit |
b48d6e |
my($self) = @_;
|
|
Packit |
b48d6e |
return $self->{ISATREE} if ref $self && defined $self->{ISATREE};
|
|
Packit |
b48d6e |
my(@isa) = grep /\bISA$/, Devel::Symdump->rnew->arrays;
|
|
Packit |
b48d6e |
my($m) = "";
|
|
Packit |
b48d6e |
my($isa);
|
|
Packit |
b48d6e |
foreach $isa (sort @isa) {
|
|
Packit |
b48d6e |
$isa =~ s/::ISA$//;
|
|
Packit |
b48d6e |
$m .= qq{$isa\n};
|
|
Packit |
b48d6e |
$m .= _isa_tree($isa)
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
$self->{ISATREE} = $m if ref $self;
|
|
Packit |
b48d6e |
$m;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
sub _isa_tree{
|
|
Packit |
b48d6e |
my($package,$depth) = @_;
|
|
Packit |
b48d6e |
$depth ||= 0;
|
|
Packit |
b48d6e |
$depth++;
|
|
Packit |
b48d6e |
if ($depth > 100){
|
|
Packit |
b48d6e |
warn "Deep recursion in ISA\n";
|
|
Packit |
b48d6e |
return;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
my($m) = "";
|
|
Packit |
b48d6e |
# print "DEBUG: package[$package]depth[$depth]\n";
|
|
Packit |
b48d6e |
my $isaisa;
|
|
Packit |
b48d6e |
no strict 'refs';
|
|
Packit |
b48d6e |
foreach $isaisa (@{"$package\::ISA"}) {
|
|
Packit |
b48d6e |
$m .= qq{\t} x $depth;
|
|
Packit |
b48d6e |
$m .= qq{$isaisa\n};
|
|
Packit |
b48d6e |
$m .= _isa_tree($isaisa,$depth);
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
$m;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
AUTOLOAD {
|
|
Packit |
b48d6e |
my($self,@packages) = @_;
|
|
Packit |
b48d6e |
unless (ref $self) {
|
|
Packit |
b48d6e |
$self = $self->new(@packages);
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
no strict "vars";
|
|
Packit |
b48d6e |
(my $auto = $AUTOLOAD) =~ s/.*:://;
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
$auto =~ s/(file|dir)handles/ios/;
|
|
Packit |
b48d6e |
my $compat = $1;
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
unless ($self->{'AUTOLOAD'}{$auto}) {
|
|
Packit |
b48d6e |
Carp::croak("invalid Devel::Symdump method: $auto()");
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
my @syms = $self->_partdump(uc $auto);
|
|
Packit |
b48d6e |
if (defined $compat) {
|
|
Packit |
b48d6e |
no strict 'refs';
|
|
Packit |
b48d6e |
local $^W; # bleadperl@26631 introduced an io warning here
|
|
Packit |
b48d6e |
if ($compat eq "file") {
|
|
Packit |
b48d6e |
@syms = grep { defined(fileno($_)) } @syms;
|
|
Packit |
b48d6e |
} else {
|
|
Packit |
b48d6e |
@syms = grep { _is_dirhandle($_) } @syms;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
return @syms; # make sure now it gets context right
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
use Config ();
|
|
Packit |
b48d6e |
use constant HAVE_TELLDIR => $Config::Config{d_telldir};
|
|
Packit |
b48d6e |
sub _is_dirhandle {
|
|
Packit |
b48d6e |
my ($glob) = @_;
|
|
Packit |
b48d6e |
if ( HAVE_TELLDIR ) {
|
|
Packit |
b48d6e |
return defined(telldir($glob));
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
else {
|
|
Packit |
b48d6e |
if ( !ref $glob ) {
|
|
Packit |
b48d6e |
no strict 'refs';
|
|
Packit |
b48d6e |
$glob = \*{$glob};
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
require B;
|
|
Packit |
b48d6e |
my $obj = B::svref_2object($glob);
|
|
Packit |
b48d6e |
return if !$obj || !eval{ $obj->IO; $obj->IO->IoTYPE; 1 };
|
|
Packit |
b48d6e |
my $mode = $obj->IO->IoTYPE;
|
|
Packit |
b48d6e |
return $mode eq "\0" ? 1 : 0;
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
}
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
1;
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
__END__
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=head1 NAME
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
Devel::Symdump - dump symbol names or the symbol table
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=head1 SYNOPSIS
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
# Constructor
|
|
Packit |
b48d6e |
require Devel::Symdump;
|
|
Packit |
b48d6e |
@packs = qw(some_package another_package);
|
|
Packit |
b48d6e |
$obj = Devel::Symdump->new(@packs); # no recursion
|
|
Packit |
b48d6e |
$obj = Devel::Symdump->rnew(@packs); # with recursion
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
# Methods
|
|
Packit |
b48d6e |
@array = $obj->packages;
|
|
Packit |
b48d6e |
@array = $obj->scalars;
|
|
Packit |
b48d6e |
@array = $obj->arrays;
|
|
Packit |
b48d6e |
@array = $obj->hashes;
|
|
Packit |
b48d6e |
@array = $obj->functions;
|
|
Packit |
b48d6e |
@array = $obj->filehandles; # deprecated, use ios instead
|
|
Packit |
b48d6e |
@array = $obj->dirhandles; # deprecated, use ios instead
|
|
Packit |
b48d6e |
@array = $obj->ios;
|
|
Packit |
b48d6e |
@array = $obj->unknowns; # only perl version < 5.003 had some
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
$string = $obj->as_string;
|
|
Packit |
b48d6e |
$string = $obj->as_HTML;
|
|
Packit |
b48d6e |
$string = $obj1->diff($obj2);
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
$string = Devel::Symdump->isa_tree; # or $obj->isa_tree
|
|
Packit |
b48d6e |
$string = Devel::Symdump->inh_tree; # or $obj->inh_tree
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
# Methods with autogenerated objects
|
|
Packit |
b48d6e |
# all of those call new(@packs) internally
|
|
Packit |
b48d6e |
@array = Devel::Symdump->packages(@packs);
|
|
Packit |
b48d6e |
@array = Devel::Symdump->scalars(@packs);
|
|
Packit |
b48d6e |
@array = Devel::Symdump->arrays(@packs);
|
|
Packit |
b48d6e |
@array = Devel::Symdump->hashes(@packs);
|
|
Packit |
b48d6e |
@array = Devel::Symdump->functions(@packs);
|
|
Packit |
b48d6e |
@array = Devel::Symdump->ios(@packs);
|
|
Packit |
b48d6e |
@array = Devel::Symdump->unknowns(@packs);
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=head1 DESCRIPTION
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
This little package serves to access the symbol table of perl.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=over 4
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=item C<Devel::Symdump-E<gt>rnew(@packages)>
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
returns a symbol table object for all subtrees below @packages.
|
|
Packit |
b48d6e |
Nested Modules are analyzed recursively. If no package is given as
|
|
Packit |
b48d6e |
argument, it defaults to C<main>. That means to get the whole symbol
|
|
Packit |
b48d6e |
table, just do a C<rnew> without arguments.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
The global variable $Devel::Symdump::MAX_RECURSION limits the
|
|
Packit |
b48d6e |
recursion to prevent contention. The default value is set to 97, just
|
|
Packit |
b48d6e |
low enough to survive the test suite without a warning about deep
|
|
Packit |
b48d6e |
recursion.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=item C<Devel::Symdump-E<gt>new(@packages)>
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
does not go into recursion and only analyzes the packages that are
|
|
Packit |
b48d6e |
given as arguments.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=item packages, scalars, arrays, hashes, functions, ios
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
The methods packages(), scalars(), arrays(), hashes(), functions(),
|
|
Packit |
b48d6e |
ios(), and (for older perls) unknowns() each return an array of fully
|
|
Packit |
b48d6e |
qualified symbols of the specified type in all packages that are held
|
|
Packit |
b48d6e |
within a Devel::Symdump object, but without the leading C<$>, C<@> or
|
|
Packit |
b48d6e |
C<%>. In a scalar context, they will return the number of such
|
|
Packit |
b48d6e |
symbols. Unknown symbols are usually either formats or variables that
|
|
Packit |
b48d6e |
haven't yet got a defined value.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
Note that scalar symbol table entries are a special case. If a symbol
|
|
Packit |
b48d6e |
table entry exists at all, presence of a scalar is currently
|
|
Packit |
b48d6e |
unknowable, due to a feature of Perl described in L
|
|
Packit |
b48d6e |
References> point 7. For example, this package will mark a scalar
|
|
Packit |
b48d6e |
value C<$foo> as present if any of C<@foo>, C<%foo>, C<&foo> etc. have
|
|
Packit |
b48d6e |
been declared or used.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=item as_string
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=item as_HTML
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
As_string() and as_HTML() return a simple string/HTML representations
|
|
Packit |
b48d6e |
of the object.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=item diff
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
Diff() prints the difference between two Devel::Symdump objects in
|
|
Packit |
b48d6e |
human readable form. The format is similar to the one used by the
|
|
Packit |
b48d6e |
as_string method.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=item isa_tree
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=item inh_tree
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
Isa_tree() and inh_tree() both return a simple string representation
|
|
Packit |
b48d6e |
of the current inheritance tree. The difference between the two
|
|
Packit |
b48d6e |
methods is the direction from which the tree is viewed: top-down or
|
|
Packit |
b48d6e |
bottom-up. As I'm sure, many users will have different expectation
|
|
Packit |
b48d6e |
about what is top and what is bottom, I'll provide an example what
|
|
Packit |
b48d6e |
happens when the Socket module is loaded:
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=item % print Devel::Symdump-E<gt>inh_tree
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
AutoLoader
|
|
Packit |
b48d6e |
DynaLoader
|
|
Packit |
b48d6e |
Socket
|
|
Packit |
b48d6e |
DynaLoader
|
|
Packit |
b48d6e |
Socket
|
|
Packit |
b48d6e |
Exporter
|
|
Packit |
b48d6e |
Carp
|
|
Packit |
b48d6e |
Config
|
|
Packit |
b48d6e |
Socket
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
The inh_tree method shows on the left hand side a package name and
|
|
Packit |
b48d6e |
indented to the right the packages that use the former.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=item % print Devel::Symdump-E<gt>isa_tree
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
Carp
|
|
Packit |
b48d6e |
Exporter
|
|
Packit |
b48d6e |
Config
|
|
Packit |
b48d6e |
Exporter
|
|
Packit |
b48d6e |
DynaLoader
|
|
Packit |
b48d6e |
AutoLoader
|
|
Packit |
b48d6e |
Socket
|
|
Packit |
b48d6e |
Exporter
|
|
Packit |
b48d6e |
DynaLoader
|
|
Packit |
b48d6e |
AutoLoader
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
The isa_tree method displays from left to right ISA relationships, so
|
|
Packit |
b48d6e |
Socket IS A DynaLoader and DynaLoader IS A AutoLoader. (Actually, they
|
|
Packit |
b48d6e |
were at the time this manpage was written)
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=back
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
You may call both methods, isa_tree() and inh_tree(), with an
|
|
Packit |
b48d6e |
object. If you do that, the object will store the output and retrieve
|
|
Packit |
b48d6e |
it when you call the same method again later. The typical usage would
|
|
Packit |
b48d6e |
be to use them as class methods directly though.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=head1 SUBCLASSING
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
The design of this package is intentionally primitive and allows it to
|
|
Packit |
b48d6e |
be subclassed easily. An example of a (maybe) useful subclass is
|
|
Packit |
b48d6e |
Devel::Symdump::Export, a package which exports all methods of the
|
|
Packit |
b48d6e |
Devel::Symdump package and turns them into functions.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=head1 SEE ALSO
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
Routines for manipulating stashes: C<Package::Stash>; to work with
|
|
Packit |
b48d6e |
lexicals: C<PadWalker>.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=head1 AUTHORS
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
Andreas Koenig F<< <andk@cpan.org> >> and Tom Christiansen
|
|
Packit |
b48d6e |
F<< <tchrist@perl.com> >>. Based on the old F<dumpvar.pl> by Larry
|
|
Packit |
b48d6e |
Wall.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=head1 COPYRIGHT, LICENSE
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
This module is
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
Copyright (c) 1995, 1997, 2000, 2002, 2005, 2006 Andreas Koenig C<< <andk@cpan.org> >>.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
All rights reserved.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
This library is free software;
|
|
Packit |
b48d6e |
you may use, redistribute and/or modify it under the same
|
|
Packit |
b48d6e |
terms as Perl itself.
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
=cut
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
|
|
Packit |
b48d6e |
# Local Variables:
|
|
Packit |
b48d6e |
# mode: cperl
|
|
Packit |
b48d6e |
# cperl-indent-level: 4
|
|
Packit |
b48d6e |
# End:
|