Tassilo von Parseval > Devel-Calltree > calltree

Download:
Devel-Calltree-0.00_3.tar.gz

Annotate this POD

Source  

NAME ^

calltree - Who called whom

SYNOPSIS ^

    calltree    --exclude=<pkg1>...<pkgN> --include=<pkg3>...<pkgQ>
                --noempty
                [ --reportfunc file ]
                [ -Iinc/path1 -Iinc/path2 -I...] [ -Mmodule1 -Mmodule2 -M...]
                [ -e <CODE> | script.pl ]

    calltree    --chkfunc=<fnc1>...<funcN>
                [ -Iinc/path1 -Iinc/path2 -M...] [ -Mmodule1 -Mmodule2 -M...]
                [ -e <CODE> | script.pl ]

OPTIONS ^

DESCRIPTION ^

calltree inspects the OP-tree of a program or module after compilation is done and creates a report showing which method and function has been called by whom.

The default output is pretty straightforward. When not using the --chkfunc switch, it looks like this:

    Package::func  (/path/to/Package.pm)
      method   'some_method'                                      (68)
      function 'Pkg::function'                                    (70)
      
    Package::nest::otherfunc  (/path/to/Package/nest.pm)
      method   'foobar'                                           (10)
    
    ...

    __MAIN__ (-)
      function 'Package::func::func'                              (3)

It begins with the fully qualified function followed by the path to the file in which this function resides. After that a list of function and method calls follows. The line where this call happens is prepended.

The last in the list is always __MAIN__ which is the report for what happens in package main. This doesn't necessarily exist (e.g. when you only inspect a module).

In --chkfunc mode, output looks like this:

    calltree --chkfunc=foo,bar -e 'sub foo {1} print foo()'
    These patterns did not match any called function:
      bar

    These functions were called:
      function main::foo        from __MAIN__           at line 1

PROVIDING YOUR OWN REPORT FUNCTIONS ^

With the help of the --reportfunc switch, you can tell calltree to use a different function for outputting the report. The argument to this switch must be a file that contains the function Devel::Calltree::print_report. The file itself must additionally return a true value.

A skeleton of this file therefore must look like this:

    sub Devel::Calltree::print_report {
        ...
    }
    
    "MJD kindly reminded calltree's author of putting in this feature";

Devel::Calltree::print_report

This function will receive exactly one argument, namely a hash-reference which is additionally blessed in some fancy way. The keys of this hash are the various functions that calltree was able to find in your code. The value is an array-reference holding Devel::Calltree::Func objects where each object represents exactly one call to a function or method that was done from within the given function.

The hash-reference passed to Devel::Calltree::print_report overloads the @{} operator. That means that in order to iterate over all functions in your program, you can simply write:

    sub Devel::Calltree::print_report {
        my $calls = shift;
        for my $func (@$calls) {
            print $func, "\n";
            ...
        }
    }

This is often more convenient than writing

    for my $func (keys %$calls) {

because @$calls will return the list of functions sorted by package and then by function names.

Now that you are iterating over all exiting functions, you want to look at what is called from each function. To get the list of these method/function calls:

    for my $func (@$calls) {
        my @called = funcs($calls->{ $func });
        ...
    }

where now @called contains the list of Devel::Calltree::Func objects. The list returned by funcs() has the same order in which the function/method calls were done. That means they are sorted by line-number.

Additionally, there's a file() function that returns the filename where the current function resides in.

    for my $func (@$calls) {
        print "$func lives in ", file($calls->{ $func });
        ...
    }

Here's a list of methods you can use on each Devel::Calltree::Func object:

Here is an example how a complete report function should look like. This function is in fact producing the same output as the built-in report function:

    sub print_report {
        my $calls = shift;
        for my $caller (@$calls) {
            my $file = file($calls->{ $caller });
            if (funcs($calls->{$caller}) || !$OPT{-filter_empty} ) {
                print "\n$caller  ($file): \n";
                for my $targ (funcs($calls->{$caller})) {
                    my $n = $targ->name;
                    my $l = $targ->line;
                    if ($targ->is_method) {
                        print "  method   '$n'", ' ' x (60 - 14 - length($n)), " ($l)\n"; 
                        next;
                    }
                    print "  function '$n'", ' ' x (60 - 14 - length($n)), " ($l)\n";
                }
            }
        }
    }

%OPT holds the arguments which calltree passed on to the underlying module:

EXAMPLES ^

See the calltree of a script:

    calltree script.pl

Or one of a script given on the command-line:

    calltree -e '...'

See the calltree of the module URI:

    calltree -MURI

The same, but skip empty functions (those that do not make calls to others):

    calltree --noempty -MURI

The same, but ignore functions not in the URI:: namespace:

    calltree --noempty --exclude=. --include=URI:: -MURI

Thus, use --exclude=. to exclude everything and then include only functions from the URI:: namespace with --include=URI::.

And finally check whether a particular function is called at all:

    calltree --chkfunc=Carp::croak -MURI

ENVIRONMENT VARIABLES ^

calltree uses PERLLIB and PERL5LIB in a similar fashion as perl does.

TODO ^

AUTHOR ^

Original idea and code by Mark Jason Dominus <mjd@plover.com>.

Current maintainer Tassilo von Parseval <tassilo.parseval@post.rwth-aachen.de>.

COPYRIGHT AND LICENSE ^

Original code copyright (C) 2003 by Mark Jason Dominus

Revisions copyright (C) 2004 by Tassilo von Parseval

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

syntax highlighting: