Mailing List Archive

sample of tracking down code refs in symtables
package pref;
use Carp;
require Exporter;
@ISA = ('Exporter');
@EXPORT = ('pref');

#use strict;

#%didpack;
#$indent;
#%known_func;

$didpack{'main::main::'} = 1;
find_funcs('main::');

sub usage {
carp "@_" if @_;
croak "usage: pref some-reference";
};

sub pref {
my $r = $_[0];
usage("wrong argcount") unless @_ == 1;
my $type = ref $r;
#usage("arg not a reference") unless defined $type && $type;
if (!defined $type) {
print_scalar($r);
return;
}


for ($type) {
/SCALAR/ && do {
print_scalar($$r);
last;
};
/ARRAY/ && do {
my $max = @$r - 1;
my $i;
print "[.\n";
for $i ( 0 .. $max ) {
pindent();
printf " %5d => ", $i;
$indent++;
pref($r->[$i]);
$indent--;
print "\n";
}
pindent();
print "],";
last;

};
/HASH/ && do {
print "{\n";
my $k;
for $k ( keys %$r ) {
pindent();
printf " %-8s => ", sprint_scalar($k);
$indent++;
pref($r->{$k});
$indent--;
print "\n";
}
pindent();
print "},";
last;

last;
};
/CODE/ && do {
my $name = $known_func{$r};
$name =~ s/^main:://;
print $name ? "&$name()" : "$r";
#print "$r";
last;
};
/GLOB/ && do {
print "(REF TO ) \\$$r";
last;
};
/REF/ && do {
print "(REF TO ) \\";
pref($$r);
last;
};

print "UNKOWN REFERENCE: $r";
}
}

sub pindent {
print " " x (10 * $indent);
}

sub print_scalar {
print &sprint_scalar;
}


sub sprint_scalar {
my $s = $_[0];
if (!defined $s) {
return "undef";
} elsif ($s != 0) {
return $s;
} elsif ($s =~ /^\*\w+/) {
return qq($s);
} else{
return qq("$s");
}
}

sub find_funcs {
my $stabname = $_[0];
#print "starting on $stabname\n";
return if $didpack{$stabname}++;
no strict;
local *stab = *$stabname;
my $ident;
for $ident (keys %stab) {
if (defined &{$stab{$ident}}) {
my $addr = \&{$stab{$ident}};
my $funcname = "$stabname$ident";
$known_func{$addr} = $funcname;
#print "func $funcname is at $addr\n";
} elsif ($ident =~ /::$/ && defined %{$stab{$ident}} ) {
#print "$ident $stab{$ident}\n";
my $newpack = $stabname . $ident;
#print "recursing on $newpack";
find_funcs($newpack);
}
}
}

sub wild::func { }

1;
Re: sample of tracking down code refs in symtables [ In reply to ]
On Fri, 24 Nov 1995 01:05:43 MST, Tom Christiansen wrote:
>
>sub find_funcs {
> my $stabname = $_[0];
> #print "starting on $stabname\n";
> return if $didpack{$stabname}++;
> no strict;
> local *stab = *$stabname;
> my $ident;
> for $ident (keys %stab) {
> if (defined &{$stab{$ident}}) {
> my $addr = \&{$stab{$ident}};
> my $funcname = "$stabname$ident";
> $known_func{$addr} = $funcname;
> #print "func $funcname is at $addr\n";
> } elsif ($ident =~ /::$/ && defined %{$stab{$ident}} ) {
> #print "$ident $stab{$ident}\n";
> my $newpack = $stabname . $ident;
> #print "recursing on $newpack";
> find_funcs($newpack);
> }
> }
>}
>

That looks very expensive without caching. A "snapshot" approach
with a Devel::Symdump object should work well.

- Sarathy.
gsar@engin.umich.edu
Re: sample of tracking down code refs in symtables [ In reply to ]
>That looks very expensive without caching. A "snapshot" approach
>with a Devel::Symdump object should work well.

Certainly. And it doesn't work for anything with outer-scoped
lexicals.

--tom