package B::RecDeparse;
-use 5.008;
+use 5.008001;
use strict;
use warnings;
+use B ();
+
use Config;
-use base qw/B::Deparse/;
+use base qw<B::Deparse>;
=head1 NAME
=head1 VERSION
-Version 0.04
+Version 0.07
=cut
-our $VERSION = '0.04';
+our $VERSION = '0.07';
=head1 SYNOPSIS
- perl -MO=RecDeparse,deparse,[@B__Deparse_opts],level,-1 [ -e '...' | bleh.pl ]
+ # Deparse recursively a Perl one-liner :
+ $ perl -MO=RecDeparse,deparse,@B__Deparse_opts,level,-1 -e '...'
+
+ # Or a complete Perl script :
+ $ perl -MO=RecDeparse,deparse,@B__Deparse_opts,level,-1 x.pl
- # Or as a module :
+ # Or a single code reference :
use B::RecDeparse;
- my $brd = B::RecDeparse->new(deparse => [ @b__deparse_opts ], level => $level);
+ my $brd = B::RecDeparse->new(
+ deparse => \@B__Deparse_opts,
+ level => $level,
+ );
my $code = $brd->coderef2text(sub { ... });
=head1 DESCRIPTION
This module extends L<B::Deparse> by making it recursively replace subroutine calls encountered when deparsing.
-Please refer to L<B::Deparse> documentation for what to do and how to do it. Besides the constructor syntax, everything should work the same for the two modules.
+Please refer to L<B::Deparse> documentation for what to do and how to do it.
+Besides the constructor syntax, everything should work the same for the two modules.
=head1 METHODS
-=head2 C<< new < deparse => [ @B__Deparse_opts ], level => $level > >>
+=head2 C<new>
-The L<B::RecDeparse> object constructor. You can specify the underlying L<B::Deparse> constructor arguments by passing a string or an array reference as the value of the C<deparse> key. The C<level> option expects an integer that specifies how many levels of recursions are allowed : C<-1> means infinite while C<0> means none and match L<B::Deparse> behaviour.
+ my $brd = B::RecDeparse->new(
+ deparse => \@B__Deparse_opts,
+ level => $level,
+ );
+
+The L<B::RecDeparse> object constructor.
+You can specify the underlying L<B::Deparse> constructor arguments by passing a string or an array reference as the value of the C<deparse> key.
+The C<level> option expects an integer that specifies how many levels of recursions are allowed : C<-1> means infinite while C<0> means none and match L<B::Deparse> behaviour.
=cut
sub init {
my $self = shift;
- $self->{brd_cur} = 0;
- $self->{brd_sub} = 0;
+ $self->{brd_cur} = 0;
+ $self->{brd_sub} = 0;
+ $self->{brd_seen} = { };
$self->SUPER::init(@_);
}
}
}
+sub deparse_sub {
+ my $self = shift;
+ my $cv = $_[0];
+
+ my $name;
+ unless ($cv->CvFLAGS & B::CVf_ANON()) {
+ $name = $cv->GV->SAFENAME;
+ }
+
+ local $self->{brd_seen}->{$name} = 1 if defined $name;
+ return $self->SUPER::deparse_sub(@_);
+}
+
sub pp_entersub {
my $self = shift;
sub pp_gv {
my $self = shift;
+ my $gv = $self->gv_or_padgv($_[0]);
+ my $name = $gv->NAME;
+ my $cv = $gv->CV;
+ my $seen = $self->{brd_seen};
+
my $body;
- if ($self->{brd_sub} <= 0 || !$self->_recurse) {
+ if (!$self->{brd_sub} or !$self->_recurse or $seen->{$name} or !$$cv
+ or !$cv->isa('B::CV') or $cv->ROOT->isa('B::NULL')) {
$body = $self->SUPER::pp_gv(@_);
} else {
- my $gv = $self->gv_or_padgv($_[0]);
-
$body = do {
- local @{$self}{qw/brd_sub brd_cur/} = (0, $self->{brd_cur} + 1);
+ local @{$self}{qw<brd_sub brd_cur>} = (0, $self->{brd_cur} + 1);
+ local $seen->{$name} = 1;
'sub ' . $self->indent($self->deparse_sub($gv->CV));
};
=head2 C<init>
+=head2 C<deparse_sub>
+
=head2 C<pp_entersub>
=head2 C<pp_refgen>
=head2 C<pp_gv>
-Functions and methods from L<B::Deparse> reimplemented by this module. Never call them directly.
+Functions and methods from L<B::Deparse> reimplemented by this module.
+Never call them directly.
Otherwise, L<B::RecDeparse> inherits all methods from L<B::Deparse>.
=head1 DEPENDENCIES
+L<perl> 5.8.1.
+
L<Carp> (standard since perl 5), L<Config> (since perl 5.00307) and L<B::Deparse> (since perl 5.005).
=head1 AUTHOR
=head1 BUGS
-Please report any bugs or feature requests to C<bug-b-recdeparse at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=B-RecDeparse>. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
+Please report any bugs or feature requests to C<bug-b-recdeparse at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=B-RecDeparse>.
+I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
=head1 SUPPORT
=head1 COPYRIGHT & LICENSE
-Copyright 2008,2009,2010 Vincent Pit, all rights reserved.
+Copyright 2008,2009,2010,2011,2013 Vincent Pit, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.