perl
view release on metacpan or search on metacpan
lib/B/Deparse.pm view on Meta::CPAN
$self->{'ambient_warnings'} = undef; # Assume no lexical warnings
$self->{'ambient_hints'} = 0;
$self->{'ambient_hinthash'} = undef;
$self->init();
while (my $arg = shift @_) {
if ($arg eq "-d") {
$self->{'use_dumper'} = 1;
require Data::Dumper;
} elsif ($arg =~ /^-f(.*)/) {
$self->{'files'}{$1} = 1;
} elsif ($arg eq "-l") {
$self->{'linenums'} = 1;
} elsif ($arg eq "-p") {
$self->{'parens'} = 1;
} elsif ($arg eq "-P") {
$self->{'noproto'} = 1;
} elsif ($arg eq "-q") {
$self->{'unquote'} = 1;
} elsif (substr($arg, 0, 2) eq "-s") {
$self->style_opts(substr $arg, 2);
} elsif ($arg =~ /^-x(\d)$/) {
$self->{'expand'} = $1;
}
}
return $self;
}
# Initialise the contextual information, either from
# defaults provided with the ambient_pragmas method,
# or from perl's own defaults otherwise.
sub init {
my $self = shift;
$self->{'warnings'} = $self->{'ambient_warnings'};
$self->{'hints'} = $self->{'ambient_hints'};
$self->{'hinthash'} = $self->{'ambient_hinthash'};
# also a convenient place to clear out subs_declared
delete $self->{'subs_declared'};
}
sub compile {
my(@args) = @_;
return sub {
my $self = B::Deparse->new(@args);
# First deparse command-line args
if (defined $^I) { # deparse -i
print q(BEGIN { $^I = ).perlstring($^I).qq(; }\n);
}
if ($^W) { # deparse -w
print qq(BEGIN { \$^W = $^W; }\n);
}
if ($/ ne "\n" or defined $O::savebackslash) { # deparse -l and -0
my $fs = perlstring($/) || 'undef';
my $bs = perlstring($O::savebackslash) || 'undef';
print qq(BEGIN { \$/ = $fs; \$\\ = $bs; }\n);
}
my @BEGINs = B::begin_av->isa("B::AV") ? B::begin_av->ARRAY : ();
my @UNITCHECKs = B::unitcheck_av->isa("B::AV")
? B::unitcheck_av->ARRAY
: ();
my @CHECKs = B::check_av->isa("B::AV") ? B::check_av->ARRAY : ();
my @INITs = B::init_av->isa("B::AV") ? B::init_av->ARRAY : ();
my @ENDs = B::end_av->isa("B::AV") ? B::end_av->ARRAY : ();
my @names = qw(BEGIN UNITCHECK CHECK INIT END);
my @blocks = \(@BEGINs, @UNITCHECKs, @CHECKs, @INITs, @ENDs);
while (@names) {
my ($name, $blocks) = (shift @names, shift @blocks);
for my $block (@$blocks) {
$self->todo($block, 0, $name);
}
}
$self->stash_subs();
local($SIG{"__DIE__"}) =
sub {
if ($self->{'curcop'}) {
my $cop = $self->{'curcop'};
my($line, $file) = ($cop->line, $cop->file);
print STDERR "While deparsing $file near line $line,\n";
}
};
$self->{'curcv'} = main_cv;
$self->{'curcvlex'} = undef;
print $self->print_protos;
@{$self->{'subs_todo'}} =
sort {$a->[0] <=> $b->[0]} @{$self->{'subs_todo'}};
my $root = main_root;
local $B::overlay = {};
unless (null $root) {
$self->pad_subs($self->{'curcv'});
# Check for a stub-followed-by-ex-cop, resulting from a program
# consisting solely of sub declarations. For backward-compati-
# bility (and sane output) we donât want to emit the stub.
# leave
# enter
# stub
# ex-nextstate (or ex-dbstate)
my $kid;
if ( $root->name eq 'leave'
and ($kid = $root->first)->name eq 'enter'
and !null($kid = $kid->sibling) and $kid->name eq 'stub'
and !null($kid = $kid->sibling) and $kid->name eq 'null'
and class($kid) eq 'COP' and null $kid->sibling )
{
# ignore
} else {
$self->pessimise($root, main_start);
print $self->indent($self->deparse_root($root)), "\n";
}
}
my @text;
while (scalar(@{$self->{'subs_todo'}})) {
push @text, $self->next_todo;
}
print $self->indent(join("", @text)), "\n" if @text;
# Print __DATA__ section, if necessary
no strict 'refs';
my $laststash = defined $self->{'curcop'}
? $self->{'curcop'}->stash->NAME : $self->{'curstash'};
if (defined *{$laststash."::DATA"}{IO}) {
print $self->keyword("package") . " $laststash;\n"
unless $laststash eq $self->{'curstash'};
print $self->keyword("__DATA__") . "\n";
print readline(*{$laststash."::DATA"});
}
( run in 0.869 second using v1.01-cache-2.11-cpan-5a3173703d6 )