An OO style solution: (It prints out all the bad calling chains it found, for each function.)
package func;
use strict;
sub new {
my $self = {};
shift;
$self->{CALLED} = [];
$self->{MARK} = 0;
$self->{NAME} = shift;
bless $self;
return $self;
}
sub call {
my ($self, $called) = @_;
push @{$self->{CALLED}}, $called;
}
sub mark {
my $result = 0;
my ($self, $mark, $current_chain) = @_;
if ($self->{MARK} != $mark) {
$self->{MARK} = $mark;
my $called;
foreach $called (@{$self->{CALLED}}) {
push @{$current_chain}, $called->{NAME};
$result |= $called->mark($mark, $current_chain);
}
} else {
$result = 1;
print(join("->", @{$current_chain})."\n");
}
pop @{$current_chain};
$self->{MARK} = 0;
return $result;
}
1;
func.pl:
use func;
use Data::Dumper;
use strict;
my %funcs;
while (<DATA>) {
chomp;
my ($calling, $called) = split(' ');
if (!exists($funcs{$calling})) {
$funcs{$calling} = new func($calling);
}
if (!exists($funcs{$called})) {
$funcs{$called} = new func($called);
}
$funcs{$calling}->call($funcs{$called});
}
my $mark = 0;
my $func;
print "Bad calling chains:\n";
foreach $func (keys %funcs) {
$mark ++;
my $current_chain = [];
push @{$current_chain}, $func;
$funcs{$func}->mark($mark, $current_chain);
}
print "End of bad calling chains\n";
__DATA__
aaa bbb
aaa ccc
bbb ccc
ccc bbb
ddd aaa
ddd eee
testing result
Bad calling chains:
bbb->ccc->bbb
aaa->bbb->ccc->bbb
aaa->ccc->bbb->ccc
ccc->bbb->ccc
ddd->aaa->bbb->ccc->bbb
ddd->aaa->ccc->bbb->ccc
End of bad calling chains
|