rajkrishna89 has asked for the wisdom of the Perl Monks concerning the following question:

the below perl script(by IVO1) will give the call tree of a c code...but its tracing only upto 2 functions ..help out guys..the snippet is

#!/usr/bin/perl -w use warnings; use strict; my ($tag, %list); while (<DATA>){ next unless /./; if (/^(\w+)/){ $tag = $1; next; } if (/^-- (\w+)/){ push @{$list{$tag}}, $1; } } for my $type (@{$list{main}}){ if ($list{$type}){ for (@{$list{$type}}){ print "main $type $_\n"; } } else { print "main $type\n"; } } __END__ main -- check -- check1 check -- computing -- net check1 -- computing2 -- net2 computing -- community The output should be main check computing community main check net main check1 computing2 main check1 net2 But the output is coming as below: main check computing1 main check net main check1 computing2 main check1 net2

Help out guys

If i use | in the snippet instead of -- , im getting an error , i used escape sequence stil its throwing errors..

Replies are listed 'Best First'.
Re: Tree Analysis
by GrandFather (Saint) on Feb 23, 2012 at 08:17 UTC

    As the only -- of note is in a regular expression and |is a magic character in regular expressions, if you replaced the -- with a | the regex becomes quite a different animal. You should read perlretut for an introduction to regular expressions.

    You may get more help from us if you show us the version of the code that generates errors and tell us what you consider the errors to be. Showing us a sample of the output you get and what you expected to see may help too.

    True laziness is hard work
Re: Tree Analysis
by Anonymous Monk on Feb 23, 2012 at 16:33 UTC

    You have a two nested for loops and so they can only print two levels. The easiest way is to use recursion. The following code has two solutions. get_all_chains will return an array of all of the call chains. print_all_chains will print the call chains as they are found.

    #!/usr/bin/perl -w use warnings; use strict; my ($tag, %list); while (<DATA>){ next unless /./; if (/^(\w+)/){ $tag = $1; next; } if (/^-- (\w+)/){ push @{$list{$tag}}, $1; } } print "get_call_chains\n"; print "---------------\n"; for my $call_chain ( get_call_chains("main") ){ print join(" ", @$call_chain),"\n"; } print "\n\n"; print "print_call_chains\n"; print "-----------------\n"; print_call_chains("main"); sub get_call_chains { my $root = shift; my @calls; if( exists $list{$root} ){ for (@{$list{$root}}){ push @calls, get_call_chains($_); } } else { @calls = ([]); } unshift @$_, $root for @calls; return @calls } sub print_call_chains { my @stack = @_; my $current = $stack[$#stack]; if(exists $list{$current}) { for (@{$list{$current}}){ print_call_chains(@stack, $_); } } else { print join(" ", @stack),"\n"; } } __END__ main -- check -- check1 check -- computing -- net check1 -- computing2 -- net2 computing -- community
    which results in
    get_call_chains --------------- main check computing community main check net main check1 computing2 main check1 net2 print_call_chains ----------------- main check computing community main check net main check1 computing2 main check1 net2

    get_call_chains can be optimized by storing the result on the first call for a given subroutine, and using the stored value if it is ever called again with the same subroutine.

    Note this version does not address the infinite loop if the analyzed code uses recursion.

Re: Tree Analysis
by Anonymous Monk on Feb 23, 2012 at 07:54 UTC

    If i use | in the snippet instead of -- , im getting an error , i used escape sequence stil its throwing errors..

    What snippet where?