[23825] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 6028 Volume: 10

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Thu Jan 29 21:16:16 2004

Date: Thu, 29 Jan 2004 18:10:42 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Thu, 29 Jan 2004     Volume: 10 Number: 6028

Today's topics:
        Call Tree utility (Mark Jason Dominus)
    Re: Call Tree utility <tassilo.parseval@rwth-aachen.de>
    Re: Call Tree utility <tassilo.parseval@rwth-aachen.de>
    Re: Call Tree utility (Mark Jason Dominus)
    Re: Call Tree utility <tassilo.parseval@rwth-aachen.de>
    Re: Call Tree utility <MJD@plover.com>
    Re: Call Tree utility (Mark Jason Dominus)
    Re: Call Tree utility <tassilo.parseval@rwth-aachen.de>
    Re: Call Tree utility <uri@stemsystems.com>
    Re: Call Tree utility <usenet@morrow.me.uk>
    Re: Call Tree utility <tassilo.parseval@rwth-aachen.de>
    Re: Call Tree utility <rgarciasuarez@free.fr>
    Re: Call Tree utility (Mark Jason Dominus)
    Re: Call Tree utility <usenet@morrow.me.uk>
    Re: Call Tree utility <tassilo.parseval@rwth-aachen.de>
    Re: Call Tree utility (Mark Jason Dominus)
    Re: Call Tree utility <tassilo.parseval@rwth-aachen.de>
    Re: Call Tree utility <abigail@abigail.nl>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Sat, 24 Jan 2004 18:03:17 +0000 (UTC)
From: mjd@plover.com (Mark Jason Dominus)
Subject: Call Tree utility
Message-Id: <buuc15$o3f$1@plover.com>


I wanted a utility which would examine a Perl program and produce a
report about which functions called which other functions (or which
functions were called by which other functions) but I couldn't find
one that someone else had written, so I wrote one.

Note that what I want is a utility which reports on the *static* call
tree, reporting on which functions *might* call others.  It's very
easy to write a module which actually runs the program and reports on
which functions *have* called which others, for that particular run.
This is different.  Given

        sub func_main {
          if (some very rare condition that hardly ever occurs) {
            func_rare();
          } else { 
            func_common();
          }
        }

I would like the report to mention that func_main calls both func_rare
and func_common, without having to actually produce a run of the
program in which func_rare is called.  The utility I wrote does do
this.  It never actually runs the program at all.

The basic features are pretty much working, but the utility needs a
lot of work.  For example, when package 'Fred' has

        package Fred;
        use Carp;

        sub foo {
          croak "Oh no!\n";
        }

the call tree reporter says that Fred::foo will call Fred::croak.
This is technically correct, but it would be better if it said that
Fred::foo will call Carp::croak.  This would not be hard to do, but I
don't have time to fix it.

Similarly, it doesn't handle method calls.  This would not be hard to
do, but I don't have time to fix it.

I'm posting here in hope that (a) someone wil find it useful even in
its current state, and (b) someone wil adopt it.

The software and the explanation of how to use it are both available
at

        http://perl.plover.com/Calltree/

Share and enjoy.




------------------------------

Date: 24 Jan 2004 23:31:42 GMT
From: "Tassilo v. Parseval" <tassilo.parseval@rwth-aachen.de>
Subject: Re: Call Tree utility
Message-Id: <buuv8u$np4$1@nets3.rz.RWTH-Aachen.DE>

Also sprach Mark Jason Dominus:

> I wanted a utility which would examine a Perl program and produce a
> report about which functions called which other functions (or which
> functions were called by which other functions) but I couldn't find
> one that someone else had written, so I wrote one.
> 
> Note that what I want is a utility which reports on the *static* call
> tree, reporting on which functions *might* call others.  It's very
> easy to write a module which actually runs the program and reports on
> which functions *have* called which others, for that particular run.
> This is different.  Given

Cool! This is much more useful than the current solutions (such as
Devel::Cover) since those will only report on the branches that were
executed and therefore can't really help finding dead code that really
never gets executed.

>         sub func_main {
>           if (some very rare condition that hardly ever occurs) {
>             func_rare();
>           } else { 
>             func_common();
>           }
>         }
> 
> I would like the report to mention that func_main calls both func_rare
> and func_common, without having to actually produce a run of the
> program in which func_rare is called.  The utility I wrote does do
> this.  It never actually runs the program at all.

One thing worthy mention is that in the case of

    sub foo { 1 }
    foo() if 0;

Calltree.pm will not list 'foo' as in the inspected optree the call to
'foo' has been optimized away. I would consider this a feature, though.

> The basic features are pretty much working, but the utility needs a
> lot of work.  For example, when package 'Fred' has
> 
>         package Fred;
>         use Carp;
> 
>         sub foo {
>           croak "Oh no!\n";
>         }
> 
> the call tree reporter says that Fred::foo will call Fred::croak.
> This is technically correct, but it would be better if it said that
> Fred::foo will call Carp::croak.  This would not be hard to do, but I
> don't have time to fix it.
> 
> Similarly, it doesn't handle method calls.  This would not be hard to
> do, but I don't have time to fix it.

You could for the moment use something like that for the find_subcall()
callback to handle named methods:

    # package names are in OPs preceeding 'method_named'
    my $pkgbuf;

    sub find_subcall {
      my ($op, $dest) = @_;
      if ($op->name eq 'const') {
          if ($op->gv->isa("B::PV")) {
            $pkgbuf = $op->gv->PV;
          }
      }
      if ($op->name eq 'gvsv') {
          $pkgbuf = $op->gv->STASH->NAME;
      }
      if ($op->name eq 'gv' && $op->next && $op->next->name eq 'entersub') {
        my $cur_gv = $op->gv;
        push @$dest, join '::', $cur_gv->STASH->NAME, $cur_gv->NAME; 
      }
      if ($op->name eq 'method_named' && $op->next && $op->next->name eq 'entersub') {
          my $cur_gv = $op->gv;
          push @$dest, join '::', $pkgbuf, $cur_gv->PV . " (meth)";
      }
    }

This would result in 

ethan@ethan:~$ perl -MCalltree -e 'sub foo {1}; my $s = bless{}=>__PACKAGE__; $s->foo()'

__MAIN__:
  main::foo (meth)

main::foo:

and also works for class-methods (but in some cases the package-portion
is empty so there are obviously still one or two cases missing).

> Share and enjoy.

Thank you for sharing it. I think this is really fun.

Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval


------------------------------

Date: 25 Jan 2004 09:25:35 GMT
From: "Tassilo v. Parseval" <tassilo.parseval@rwth-aachen.de>
Subject: Re: Call Tree utility
Message-Id: <bv022f$8lk$1@nets3.rz.RWTH-Aachen.DE>

Also sprach Mark Jason Dominus:

> I wanted a utility which would examine a Perl program and produce a
> report about which functions called which other functions (or which
> functions were called by which other functions) but I couldn't find
> one that someone else had written, so I wrote one.
> 
> Note that what I want is a utility which reports on the *static* call
> tree, reporting on which functions *might* call others.  It's very
> easy to write a module which actually runs the program and reports on
> which functions *have* called which others, for that particular run.
> This is different.  Given
> 
>         sub func_main {
>           if (some very rare condition that hardly ever occurs) {
>             func_rare();
>           } else { 
>             func_common();
>           }
>         }
> 
> I would like the report to mention that func_main calls both func_rare
> and func_common, without having to actually produce a run of the
> program in which func_rare is called.  The utility I wrote does do
> this.  It never actually runs the program at all.
> 
> The basic features are pretty much working, but the utility needs a
> lot of work.  For example, when package 'Fred' has
> 
>         package Fred;
>         use Carp;
> 
>         sub foo {
>           croak "Oh no!\n";
>         }
> 
> the call tree reporter says that Fred::foo will call Fred::croak.
> This is technically correct, but it would be better if it said that
> Fred::foo will call Carp::croak.  This would not be hard to do, but I
> don't have time to fix it.

Hmmh, I just tried to add that for fun. What would the correct approach
to that be? After use()ing Carp main::croak() becomes an alias to
Carp::carp(). So far, so good.

Now I thought I just have to look at all the available namespaces and
see whether they have a function called croak() and compare the address
of it with main::croak:

    sub find_realpkg {
        my ($pkg, $func) = @_;    
        my @stashes = keys %{ $OPT->{INCLUDE_PACKAGES} } || walk_stashes();
        for (@stashes) {
            $_ ||= "main";
            next if $_ eq $pkg;
            no strict 'refs';
            my $src  = *{"${pkg}::$func"};
            my $dest = *{"${_}::$func"};
            return $_ if *$src{CODE} == *$dest{CODE};
        }
        return $pkg;
    }

This is not good enough (besides, it's painfully slow) because for
croak(), this resulted in "warnings::croak" so warnings obviously
imported croak() as well.

So I added a check to see whether the function is in @EXPORT or
@EXPORT_OK of the package. That would not detect manual aliases such as

    *main::croak = \&Carp::croak;

Since you say it's not hard, you must have been thinking of an easier
way. Which one?

Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval


------------------------------

Date: Sun, 25 Jan 2004 12:16:21 +0000 (UTC)
From: mjd@plover.com (Mark Jason Dominus)
Subject: Re: Call Tree utility
Message-Id: <bv0c2l$5mk$1@plover.com>

In article <bv022f$8lk$1@nets3.rz.RWTH-Aachen.DE>,
Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote:
>Also sprach Mark Jason Dominus:

It seems to me that if you're going to say "Also sprach" you should
say "Also sprach Dominus", or perhaps "Also sprach DOMINUS", and leave
it at that.

>> the call tree reporter says that Fred::foo will call Fred::croak.
>> This is technically correct, but it would be better if it said that
>> Fred::foo will call Carp::croak.  This would not be hard to do, but I
>> don't have time to fix it.
>
>Hmmh, I just tried to add that for fun. What would the correct approach
>to that be? After use()ing Carp main::croak() becomes an alias to
>Carp::carp(). So far, so good.
>
>Now I thought I just have to look at all the available namespaces and
>see whether they have a function called croak() and compare the address
>of it with main::croak:
>
>    sub find_realpkg {
>        my ($pkg, $func) = @_;    
>        my @stashes = keys %{ $OPT->{INCLUDE_PACKAGES} } || walk_stashes();
>        for (@stashes) {
>            $_ ||= "main";
>            next if $_ eq $pkg;
>            no strict 'refs';
>            my $src  = *{"${pkg}::$func"};
>            my $dest = *{"${_}::$func"};
>            return $_ if *$src{CODE} == *$dest{CODE};
>        }
>        return $pkg;
>    }
>
>This is not good enough (besides, it's painfully slow) 

Perhaps that's because you're doing it once for every function.  But
you should be doing it once total.  

I imagined that I would would have the program walk over the stash
tree, accumulating a hash whose keys were function addresses and whose
values were names for the functions.  That only requires a couple of
extra lines in 'walk_stashes', which we were going to call anyway:

        # I DID NOT TEST THIS
        sub walk_stashes {
          my $top = shift || '';
          return if $top eq '::main';
        #  print "* $top\n";
          my @packages = $top;
          while (my $name = each %{"$top\::"}) {
            if ($name =~ s/::$//) {
              push @packages, walk_stashes("$top\::$name");
            # NEW CODE STARS HERE
            } elsif (defined &{"$top\::$name"}) {
              push @{$ALIASES{\&{"$top\::$name"}}}, "$top\::$name";
            # NEW CODE ENDS HERE
            }
          }
        #  print "=> @packages\n";
          map /^(?:::)?(.*)/, @packages;
        }

Now for each function f, you can find a list of the names of f by
examining $ALIASES{\&f}, which is a reference to an array of aliases.

Then you can deduce the canonical name for each function by examining
the appropriate @EXPORT/@EXPORT_OK arrays; if you have main::croak,
Carp::croak, and warnings::croak, you look at @main::EXPORT,
@Carp::EXPORT, and @warnings::EXPORT, observe that 'croak' is only
listed in @Carp::EXPORT, and conlcude that that's the canonical
version, something like this:

        # I DID NOT TEST THIS EITHER
        sub find_canonical_names {
          for my $alias_list (values %aliases) {
            my $canonical;
            for my $alias (@$alias_list) {
              my ($pkg, $func) = $alias =~ /(.*)::(.*)/;
              # The 
              use strict "police"->can('kiss') . my @ss;
              my @exports = (@{"$pkg\::EXPORT"}, @{"$pkg\::EXPORT_OK"});
              for my $export (@exports) {
                if ($export eq $func) {
                  if (defined $canonical) {
                    warn "Packages $canonical and $pkg both export function '$func'!\n";
                  } else {
                    $canonical = $pkg;
                  }
                }
              }
              $CANONICAL_PACKAGE{$alias} = $canonical;
            }
          }
        }       

>That would not detect manual aliases such as
>
>    *main::croak = \&Carp::croak;

True.  It will also fail in the presence of modules like DB_File that
import functions from one place and then export them again elsewhere.
For example, if I have

        package Mine;
        use DB_File;
        sub foo { print O_RDONLY }

the method above will not be able to decide whether O_RDONLY was
originally in Fcntl, and was exported into DB_File, or vice versa; it
might report that Mine::foo is calling DB_File::O_RDONLY or
Fcntl::O_RDONLY.  And while it seems to me that you could make a
persuasive case for the program's behavior if it were to consistently
choose one or the other, the behavior it would actually have, which
would be to select one unpredictably, is indefensible.

>Since you say it's not hard, you must have been thinking of an easier
>way. Which one?

Hey, I only said it would not be hard to do.  I didn't say it would
not be hard to do correctly.



------------------------------

Date: 25 Jan 2004 14:24:00 GMT
From: "Tassilo v. Parseval" <tassilo.parseval@rwth-aachen.de>
Subject: Re: Call Tree utility
Message-Id: <bv0ji0$2d8$1@nets3.rz.RWTH-Aachen.DE>

Also sprach Mark Jason Dominus:

> In article <bv022f$8lk$1@nets3.rz.RWTH-Aachen.DE>,
> Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote:
>>Also sprach Mark Jason Dominus:
> 
> It seems to me that if you're going to say "Also sprach" you should
> say "Also sprach Dominus", or perhaps "Also sprach DOMINUS", and leave
> it at that.

That would make the reference to good ol' Nietzsche clearer, but it
would blur a little the fact who has written the post I am replying to.
There are also some obnoxious people here (me:-) whose last name
consists of two words, either abbreviated or not. Maybe my newsclient
has some smart heuristics to do that properly.

>>Now I thought I just have to look at all the available namespaces and
>>see whether they have a function called croak() and compare the address
>>of it with main::croak:
>>
>>    sub find_realpkg {
>>        my ($pkg, $func) = @_;    
>>        my @stashes = keys %{ $OPT->{INCLUDE_PACKAGES} } || walk_stashes();
>>        for (@stashes) {
>>            $_ ||= "main";
>>            next if $_ eq $pkg;
>>            no strict 'refs';
>>            my $src  = *{"${pkg}::$func"};
>>            my $dest = *{"${_}::$func"};
>>            return $_ if *$src{CODE} == *$dest{CODE};
>>        }
>>        return $pkg;
>>    }
>>
>>This is not good enough (besides, it's painfully slow) 
> 
> Perhaps that's because you're doing it once for every function.  But
> you should be doing it once total.  
> 
> I imagined that I would would have the program walk over the stash
> tree, accumulating a hash whose keys were function addresses and whose
> values were names for the functions.  That only requires a couple of
> extra lines in 'walk_stashes', which we were going to call anyway:

[...]

> Now for each function f, you can find a list of the names of f by
> examining $ALIASES{\&f}, which is a reference to an array of aliases.
> 
> Then you can deduce the canonical name for each function by examining
> the appropriate @EXPORT/@EXPORT_OK arrays; if you have main::croak,
> Carp::croak, and warnings::croak, you look at @main::EXPORT,
> @Carp::EXPORT, and @warnings::EXPORT, observe that 'croak' is only
> listed in @Carp::EXPORT, and conlcude that that's the canonical
> version, something like this:

[...]

Ah, ok. This is the same approach I was thinking of, only done properly
without unnecessary duplicate calculations. 

>>That would not detect manual aliases such as
>>
>>    *main::croak = \&Carp::croak;
> 
> True.  It will also fail in the presence of modules like DB_File that
> import functions from one place and then export them again elsewhere.
> For example, if I have
> 
>         package Mine;
>         use DB_File;
>         sub foo { print O_RDONLY }
> 
> the method above will not be able to decide whether O_RDONLY was
> originally in Fcntl, and was exported into DB_File, or vice versa; it
> might report that Mine::foo is calling DB_File::O_RDONLY or
> Fcntl::O_RDONLY.  And while it seems to me that you could make a
> persuasive case for the program's behavior if it were to consistently
> choose one or the other, the behavior it would actually have, which
> would be to select one unpredictably, is indefensible.
> 
>>Since you say it's not hard, you must have been thinking of an easier
>>way. Which one?
> 
> Hey, I only said it would not be hard to do.  I didn't say it would
> not be hard to do correctly.

With this last question I was suggesting that there might be an
altogether different way that would not involve looking into the
stashes. The original function must still be somewhere in the OP-tree.
I figure that this would be more reliable than the stash/@EXPORT(_OK)?
approach. all_roots() unfortunately returns the aliased functions, too.

But never mind. The module in your preliminary version is a very useful
base that should be extensible enough.

Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval


------------------------------

Date: Sun, 25 Jan 2004 17:03:14 +0000 (UTC)
From: DOMINUS <MJD@plover.com>
Subject: Re: Call Tree utility
Message-Id: <bv0ssi$fog$1@plover.com>

In article <bv0ji0$2d8$1@nets3.rz.RWTH-Aachen.DE>,
Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote:
>Also sprach Mark Jason Dominus:
>> 
>> It seems to me that if you're going to say "Also sprach" you should
>> say "Also sprach Dominus", or perhaps "Also sprach DOMINUS", and leave
>> it at that.
>
>There are also some obnoxious people here (me:-) whose last name
>consists of two words, either abbreviated or not. 

I wasn't suggesting that you do it for everyone, just for me.
Not everyone has a name that works so well in all caps.

For example, compare

        Tremble, puny mortal, before the wrath of DOMINUS!

and

        Tremble, puny mortal, before the wrath of GUTTMAN!

See?  








------------------------------

Date: Sun, 25 Jan 2004 17:11:45 +0000 (UTC)
From: mjd@plover.com (Mark Jason Dominus)
Subject: Re: Call Tree utility
Message-Id: <bv0tch$g9s$1@plover.com>

In article <bv0ji0$2d8$1@nets3.rz.RWTH-Aachen.DE>,
Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote:
>The original function must still be somewhere in the OP-tree.
>I figure that this would be more reliable than the stash/@EXPORT(_OK)?
>approach. all_roots() unfortunately returns the aliased functions, too.

That's a good point.  It makes me wonder how all_roots works.  It
seems to me that a purely optree based all_roots should find only the
canonical version.

But here's something else you could do.  Each 'nextstate' op has a
field that tells it what package the new statement was compiled into
by default.  So you look at the first 'nextstate' op in the function's
tree, and use that.

It fails in cases like this:

        package A;
        sub foo {
          package B;
          ...
        }

because it will think this is B::foo, not A::foo.  But with the other
techniques also, maybe the program has enough information to get
nearly all the cases right nearly all the time.  I think the technique
described previously probably works about 99% of the time; when
correlated with this technique, it probably works about 99.99% of the
time.

On the other hand, maybe using this technique also would be like
wearing two watches.



>But never mind. The module in your preliminary version is a very useful
>base that should be extensible enough.

Oh, that reminds me that the really major flaw I see is that the
'report' function is not sufficiently pluggable.  Although I vaguely
recall a

        CALLBACK => \&my_report

option, so maybe it's pluggable enough.  Also it seems to me it should
generate both the forward and backward hashes and pass them both to
the callback.






------------------------------

Date: 25 Jan 2004 17:18:26 GMT
From: "Tassilo v. Parseval" <tassilo.parseval@rwth-aachen.de>
Subject: Re: Call Tree utility
Message-Id: <bv0tp2$cfp$1@nets3.rz.RWTH-Aachen.DE>

Also sprach DOMINUS:

> In article <bv0ji0$2d8$1@nets3.rz.RWTH-Aachen.DE>,
> Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote:
>>Also sprach Mark Jason Dominus:
>>> 
>>> It seems to me that if you're going to say "Also sprach" you should
>>> say "Also sprach Dominus", or perhaps "Also sprach DOMINUS", and leave
>>> it at that.
>>
>>There are also some obnoxious people here (me:-) whose last name
>>consists of two words, either abbreviated or not. 
> 
> I wasn't suggesting that you do it for everyone, just for me.
> Not everyone has a name that works so well in all caps.
> 
> For example, compare
> 
>         Tremble, puny mortal, before the wrath of DOMINUS!
> 
> and
> 
>         Tremble, puny mortal, before the wrath of GUTTMAN!
> 
> See?  

Haha, LOL. You don't seem to be very busy in these days if you find the
time to worry about this (although point taken: uri in all-caps is just
plain wrong).

Looks as though you have found a good solution by setting the
appropriate From-header. I am waiting for the joker who sets it to
Zarathustra...

Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval


------------------------------

Date: Sun, 25 Jan 2004 17:53:47 GMT
From: Uri Guttman <uri@stemsystems.com>
Subject: Re: Call Tree utility
Message-Id: <x7fze3x6c4.fsf@mail.sysarch.com>

>>>>> "D" == DOMINUS  <MJD@plover.com> writes:

  D> I wasn't suggesting that you do it for everyone, just for me.
  D> Not everyone has a name that works so well in all caps.

  D> For example, compare

  D>         Tremble, puny mortal, before the wrath of DOMINUS!

  D> and

  D>         Tremble, puny mortal, before the wrath of GUTTMAN!

and the other difference is that DOMINUS' wrath is more academic while
mine is more visceral. :)

uri

-- 
Uri Guttman  ------  uri@stemsystems.com  -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs  ----------------------------  http://jobs.perl.org


------------------------------

Date: Sun, 25 Jan 2004 18:09:38 +0000 (UTC)
From: Ben Morrow <usenet@morrow.me.uk>
Subject: Re: Call Tree utility
Message-Id: <bv10p2$cod$1@wisteria.csv.warwick.ac.uk>


tassilo.parseval@post.rwth-aachen.de wrote:
> > the call tree reporter says that Fred::foo will call Fred::croak.
> > This is technically correct, but it would be better if it said that
> > Fred::foo will call Carp::croak.  This would not be hard to do, but I
> > don't have time to fix it.
> 
> Hmmh, I just tried to add that for fun. What would the correct approach
> to that be? After use()ing Carp main::croak() becomes an alias to
> Carp::carp(). So far, so good.
> 
<snip>
> This is not good enough (besides, it's painfully slow) because for
> croak(), this resulted in "warnings::croak" so warnings obviously
> imported croak() as well.
> 
<snip>
> Since you say it's not hard, you must have been thinking of an easier
> way. Which one?

How about (Inline::C used just for simplicity):

#!/usr/bin/perl -l

use Inline C => <<'EOC';

char* find_realpkg(CV* cv)
{
    return HvNAME(GvSTASH(CvGV(cv)));
}

EOC

use Carp;

BEGIN {
    package My::Carp;
    use Carp;
    *confess = \&Carp::confess;
}

*confess = \&My::Carp::confess;

print find_realpkg \&carp;
print find_realpkg \&confess;

__END__

?

Ben

-- 
For the last month, a large number of PSNs in the Arpa[Inter-]net have been
reporting symptoms of congestion ... These reports have been accompanied by an
increasing number of user complaints ... As of June,... the Arpanet contained
47 nodes and 63 links. [ftp://rtfm.mit.edu/pub/arpaprob.txt] * ben@morrow.me.uk


------------------------------

Date: 25 Jan 2004 20:43:18 GMT
From: "Tassilo v. Parseval" <tassilo.parseval@rwth-aachen.de>
Subject: Re: Call Tree utility
Message-Id: <bv19p6$pqe$1@nets3.rz.RWTH-Aachen.DE>

Also sprach Ben Morrow:

> tassilo.parseval@post.rwth-aachen.de wrote:
>> > the call tree reporter says that Fred::foo will call Fred::croak.
>> > This is technically correct, but it would be better if it said that
>> > Fred::foo will call Carp::croak.  This would not be hard to do, but I
>> > don't have time to fix it.
>> 
>> Hmmh, I just tried to add that for fun. What would the correct approach
>> to that be? After use()ing Carp main::croak() becomes an alias to
>> Carp::carp(). So far, so good.
>> 
><snip>
>> This is not good enough (besides, it's painfully slow) because for
>> croak(), this resulted in "warnings::croak" so warnings obviously
>> imported croak() as well.
>> 
><snip>
>> Since you say it's not hard, you must have been thinking of an easier
>> way. Which one?
> 
> How about (Inline::C used just for simplicity):
> 
> #!/usr/bin/perl -l
> 
> use Inline C => <<'EOC';
> 
> char* find_realpkg(CV* cv)
> {
>     return HvNAME(GvSTASH(CvGV(cv)));
> }
> 
> EOC
> 
> use Carp;
> 
> BEGIN {
>     package My::Carp;
>     use Carp;
>     *confess = \&Carp::confess;
> }
> 
> *confess = \&My::Carp::confess;
> 
> print find_realpkg \&carp;
> print find_realpkg \&confess;

Yup, cool, this works. Inline::C adds a few screens full of new
functions to the Calltree, so eventually this will be done with XS. 

This solves all problems. It's much simpler and of course much faster as
well.

Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval


------------------------------

Date: 25 Jan 2004 20:44:55 GMT
From: Rafael Garcia-Suarez <rgarciasuarez@free.fr>
Subject: Re: Call Tree utility
Message-Id: <slrnc18aoe.apa.rgarciasuarez@dat.local>

Ben Morrow wrote in comp.lang.perl.misc :
> 
> How about (Inline::C used just for simplicity):
> 
> #!/usr/bin/perl -l
> 
> use Inline C => <<'EOC';
> 
> char* find_realpkg(CV* cv)
> {
>     return HvNAME(GvSTASH(CvGV(cv)));
> }
> 
> EOC

or maybe :

$ perl -MB -MCarp -le 'print B::svref_2object(\&croak)->STASH->NAME'
Carp



------------------------------

Date: Mon, 26 Jan 2004 02:32:09 +0000 (UTC)
From: mjd@plover.com (Mark Jason Dominus)
Subject: Re: Call Tree utility
Message-Id: <bv1u79$65p$1@plover.com>

In article <bv19p6$pqe$1@nets3.rz.RWTH-Aachen.DE>,
Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote:
>Yup, cool, this works. Inline::C adds a few screens full of new
>functions to the Calltree,

That's what the EXCLUDE_PACKAGES option is for. By default, it
excludes functions in package 'Calltree'.  If you're going to use
Inline::C, you should add those packages to the default too.

But I think a better solution might be to merge this functionality
into B::Utils.



------------------------------

Date: Mon, 26 Jan 2004 04:49:18 +0000 (UTC)
From: Ben Morrow <usenet@morrow.me.uk>
Subject: Re: Call Tree utility
Message-Id: <bv268e$7h9$1@wisteria.csv.warwick.ac.uk>


mjd@plover.com (Mark Jason Dominus) wrote:
> In article <bv19p6$pqe$1@nets3.rz.RWTH-Aachen.DE>,
> Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote:
> >Yup, cool, this works. Inline::C adds a few screens full of new
> >functions to the Calltree,
> 
> That's what the EXCLUDE_PACKAGES option is for. By default, it
> excludes functions in package 'Calltree'.  If you're going to use
> Inline::C, you should add those packages to the default too.
> 
> But I think a better solution might be to merge this functionality
> into B::Utils.

As Rafael Garcia-Suarez pointed out, it is perfectly straightforward
to do this with B as it is.

Ben

-- 
   Razors pain you / Rivers are damp
   Acids stain you / And drugs cause cramp.                    [Dorothy Parker]
Guns aren't lawful / Nooses give
  Gas smells awful / You might as well live.                   ben@morrow.me.uk


------------------------------

Date: 26 Jan 2004 08:58:09 GMT
From: "Tassilo v. Parseval" <tassilo.parseval@rwth-aachen.de>
Subject: Re: Call Tree utility
Message-Id: <bv2kr1$cdj$1@nets3.rz.RWTH-Aachen.DE>

Also sprach Mark Jason Dominus:

> In article <bv19p6$pqe$1@nets3.rz.RWTH-Aachen.DE>,
> Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote:
>>Yup, cool, this works. Inline::C adds a few screens full of new
>>functions to the Calltree,
> 
> That's what the EXCLUDE_PACKAGES option is for. By default, it
> excludes functions in package 'Calltree'.  If you're going to use
> Inline::C, you should add those packages to the default too.

This is not so good, I think. That way Calltree.pm couldn't be used to
inspect Inline::C itself. Unlikely that Ingy would want to do that
though, but nonetheless. But since I always prefer XS over Inline::C
this is not a serious issue.

> But I think a better solution might be to merge this functionality
> into B::Utils.

Rafael showed how B::svref_2object can be used for it so it's already
there. I'll now see whether I can turn into a usable CPAN module (maybe
Devel::Calltree or so).

Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval


------------------------------

Date: Mon, 26 Jan 2004 16:00:33 +0000 (UTC)
From: mjd@plover.com (Mark Jason Dominus)
Subject: Re: Call Tree utility
Message-Id: <bv3dj1$fi1$1@plover.com>

In article <bv2kr1$cdj$1@nets3.rz.RWTH-Aachen.DE>,
Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote:
>> That's what the EXCLUDE_PACKAGES option is for. By default, it
>> excludes functions in package 'Calltree'.  If you're going to use
>> Inline::C, you should add those packages to the default too.
>
>This is not so good, I think. That way Calltree.pm couldn't be used to
>inspect Inline::C itself.

The user of Calltree can override the default value.  

>Rafael showed how B::svref_2object can be used for it

Rafael is right as usual.



------------------------------

Date: 26 Jan 2004 23:30:56 GMT
From: "Tassilo v. Parseval" <tassilo.parseval@rwth-aachen.de>
Subject: Re: Call Tree utility
Message-Id: <bv47vg$i94$1@nets3.rz.RWTH-Aachen.DE>

Also sprach Mark Jason Dominus:

> I wanted a utility which would examine a Perl program and produce a
> report about which functions called which other functions (or which
> functions were called by which other functions) but I couldn't find
> one that someone else had written, so I wrote one.
> 
> Note that what I want is a utility which reports on the *static* call
> tree, reporting on which functions *might* call others.  It's very
> easy to write a module which actually runs the program and reports on
> which functions *have* called which others, for that particular run.
> This is different.  Given

[...]

> Similarly, it doesn't handle method calls.  This would not be hard to
> do, but I don't have time to fix it.

I have thought about this a little more and after some experiments I
come to the conclusion that methods cannot be handled. This should
become obvious from the fact that in Perl method-dispatch happens at
runtime. In

    my $var;
    ...
    $var->method;

one would need to know into which class $var is blessed to know which
method is ultimately triggered. At INIT-time however, $var does not yet
contain a value.

This is surprisingly obvious, but nonetheless I was looking into the
padstack for over an hour until I realized that there is a reason why
most of the values in it were undef.

Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval


------------------------------

Date: 27 Jan 2004 01:42:56 GMT
From: Abigail <abigail@abigail.nl>
Subject: Re: Call Tree utility
Message-Id: <slrnc1bgh0.kui.abigail@alexandra.abigail.nl>

Tassilo v. Parseval (tassilo.parseval@rwth-aachen.de) wrote on MMMDCCXCIX
September MCMXCIII in <URL:news:bv0ji0$2d8$1@nets3.rz.RWTH-Aachen.DE>:
//  Also sprach Mark Jason Dominus:
//  
// > In article <bv022f$8lk$1@nets3.rz.RWTH-Aachen.DE>,
// > Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote:
// >>Also sprach Mark Jason Dominus:
// > 
// > It seems to me that if you're going to say "Also sprach" you should
// > say "Also sprach Dominus", or perhaps "Also sprach DOMINUS", and leave
// > it at that.
//  
//  That would make the reference to good ol' Nietzsche clearer, but it
//  would blur a little the fact who has written the post I am replying to.
//  There are also some obnoxious people here (me:-) whose last name
//  consists of two words, either abbreviated or not. Maybe my newsclient
//  has some smart heuristics to do that properly.


Of course, there are also those who go about with just a first name.

(Jezus, Madonna, Beatrix,

Abigail
)
-- 
perl -le 's[$,][join$,,(split$,,($!=85))[(q[0006143730380126152532042307].
          q[41342211132019313505])=~m[..]g]]e and y[yIbp][HJkP] and print'


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

#The Perl-Users Digest is a retransmission of the USENET newsgroup
#comp.lang.perl.misc.  For subscription or unsubscription requests, send
#the single line:
#
#	subscribe perl-users
#or:
#	unsubscribe perl-users
#
#to almanac@ruby.oce.orst.edu.  

NOTE: due to the current flood of worm email banging on ruby, the smtp
server on ruby has been shut off until further notice. 

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

#To request back copies (available for a week or so), send your request
#to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
#where x is the volume number and y is the issue number.

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V10 Issue 6028
***************************************


home help back first fref pref prev next nref lref last post