File Coverage

lib/B/DeparseTree/TreeMain.pm
Criterion Covered Total %
statement 330 662 49.8
branch 123 346 35.5
condition 31 122 25.4
subroutine 39 50 78.0
pod 2 25 8.0
total 525 1205 43.5


line stmt bran cond sub pod time code
1             # Copyright (c) 2015-2018 Rocky Bernstein
2             # Copyright (c) 1998-2000, 2002, 2003, 2004, 2005, 2006 Stephen McCamant.
3              
4             # All rights reserved.
5             # This module is free software; you can redistribute and/or modify
6             # it under the same terms as Perl itself.
7              
8             # This is based on the module B::Deparse by Stephen McCamant.
9             # It has been extended save tree structure, and is addressible
10             # by opcode address.
11              
12             # B::Parse in turn is based on the module of the same name by Malcolm Beattie,
13             # but essentially none of his code remains.
14              
15             # The is the main entrypoint for DeparseTree objects and routines.
16             # In the future there may be a StringMain which is like this
17             # but doesn't save copious tree information but instead just gathers
18             # strings in the same way B::Deparse does.
19 8     8   39 use strict; use warnings;
  8     8   11  
  8         176  
  8         29  
  8         13  
  8         347  
20              
21             package B::DeparseTree;
22              
23 8         905 use B qw(class
24             CVf_LVALUE
25             CVf_METHOD
26             OPf_KIDS
27             OPf_SPECIAL
28             OPpLVAL_INTRO
29             OPpTARGET_MY
30             SVf_IOK
31             SVf_NOK
32             SVf_POK
33             SVf_ROK
34             SVs_RMG
35             SVs_SMG
36             main_cv main_root main_start
37             opnumber
38             perlstring
39             svref_2object
40 8     8   37 );
  8         12  
41              
42 8     8   41 use Carp;
  8         10  
  8         332  
43 8     8   34 use B::Deparse;
  8         31  
  8         155  
44 8     8   2673 use B::DeparseTree::OPflags;
  8         16  
  8         405  
45 8     8   2759 use B::DeparseTree::PP_OPtable;
  8         38  
  8         901  
46 8     8   3082 use B::DeparseTree::SyntaxTree;
  8         21  
  8         1580  
47              
48             # Copy unchanged functions from B::Deparse
49             *find_scope_en = *B::Deparse::find_scope_en;
50             *find_scope_st = *B::Deparse::find_scope_st;
51             *gv_name = *B::Deparse::gv_name;
52             *lex_in_scope = *B::Deparse::lex_in_scope;
53             *padname = *B::Deparse::padname;
54             *stash_subs = *B::Deparse::stash_subs;
55             *stash_variable = *B::Deparse::stash_variable;
56             *todo = *B::Deparse::todo;
57              
58             our($VERSION, @EXPORT, @ISA);
59             $VERSION = '3.3.0';
60             @ISA = qw(Exporter);
61             @EXPORT = qw(
62             %globalnames
63             %ignored_hints
64             %rev_feature
65             WARN_MASK
66             coderef2info
67             coderef2text
68             const
69             declare_hinthash
70             declare_hints
71             declare_warnings
72             deparse_sub($$$$)
73             deparse_subname($$)
74             new
75             next_todo
76             pragmata
77             seq_subs
78             style_opts
79             todo
80             );
81              
82 8     8   49 use Config;
  8         13  
  8         1397  
83             my $is_cperl = $Config::Config{usecperl};
84              
85             my $module;
86             if ($] >= 5.014 and $] < 5.016) {
87             $module = "P514";
88             } elsif ($] >= 5.016 and $] < 5.018) {
89             $module = "P516";
90             } elsif ($] >= 5.018 and $] < 5.020) {
91             $module = "P518";
92             } elsif ($] >= 5.020 and $] < 5.022) {
93             $module = "P520";
94             } elsif ($] >= 5.022 and $] < 5.024) {
95             $module = "P522";
96             } elsif ($] >= 5.024 and $] < 5.026) {
97             $module = "P524";
98             } elsif ($] >= 5.026) {
99             $module = "P526";
100             } else {
101             die "Can only handle Perl 5.16..5.26";
102             }
103              
104             $module .= 'c' if $is_cperl;
105             @ISA = ("Exporter", "B::DeparseTree::$module");
106              
107             require "B/DeparseTree/${module}.pm";
108              
109             # The BEGIN {} is used here because otherwise this code isn't executed
110             # when you run B::Deparse on itself.
111             my %globalnames;
112 8     8   511 BEGIN { map($globalnames{$_}++, "SIG", "STDIN", "STDOUT", "STDERR", "INC",
113             "ENV", "ARGV", "ARGVOUT", "_"); }
114              
115             my $max_prec;
116 8     8   517 BEGIN { $max_prec = int(0.999 + 8*length(pack("F", 42))*log(2)/log(10)); }
117              
118             BEGIN {
119             # List version-specific constants here.
120             # Easiest way to keep this code portable between version looks to
121             # be to fake up a dummy constant that will never actually be true.
122 8     8   28 foreach (qw(OPpSORT_INPLACE OPpSORT_DESCEND OPpITER_REVERSED
123             OPpCONST_NOVER OPpPAD_STATE PMf_SKIPWHITE RXf_SKIPWHITE
124             RXf_PMf_CHARSET RXf_PMf_KEEPCOPY
125             CVf_LOCKED OPpREVERSE_INPLACE OPpSUBSTR_REPL_FIRST
126             PMf_NONDESTRUCT OPpCONST_ARYBASE OPpEVAL_BYTES)) {
127 120         151 eval { import B $_ };
  120         8235  
128 8     8   47 no strict 'refs';
  8         17  
  8         513  
129 120 100       199 *{$_} = sub () {0} unless *{$_}{CODE};
  24         78  
  120         3256  
130             }
131             }
132              
133             sub new {
134 10     10 1 662388 my $class = shift;
135 10         39 my $self = bless {}, $class;
136 10         163 $self->{'cuddle'} = " "; #\n%| is another alternative
137 10         69 $self->{'curcop'} = undef;
138 10         40 $self->{'curstash'} = "main";
139 10         36 $self->{'ex_const'} = "'?unrecoverable constant?'";
140 10         29 $self->{'expand'} = 0;
141 10         35 $self->{'files'} = {};
142              
143             # How many spaces per indent nesting?
144 10         34 $self->{'indent_size'} = 4;
145              
146 10         37 $self->{'opaddr'} = 0;
147 10         30 $self->{'linenums'} = 0;
148 10         31 $self->{'parens'} = 0;
149 10         32 $self->{'subs_todo'} = [];
150 10         27 $self->{'unquote'} = 0;
151 10         27 $self->{'use_dumper'} = 0;
152              
153             # Compress spaces with tabs? 1 tab = 8 spaces
154 10         21 $self->{'use_tabs'} = 0;
155              
156             # Indentation level
157 10         25 $self->{'level'} = 0;
158              
159 10         33 $self->{'ambient_arybase'} = 0;
160 10         26 $self->{'ambient_warnings'} = undef; # Assume no lexical warnings
161 10         24 $self->{'ambient_hints'} = 0;
162 10         29 $self->{'ambient_hinthash'} = undef;
163              
164             # Given an opcode address, get the accumulated OP tree
165             # OP for that. FIXME: remove this
166 10         28 $self->{optree} = {};
167              
168             # For B::DeparseTree::TreeNode's that are created and don't have
169             # real OPs associated with them, we assign a fake address;
170 10         28 $self->{'last_fake_addr'} = 0;
171              
172 10         54 $self->init();
173              
174 10         39 while (my $arg = shift @_) {
175 0 0       0 if ($arg eq "-d") {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
176 0         0 $self->{'use_dumper'} = 1;
177 0         0 require Data::Dumper;
178             } elsif ($arg =~ /^-f(.*)/) {
179 0         0 $self->{'files'}{$1} = 1;
180             } elsif ($arg eq "-l") {
181 0         0 $self->{'linenums'} = 1;
182             } elsif ($arg eq "-a") {
183 0         0 $self->{'linenums'} = 1;
184 0         0 $self->{'opaddr'} = 1;
185             } elsif ($arg eq "-p") {
186 0         0 $self->{'parens'} = 1;
187             } elsif ($arg eq "-P") {
188 0         0 $self->{'noproto'} = 1;
189             } elsif ($arg eq "-q") {
190 0         0 $self->{'unquote'} = 1;
191             } elsif (substr($arg, 0, 2) eq "-s") {
192 0         0 $self->style_opts(substr $arg, 2);
193             } elsif ($arg =~ /^-x(\d)$/) {
194 0         0 $self->{'expand'} = $1;
195             }
196             }
197 10         35 return $self;
198             }
199              
200             {
201             # Mask out the bits that L uses
202             my $WARN_MASK;
203             BEGIN {
204 8     8   1248 $WARN_MASK = $warnings::Bits{all} | $warnings::DeadBits{all};
205             }
206             sub WARN_MASK () {
207 5184     5184 0 26958 return $WARN_MASK;
208             }
209             }
210              
211             # Initialize the contextual information, either from
212             # defaults provided with the ambient_pragmas method,
213             # or from Perl's own defaults otherwise.
214             sub init {
215 1402     1402 0 2550 my $self = shift;
216              
217 1402         3416 $self->{'arybase'} = $self->{'ambient_arybase'};
218             $self->{'warnings'} = defined ($self->{'ambient_warnings'})
219 1402 100       3898 ? $self->{'ambient_warnings'} & WARN_MASK
220             : undef;
221 1402         2304 $self->{'hints'} = $self->{'ambient_hints'};
222 1402 50       3048 $self->{'hints'} &= 0xFF if $] < 5.009;
223 1402         2364 $self->{'hinthash'} = $self->{'ambient_hinthash'};
224              
225             # also a convenient place to clear out subs_declared
226 1402         2950 delete $self->{'subs_declared'};
227             }
228              
229             BEGIN {
230 8     8   31 for (qw[ pushmark ])
231             {
232 8         6425 eval "sub OP_\U$_ () { " . opnumber($_) . "}"
233             }
234             }
235              
236             sub main2info
237             {
238 0     0 0 0 my $self = shift;
239 0         0 $self->{'curcv'} = B::main_cv;
240 0         0 $self->pessimise(B::main_root, B::main_start);
241 0         0 return $self->deparse_root(B::main_root);
242             }
243              
244             sub coderef2info
245             {
246 1328     1328 0 1089180 my ($self, $coderef, $start_op) = @_;
247 1328         6417 my $cv = svref_2object ( $coderef );
248 1328         4424 my $gv = $cv->GV;
249 1328 50       6117 if ($gv->NAME eq 'main') {
250 0         0 return $self->main2info();
251             } else {
252 1328 50       5050 croak "Usage: ->coderef2info(CODEREF)"
253             unless UNIVERSAL::isa($coderef, "CODE");
254 1328         4712 $self->init();
255 1328         3878 return $self->deparse_sub($cv, $start_op);
256             }
257             }
258              
259             sub coderef2text
260             {
261 64     64 1 104936 my ($self, $func) = @_;
262 64         134 my $info;
263 64 50       199 if ($func eq 'main::main') {
264 0         0 $info = $self->main2info();
265             } else {
266 64 50       248 croak "Usage: ->coderef2text(CODEREF)" unless UNIVERSAL::isa($func, "CODE");
267 64         197 $self->init();
268 64         179 $info = $self->coderef2info($func);
269             }
270 64         209 return $self->info2str($info);
271             }
272              
273             sub const {
274 91     91 0 120 my $self = shift;
275 91         156 my($sv, $cx) = @_;
276 91 50       184 if ($self->{'use_dumper'}) {
277 0         0 return $self->const_dumper($sv, $cx);
278             }
279 91 50       478 if (class($sv) eq "SPECIAL") {
280             # sv_undef, sv_yes, sv_no
281 0         0 my $text = ('undef', '1', $self->maybe_parens("!1", $cx, 21))[$$sv-1];
282 0         0 return $self->info_from_string('const: special', $sv, $text);
283             }
284 91 50       384 if (class($sv) eq "NULL") {
285 0         0 return $self->info_from_string('const: NULL', $sv, 'undef');
286             }
287             # convert a version object into the "v1.2.3" string in its V magic
288 91 50       280 if ($sv->FLAGS & SVs_RMG) {
289 0         0 for (my $mg = $sv->MAGIC; $mg; $mg = $mg->MOREMAGIC) {
290 0 0       0 if ($mg->TYPE eq 'V') {
291 0         0 return $self->info_from_string('const_magic', $sv,
292             $mg->PTR);
293             }
294             }
295             }
296              
297 91 100 33     377 if ($sv->FLAGS & SVf_IOK) {
    50          
    50          
    50          
298 62         212 my $str = $sv->int_value;
299 62 50       146 $str = $self->maybe_parens($str, $cx, 21) if $str < 0;
300 62         201 return $self->info_from_string("const: integer $str", $sv, $str);
301             } elsif ($sv->FLAGS & SVf_NOK) {
302 0         0 my $nv = $sv->NV;
303 0 0       0 if ($nv == 0) {
    0          
    0          
304 0 0       0 if (pack("F", $nv) eq pack("F", 0)) {
305             # positive zero
306 0         0 return $self->info_from_string('const: float positive 0',
307             $sv,
308             "0");
309             } else {
310             # negative zero
311 0         0 return $self->info_from_string('const: float negative 0',
312             $sv, $self,
313             $self->maybe_parens("-.0", $cx, 21));
314             }
315             } elsif (1/$nv == 0) {
316 0 0       0 if ($nv > 0) {
317             # positive infinity
318 0         0 return $self->info_from_string('const: float +infinity',
319             $sv,
320             $self->maybe_parens("9**9**9", $cx, 22));
321             } else {
322             # negative infinity
323 0         0 return $self->info_from_string('const: float -infinity',
324             $sv,
325             $self->maybe_parens("-9**9**9", $cx, 21));
326             }
327             } elsif ($nv != $nv) {
328             # NaN
329 0 0       0 if (pack("F", $nv) eq pack("F", sin(9**9**9))) {
    0          
330             # the normal kind
331 0         0 return info_from_text($sv, $self, "sin(9**9**9)", 'const_Nan', {});
332             } elsif (pack("F", $nv) eq pack("F", -sin(9**9**9))) {
333             # the inverted kind
334 0         0 return info_from_text($sv, $self, $self->maybe_parens("-sin(9**9**9)", $cx, 21),
335             'const: float Nan invert', {});
336             } else {
337             # some other kind
338 0         0 my $hex = unpack("h*", pack("F", $nv));
339 0         0 return info_from_text($sv, $self, qq'unpack("F", pack("h*", "$hex"))',
340             'const: Na na na', {});
341             }
342             }
343             # first, try the default stringification
344 0         0 my $str = "$nv";
345 0 0       0 if ($str != $nv) {
346             # failing that, try using more precision
347 0         0 $str = sprintf("%.${max_prec}g", $nv);
348             # if (pack("F", $str) ne pack("F", $nv)) {
349 0 0       0 if ($str != $nv) {
350             # not representable in decimal with whatever sprintf()
351             # and atof() Perl is using here.
352 0         0 my($mant, $exp) = B::Deparse::split_float($nv);
353 0         0 return info_from_text($sv, $self, $self->maybe_parens("$mant * 2**$exp", $cx, 19),
354             'const: float not-sprintf/atof-able', {});
355             }
356             }
357 0 0       0 $str = $self->maybe_parens($str, $cx, 21) if $nv < 0;
358 0         0 return info_from_text($sv, $self, $str, 'constant nv', {});
359             } elsif ($sv->FLAGS & SVf_ROK && $sv->can("RV")) {
360 0         0 my $ref = $sv->RV;
361 0 0       0 if (class($ref) eq "AV") {
    0          
    0          
362 0         0 my $list_info = $self->list_const($sv, 2, $ref->ARRAY);
363 0         0 return info_from_list($sv, $self, ['[', $list_info->{text}, ']'], '', 'const_av',
364             {body => [$list_info]});
365             } elsif (class($ref) eq "HV") {
366 0         0 my %hash = $ref->ARRAY;
367 0         0 my @elts;
368 0         0 for my $k (sort keys %hash) {
369 0         0 push @elts, "$k => " . $self->const($hash{$k}, 6);
370             }
371 0         0 return info_from_list($sv, $self, ["{", join(", ", @elts), "}"], '',
372             'constant hash value', {});
373             } elsif (class($ref) eq "CV") {
374             BEGIN {
375 8 50   8   65 if ($] > 5.0150051) {
376 8         72 require overloading;
377 8         14729 unimport overloading;
378             }
379             }
380 0 0 0     0 if ($] > 5.0150051 && $self->{curcv} &&
      0        
381             $self->{curcv}->object_2svref == $ref->object_2svref) {
382 0         0 return $self->info_from_string('sub __SUB__', $sv,
383             $self->keyword("__SUB__"));
384             }
385 0         0 my $sub_info = $self->deparse_sub($ref);
386 0         0 return info_from_list($sub_info->{op}, $self, ["sub ", $sub_info->{text}], '',
387             'constant sub 2',
388             {body => [$sub_info]});
389             }
390 0 0       0 if ($ref->FLAGS & SVs_SMG) {
391 0         0 for (my $mg = $ref->MAGIC; $mg; $mg = $mg->MOREMAGIC) {
392 0 0       0 if ($mg->TYPE eq 'r') {
393 0         0 my $re = B::Deparse::re_uninterp(B::Deparse::escape_str(B::Deparse::re_unback($mg->precomp)));
394 0         0 return $self->single_delim($sv, "qr", "", $re);
395             }
396             }
397             }
398              
399 0         0 my $const = $self->const($ref, 20);
400 0 0 0     0 if ($self->{in_subst_repl} && $const =~ /^[0-9]/) {
401 0         0 $const = "($const)";
402             }
403 0         0 my @texts = ("\\", $const);
404 0         0 return info_from_list($sv, $self, \@texts, '', 'const_rv',
405             {maybe_parens => [$self, $cx, 20]});
406              
407             } elsif ($sv->FLAGS & SVf_POK) {
408 29         78 my $str = $sv->PV;
409 29 50       105 if ($str =~ /[[:^print:]]/) {
410 0         0 return $self->single_delim($sv, "qq", '"',
411             B::Deparse::uninterp B::Deparse::escape_str B::Deparse::unback $str);
412             } else {
413 29         202 return $self->single_delim($sv, "q", "'", B::Deparse::unback $str);
414             }
415             } else {
416 0         0 return $self->info_from_string('const: undef', $sv, "undef");
417             }
418             }
419              
420             sub const_dumper
421             {
422 0     0 0 0 my $self = shift;
423 0         0 my($sv, $cx) = @_;
424 0         0 my $ref = $sv->object_2svref();
425 0         0 my $dumper = Data::Dumper->new([$$ref], ['$v']);
426 0         0 $dumper->Purity(1)->Terse(1)->Deparse(1)->Indent(0)->Useqq(1)->Sortkeys(1);
427 0         0 my $str = $dumper->Dump();
428 0 0       0 if ($str =~ /^\$v/) {
429             # FIXME: ???
430 0         0 return info_from_text($sv, $self, ['${my', $str, '\$v}'], 'const_dumper_my', {});
431             } else {
432 0         0 return $self->info_from_string("constant string", $sv, $str);
433             }
434             }
435              
436             # This is a special case of scopeop and lineseq, for the case of the
437             # main_root.
438             sub deparse_root {
439 0     0 0 0 my $self = shift;
440 0         0 my($op) = @_;
441             local(@$self{qw'curstash warnings hints hinthash'})
442 0         0 = @$self{qw'curstash warnings hints hinthash'};
443 0         0 my @ops;
444 0 0       0 return if B::Deparse::null $op->first; # Can happen, e.g., for Bytecode without -k
445 0         0 for (my $kid = $op->first->sibling; !B::Deparse::null($kid); $kid = $kid->sibling) {
446 0         0 push @ops, $kid;
447             }
448             my $fn = sub {
449 0     0   0 my ($exprs, $i, $info, $parent) = @_;
450 0         0 my $text = $info->{text};
451 0         0 my $op = $ops[$i];
452 0         0 $text =~ s/\f//;
453 0         0 $text =~ s/\n$//;
454 0         0 $text =~ s/;\n?\z//;
455 0         0 $text =~ s/^\((.+)\)$/$1/;
456 0         0 $info->{type} = $op->name;
457 0         0 $info->{op} = $op;
458              
459 0         0 $self->{optree}{$$op} = $info;
460              
461 0         0 $info->{text} = $text;
462 0 0       0 $info->{parent} = $$parent if $parent;
463 0         0 push @$exprs, $info;
464 0         0 };
465 0         0 my $info = $self->walk_lineseq($op, \@ops, $fn);
466 0         0 my @skipped_ops;
467 0 0       0 if (exists $info->{other_ops}) {
468 0         0 @skipped_ops = @{$info->{other_ops}};
  0         0  
469 0         0 push @skipped_ops, $op->first;
470             } else {
471 0         0 @skipped_ops = ($op->first);
472             }
473 0         0 $info->{other_ops} = \@skipped_ops;
474 0         0 return $info;
475              
476             }
477              
478             sub update_node($$$$)
479             {
480 2101     2101 0 4461 my ($self, $node, $prev_expr, $op) = @_;
481 2101         3730 $node->{prev_expr} = $prev_expr;
482 2101         2823 my $addr = $prev_expr->{addr};
483 2101 100 66     8386 if ($addr && ! exists $self->{optree}{$addr}) {
484 4 50       27 $self->{optree}{$addr} = $node if $op;
485             }
486             }
487              
488             sub walk_lineseq
489             {
490 1342     1342 0 2665 my ($self, $op, $kids, $callback) = @_;
491 1342         2308 my @kids = @$kids;
492 1342         2040 my @body = (); # Accumulated node structures
493 1342         1660 my $expr;
494 1342         1809 my $prev_expr = undef;
495 1342         1813 my $fix_cop = undef;
496 1342         3228 for (my $i = 0; $i < @kids; $i++) {
497 2088 100       13231 if (B::Deparse::is_state $kids[$i]) {
498 2087         6286 $expr = ($self->deparse($kids[$i], 0, $op));
499 2087         5743 $callback->(\@body, $i, $expr, $op);
500 2087         2836 $prev_expr = $expr;
501 2087 50       3854 if ($fix_cop) {
502 0         0 $fix_cop->{text} = $expr->{text};
503             }
504 2087         2668 $i++;
505 2087 50       4482 if ($i > $#kids) {
506 0         0 last;
507             }
508             }
509 2088 50       38520 if (B::Deparse::is_for_loop($kids[$i])) {
510 0 0       0 print "YYY for loop\n" if $ENV{'DEBUG_DEPARSETREE'};
511 0         0 my $loop_expr = $self->for_loop($kids[$i], 0);
512 0 0       0 $callback->(\@body,
513             $i += $kids[$i]->sibling->name eq "unstack" ? 2 : 1,
514             $loop_expr);
515 0         0 $prev_expr = $loop_expr;
516 0         0 next;
517             }
518 2088         7823 $expr = $self->deparse($kids[$i], (@kids != 1)/2, $op);
519              
520             # Perform semantic action on $expr accumulating the result
521             # in @body. $op is the parent, and $i is the child position
522 2088         6163 $callback->(\@body, $i, $expr, $op);
523 2088 100       4654 unless (exists $expr->{prev_expr}) {
524 759         1977 $self->update_node($expr, $prev_expr, $op);
525             }
526 2088         2875 $prev_expr = $expr;
527 2088 50       3583 if ($fix_cop) {
528 0         0 $fix_cop->{text} = $expr->{text};
529             }
530              
531             # If the text portion of a COP is empty, set up to fill it in
532             # from the text portion of the next node.
533 2088 50 33     16099 if (B::class($op) eq "COP" && !$expr->{text}) {
534 0         0 $fix_cop = $op;
535             } else {
536 2088         6440 $fix_cop = undef;
537             }
538             }
539              
540             # Add semicolons between statements. Don't null statements
541             # (which can happen for nexstate which doesn't have source code
542             # associated with it.
543 1342         4593 $expr = $self->info_from_template("statements", $op, "%;", [], \@body);
544 1342         4499 $self->update_node($expr, $prev_expr, $op);
545 1342         12533 return $expr;
546             }
547              
548             # $root should be the op which represents the root of whatever
549             # we're sequencing here. If it's undefined, then we don't append
550             # any subroutine declarations to the deparsed ops, otherwise we
551             # append appropriate declarations.
552             sub lineseq {
553 1342     1342 0 3806 my($self, $root, $cx, @ops) = @_;
554              
555 1342         2430 my $out_cop = $self->{'curcop'};
556 1342 100       2776 my $out_seq = defined($out_cop) ? $out_cop->cop_seq : undef;
557 1342         1781 my $limit_seq;
558 1342 50       2679 if (defined $root) {
559 1342         2227 $limit_seq = $out_seq;
560 1342         1580 my $nseq;
561 1342 50       1597 $nseq = $self->find_scope_st($root->sibling) if ${$root->sibling};
  1342         5389  
562 1342 100 33     4237 $limit_seq = $nseq if !defined($limit_seq)
      66        
563             or defined($nseq) && $nseq < $limit_seq;
564             }
565             $limit_seq = $self->{'limit_seq'}
566             if defined($self->{'limit_seq'})
567 1342 50 33     3128 && (!defined($limit_seq) || $self->{'limit_seq'} < $limit_seq);
      66        
568 1342         2714 local $self->{'limit_seq'} = $limit_seq;
569              
570             my $fn = sub {
571 4175     4175   7335 my ($exprs, $i, $info, $parent) = @_;
572 4175         5838 my $op = $ops[$i];
573 4175 50       7349 $info->{type} = $op->name unless $info->{type};
574 4175         6015 $info->{child_pos} = $i;
575 4175         5353 $info->{op} = $op;
576 4175 50       6955 if ($parent) {
577 4175 50       7131 Carp::confess("nonref parent, op: $op->name") if !ref($parent);
578 4175         6028 $info->{parent} = $$parent ;
579             }
580              
581 4175         6624 $self->{optree}{$$op} = $info;
582              
583 4175         7352 push @$exprs, $info;
584 1342         6543 };
585 1342         4468 return $self->walk_lineseq($root, \@ops, $fn);
586             }
587              
588             # _pessimise_walk(): recursively walk the optree of a sub,
589             # possibly undoing optimisations along the way.
590             # walk tree in root-to-branch order
591             # We add parent pointers in the process.
592              
593             sub _pessimise_walk {
594 12558     12558   19514 my ($self, $startop) = @_;
595              
596 12558 50       18657 return unless $$startop;
597 12558         14877 my ($op, $parent_op);
598              
599 12558         20705 for ($op = $startop; $$op; $op = $op->sibling) {
600 24710         62258 my $ppname = $op->name;
601              
602 24710   50     109491 $self->{ops}{$$op} ||= {};
603 24710         40283 $self->{ops}{$$op}{op} = $op;
604 24710         31572 $self->{ops}{$$op}{parent_op} = $startop;
605              
606             # pessimisations start here
607              
608 24710 100       34808 if ($ppname eq "padrange") {
609             # remove PADRANGE:
610             # the original optimisation either (1) changed this:
611             # pushmark -> (various pad and list and null ops) -> the_rest
612             # or (2), for the = @_ case, changed this:
613             # pushmark -> gv[_] -> rv2av -> (pad stuff) -> the_rest
614             # into this:
615             # padrange ----------------------------------------> the_rest
616             # so we just need to convert the padrange back into a
617             # pushmark, and in case (1), set its op_next to op_sibling,
618             # which is the head of the original chain of optimised-away
619             # pad ops, or for (2), set it to sibling->first, which is
620             # the original gv[_].
621              
622 827         4532 $B::overlay->{$$op} = {
623             type => OP_PUSHMARK,
624             name => 'pushmark',
625             private => ($op->private & OPpLVAL_INTRO),
626             };
627             }
628              
629             # pessimisations end here
630              
631 24710 100 66     100354 if (class($op) eq 'PMOP'
      100        
      66        
632             && ref($op->pmreplroot)
633 24         109 && ${$op->pmreplroot}
634             && $op->pmreplroot->isa( 'B::OP' ))
635             {
636 4         14 $self-> _pessimise_walk($op->pmreplroot);
637             }
638              
639 24710 100       118242 if ($op->flags & OPf_KIDS) {
640 11224         34337 $self-> _pessimise_walk($op->first);
641             }
642              
643             }
644             }
645              
646              
647             # _pessimise_walk_exe(): recursively walk the op_next chain of a sub,
648             # possibly undoing optimisations along the way.
649             # walk tree in execution order
650              
651             sub _pessimise_walk_exe {
652 1469     1469   3355 my ($self, $startop, $visited) = @_;
653              
654 1469 100       3366 return unless $$startop;
655 1455 50       3974 return if $visited->{$$startop};
656 1455         2277 my $op;
657 1455         3490 for ($op = $startop; $$op; $op = $op->next) {
658 12891 100       23851 last if $visited->{$$op};
659 12770         18641 $visited->{$$op} = 1;
660              
661 12770   50     21014 $self->{ops}{$$op} ||= {};
662 12770         17762 $self->{ops}{$$op}{op} = $op;
663              
664 12770         30058 my $ppname = $op->name;
665 12770 100       70867 if ($ppname =~
    100          
    100          
666             /^((and|d?or)(assign)?|(map|grep)while|range|cond_expr|once)$/
667             # entertry is also a logop, but its op_other invariably points
668             # into the same chain as the main execution path, so we skip it
669             ) {
670 116         443 $self->_pessimise_walk_exe($op->other, $visited);
671             }
672             elsif ($ppname eq "subst") {
673 18         61 $self->_pessimise_walk_exe($op->pmreplstart, $visited);
674             }
675             elsif ($ppname =~ /^(enter(loop|iter))$/) {
676             # redoop and nextop will already be covered by the main block
677             # of the loop
678 5         24 $self->_pessimise_walk_exe($op->lastop, $visited);
679             }
680              
681             # pessimisations start here
682             }
683             }
684              
685             # Go through an optree and "remove" some optimisations by using an
686             # overlay to selectively modify or un-null some ops. Deparsing in the
687             # absence of those optimisations is then easier.
688             #
689             # Note that older optimisations are not removed, as Deparse was already
690             # written to recognise them before the pessimise/overlay system was added.
691              
692             sub pessimise {
693 1330     1330 0 2779 my ($self, $root, $start) = @_;
694              
695 8     8   55 no warnings 'recursion';
  8         18  
  8         5417  
696             # walk tree in root-to-branch order
697 1330         4340 $self->_pessimise_walk($root);
698              
699 1330         2120 my %visited;
700             # walk tree in execution order
701 1330         3621 $self->_pessimise_walk_exe($start, \%visited);
702             }
703              
704             sub style_opts
705             {
706 0     0 0 0 my ($self, $opts) = @_;
707 0         0 my $opt;
708 0         0 while (length($opt = substr($opts, 0, 1))) {
709 0 0       0 if ($opt eq "C") {
    0          
    0          
    0          
710 0         0 $self->{'cuddle'} = " ";
711 0         0 $opts = substr($opts, 1);
712             } elsif ($opt eq "i") {
713 0         0 $opts =~ s/^i(\d+)//;
714 0         0 $self->{'indent_size'} = $1;
715             } elsif ($opt eq "T") {
716 0         0 $self->{'use_tabs'} = 1;
717 0         0 $opts = substr($opts, 1);
718             } elsif ($opt eq "v") {
719 0         0 $opts =~ s/^v([^.]*)(.|$)//;
720 0         0 $self->{'ex_const'} = $1;
721             }
722             }
723             }
724              
725             # B::Deparse name is print_protos
726             sub extract_prototypes($)
727             {
728 0     0 0 0 my $self = shift;
729 0         0 my $ar;
730             my @ret;
731 0         0 foreach $ar (@{$self->{'protos_todo'}}) {
  0         0  
732 0         0 my $body;
733 0 0       0 if (defined $ar->[1]) {
734 0 0       0 if (ref $ar->[1]) {
735             # FIXME: better optree tracking?
736             # And use formatting markup?
737 0         0 my $node = $self->const($ar->[1]->RV,0);
738 0         0 my $body_node =
739             $self->info_from_template("protos", undef,
740             "() {\n %c;\n}",
741             undef, [$node]);
742 0         0 $body = $body_node->{text};
743             } else {
744 0         0 $body = sprintf " (%s);", $ar->[1];
745             }
746             } else {
747 0         0 $body = ";";
748             }
749 0         0 push @ret, sprintf "sub %s%s\n", $ar->[0], $body;
750             }
751 0         0 delete $self->{'protos_todo'};
752 0         0 return @ret;
753             }
754              
755             # This gets called automatically when option:
756             # -MO="DeparseTree,sC" is added
757             # Running this prints out the program text.
758             sub compile {
759 0     0 0 0 my(@args) = @_;
760             return sub {
761 0     0   0 my $self = B::DeparseTree->new(@args);
762             # First deparse command-line args
763 0 0       0 if (defined $^I) { # deparse -i
764 0         0 print q(BEGIN { $^I = ).perlstring($^I).qq(; }\n);
765             }
766 0 0       0 if ($^W) { # deparse -w
767 0         0 print qq(BEGIN { \$^W = $^W; }\n);
768             }
769 0 0 0     0 if ($/ ne "\n" or defined $O::savebackslash) { # deparse -l and -0
770 0   0     0 my $fs = perlstring($/) || 'undef';
771 0   0     0 my $bs = perlstring($O::savebackslash) || 'undef';
772 0         0 print qq(BEGIN { \$/ = $fs; \$\\ = $bs; }\n);
773             }
774 0 0       0 my @BEGINs = B::begin_av->isa("B::AV") ? B::begin_av->ARRAY : ();
775 0 0       0 my @UNITCHECKs = B::unitcheck_av->isa("B::AV")
776             ? B::unitcheck_av->ARRAY
777             : ();
778 0 0       0 my @CHECKs = B::check_av->isa("B::AV") ? B::check_av->ARRAY : ();
779 0 0       0 my @INITs = B::init_av->isa("B::AV") ? B::init_av->ARRAY : ();
780 0 0       0 my @ENDs = B::end_av->isa("B::AV") ? B::end_av->ARRAY : ();
781 0 0       0 if ($] < 5.020) {
782 0         0 for my $block (@BEGINs, @UNITCHECKs, @CHECKs, @INITs, @ENDs) {
783 0         0 $self->B::Deparse::todo($block, 0);
784             }
785             } else {
786 0         0 my @names = qw(BEGIN UNITCHECK CHECK INIT END);
787 0         0 my @blocks = (\@BEGINs, \@UNITCHECKs, \@CHECKs, \@INITs, \@ENDs);
788 0         0 while (@names) {
789 0         0 my ($name, $blocks) = (shift @names, shift @blocks);
790 0         0 for my $block (@$blocks) {
791 0         0 $self->todo($block, 0, $name);
792             }
793             }
794             }
795 0         0 $self->B::Deparse::stash_subs();
796             local($SIG{"__DIE__"}) =
797             sub {
798 0 0       0 if ($self->{'curcop'}) {
799 0         0 my $cop = $self->{'curcop'};
800 0         0 my($line, $file) = ($cop->line, $cop->file);
801 0         0 print STDERR "While deparsing $file near line $line,\n";
802             }
803 8     8   50 use Data::Printer;
  8         13  
  8         68  
804 0         0 my @bt = caller(1);
805 0         0 p @bt;
806 0         0 };
807 0         0 $self->{'curcv'} = main_cv;
808 0         0 $self->{'curcvlex'} = undef;
809 0         0 print $self->extract_prototypes;
810 0         0 @{$self->{'subs_todo'}} =
811 0         0 sort {$a->[0] <=> $b->[0]} @{$self->{'subs_todo'}};
  0         0  
  0         0  
812 0         0 my $root = main_root;
813 0         0 local $B::overlay = {};
814              
815 0 0       0 if ($] < 5.021) {
816 0 0       0 unless (B::Deparse::null $root) {
817 0         0 $self->pessimise($root, main_start);
818             # Print deparsed program
819 0         0 print $self->deparse_root($root)->{text}, "\n";
820             }
821             } else {
822 0 0       0 unless (B::Deparse::null $root) {
823 0         0 $self->B::Deparse::pad_subs($self->{'curcv'});
824             # Check for a stub-followed-by-ex-cop, resulting from a program
825             # consisting solely of sub declarations. For backward-compati-
826             # bility (and sane output) we don’t want to emit the stub.
827             # leave
828             # enter
829             # stub
830             # ex-nextstate (or ex-dbstate)
831 0         0 my $kid;
832 0 0 0     0 if ( $root->name eq 'leave'
      0        
      0        
      0        
      0        
      0        
      0        
833             and ($kid = $root->first)->name eq 'enter'
834             and !B::Deparse::null($kid = $kid->sibling) and $kid->name eq 'stub'
835             and !B::Deparse::null($kid = $kid->sibling) and $kid->name eq 'null'
836             and class($kid) eq 'COP' and B::Deparse::null $kid->sibling )
837             {
838             # ignore deparsing routine
839             } else {
840 0         0 $self->pessimise($root, main_start);
841             # Print deparsed program
842 0         0 my $root_tree = $self->deparse_root($root);
843 0         0 print $root_tree->{text}, "\n";
844             }
845             }
846             }
847 0         0 my @text;
848 0         0 while (scalar(@{$self->{'subs_todo'}})) {
  0         0  
849 0         0 push @text, $self->next_todo->{text};
850             }
851 0 0       0 print join("", @text), "\n" if @text;
852              
853             # Print __DATA__ section, if necessary
854 8     8   2371 no strict 'refs';
  8         15  
  8         22663  
855             my $laststash = defined $self->{'curcop'}
856 0 0       0 ? $self->{'curcop'}->stash->NAME : $self->{'curstash'};
857 0 0       0 if (defined *{$laststash."::DATA"}{IO}) {
  0         0  
858             print $self->keyword("package") . " $laststash;\n"
859 0 0       0 unless $laststash eq $self->{'curstash'};
860 0         0 print $self->keyword("__DATA__") . "\n";
861 0         0 print readline(*{$laststash."::DATA"});
  0         0  
862             }
863             }
864 0         0 }
865              
866             # "deparse()" is the main function to call to produces a depare tree
867             # for a give B::OP. This method is the inner loop.
868              
869             # Rocky's comment with respect to:
870             # so try to keep it simple
871             #
872             # Most normal Perl programs really aren't that big. Yeah, I know there
873             # are a couple of big pigs like the B::Deparse code itself. The perl5
874             # debugger comes to mind too. But what's the likelihood of anyone wanting
875             # to decompile all of this?
876             #
877             # On the other hand, error checking is too valuable to throw out here.
878             # Also, in trying to use and modularize this code, I see there is
879             # a lot of repetition in subroutine parsing routines. That's
880             # why I added the above PP_MAPFNS table. I'm not going to trade off
881             # table lookup and interpetation for a huge amount of subroutine
882             # bloat.
883              
884             # That said it is useful to note that this is inner-most loop
885             # interpeter loop as it is called for each node in the B::OP tree.
886             #
887             sub deparse
888             {
889 19281     19281 0 32811 my($self, $op, $cx, $parent) = @_;
890              
891 19281 50       50465 Carp::confess("deparse called on an invalid op $op")
892             unless $op->can('name');
893              
894 19281         54475 my $name = $op->name;
895 19281 50       37065 print "YYY $name\n" if $ENV{'DEBUG_DEPARSETREE'};
896 19281         23002 my ($info, $meth);
897              
898 19281 100       33014 if (exists($PP_MAPFNS{$name})) {
899             # Interpret method calls for our PP_MAPFNS table
900 4092 100       8429 if (ref($PP_MAPFNS{$name}) eq 'ARRAY') {
901 1664         2388 my @args = @{$PP_MAPFNS{$name}};
  1664         4742  
902 1664         2924 $meth = shift @args;
903 1664 100       3384 if ($meth eq 'maybe_targmy') {
904             # FIXME: This is an inline version of targmy.
905             # Can we dedup it? do we want to?
906 231         345 $meth = shift @args;
907 231 100       547 unshift @args, $name unless @args;
908 231 100       843 if ($op->private & OPpTARGET_MY) {
909 4         33 my $var = $self->padname($op->targ);
910 4         13 my $val = $self->$meth($op, 7, @args);
911 4         9 my @texts = ($var, '=', $val);
912 4         18 $info = $self->info_from_template("my", $op,
913             "%c = %c", [0, 1],
914             [$var, $val],
915             {maybe_parens => [$self, $cx, 7]});
916             } else {
917 227         988 $info = $self->$meth($op, $cx, @args);
918             }
919             } else {
920 1433         5846 $info = $self->$meth($op, $cx, @args);
921             }
922             } else {
923             # Simple case: one simple call of the
924             # the method in the table. Call this
925             # passing arguments $op, $cx, and $name.
926             # Some functions might not use these,
927             # but that's okay.
928 2428         3859 $meth = $PP_MAPFNS{$name};
929 2428         9425 $info = $self->$meth($op, $cx, $name);
930             }
931             } else {
932             # Tried and true fallback method:
933             # a method has been defined for this pp_op special.
934             # call that.
935 15189         19603 $meth = "pp_" . $name;
936 15189         43048 $info = $self->$meth($op, $cx);
937             }
938              
939 19281 50       37520 Carp::confess("nonref return for $meth deparse: $info") if !ref($info);
940 19281 50       45981 Carp::confess("not B::DeparseTree:Node returned for $meth: $info")
941             if !$info->isa("B::DeparseTree::TreeNode");
942 19281 100       40489 $info->{parent} = $$parent if $parent;
943 19281         29365 $info->{cop} = $self->{'curcop'};
944 19281         24195 my $got_op = $info->{op};
945 19281 100       26728 if ($got_op) {
946 19212 100       33797 if ($got_op != $op) {
947             # Do something here?
948             # printf("XX final op 0x%x is not requested 0x%x\n",
949             # $$op, $$got_op);
950             }
951             } else {
952 69         90 $info->{op} = $op;
953             }
954 19281         46415 $self->{optree}{$$op} = $info;
955 19281 100       31030 if ($info->{other_ops}) {
956 4183         4887 foreach my $other (@{$info->{other_ops}}) {
  4183         7516  
957 8884 50       24387 if (!ref $other) {
    100          
958 0         0 Carp::confess "$meth returns invalid other $other";
959             } elsif ($other->isa("B::DeparseTree::TreeNode")) {
960             # "$other" has been set up to mark a particular portion
961             # of the info.
962 5501         9862 $self->{optree}{$other->{addr}} = $other;
963 5501         9665 $other->{parent} = $$op;
964             } else {
965             # "$other" is just the OP. Have it mark everything
966             # or "info".
967 3383         9796 $self->{optree}{$$other} = $info;
968             }
969             }
970             }
971 19281         41235 return $info;
972             }
973              
974             # Deparse a subroutine
975             sub deparse_sub($$$$)
976             {
977 1330     1330 0 2916 my ($self, $cv, $start_op) = @_;
978              
979             # Sanity checks..
980 1330 50 33     10288 Carp::confess("NULL in deparse_sub") if !defined($cv) || $cv->isa("B::NULL");
981 1330 50       5267 Carp::confess("SPECIAL in deparse_sub") if $cv->isa("B::SPECIAL");
982              
983             # First get protype and sub attribute information
984 1330         3868 local $self->{'curcop'} = $self->{'curcop'};
985 1330         2434 my $proto = '';
986 1330 50       5044 if ($cv->FLAGS & SVf_POK) {
987 0         0 $proto .= "(". $cv->PV . ")";
988             }
989 1330 100       4857 if ($cv->CvFLAGS & (CVf_METHOD|CVf_LOCKED|CVf_LVALUE)) {
990 2         12 $proto .= ":";
991 2 100       10 $proto .= " lvalue" if $cv->CvFLAGS & CVf_LVALUE;
992 2 50       7 $proto .= " locked" if $cv->CvFLAGS & CVf_LOCKED;
993 2 100       8 $proto .= " method" if $cv->CvFLAGS & CVf_METHOD;
994             }
995              
996 1330         3568 local($self->{'curcv'}) = $cv;
997 1330         3392 local($self->{'curcvlex'});
998             local(@$self{qw'curstash warnings hints hinthash'})
999 1330         5687 = @$self{qw'curstash warnings hints hinthash'};
1000              
1001             # Now deparse subroutine body
1002              
1003 1330         4840 my $root = $cv->ROOT;
1004 1330         2533 my ($body, $node);
1005              
1006 1330         2571 local $B::overlay = {};
1007 1330 50       14255 if (not B::Deparse::null $root) {
1008 1330         7290 $self->pessimise($root, $cv->START);
1009 1330         5972 my $lineseq = $root->first;
1010 1330 50       5088 if ($lineseq->name eq "lineseq") {
    0          
1011 1330         2050 my @ops;
1012 1330         5758 for(my $o=$lineseq->first; $$o; $o=$o->sibling) {
1013 4148         13631 push @ops, $o;
1014             }
1015 1330         4142 $body = $self->lineseq($root, 0, @ops);
1016 1330         38848 my $scope_en = $self->find_scope_en($lineseq);
1017             }
1018             elsif ($start_op) {
1019 0         0 $body = $self->deparse($start_op, 0, $lineseq);
1020             } else {
1021 0         0 $body = $self->deparse($root->first, 0, $lineseq);
1022             }
1023              
1024 1330         7911 my $fn_name = $cv->GV->NAME;
1025 1330         8710 $node = $self->info_from_template("sub $fn_name$proto",
1026             $lineseq,
1027             "$proto\n%|{\n%+%c\n%-}",
1028             [0], [$body]);
1029 1330         3682 $body->{parent} = $$lineseq;
1030 1330         4733 $self->{optree}{$$lineseq} = $node;
1031              
1032             } else {
1033 0         0 my $sv = $cv->const_sv;
1034 0 0       0 if ($$sv) {
1035             # uh-oh. inlinable sub... format it differently
1036 0         0 $node = $self->info_from_template('inline sub', $sv,
1037             "$proto\n%|{\n%+%c\n%-}",
1038             [0], [$self->const($sv, 0)]);
1039             } else {
1040             # XSUB? (or just a declaration)
1041 0         0 $node = $self->info_from_string("XSUB or sub declaration", $proto);
1042             }
1043             }
1044              
1045              
1046             # Should we create a real node for this instead of the copy?
1047 1330         4174 $self->{optree}{$$root} = $node;
1048              
1049             # Add additional DeparseTree tracking info
1050 1330 50       2989 if ($start_op) {
1051 0         0 $node->{op} = $start_op;
1052 0         0 $self->{'optree'}{$$start_op} = $node;
1053             }
1054 1330         2831 $node->{cop} = undef;
1055 1330         2201 $node->{'parent'} = $cv;
1056 1330         36575 return $node;
1057             }
1058              
1059             # We have a TODO list of things that must be handled
1060             # at the top level. There are things like
1061             # format statements, "BEGIN" and "use" statements.
1062             # Here we handle the next one.
1063             sub next_todo
1064             {
1065 0     0 0 0 my ($self, $parent) = @_;
1066 0         0 my $ent = shift @{$self->{'subs_todo'}};
  0         0  
1067 0         0 my ($seq, $cv, $is_form, $name) = @$ent;
1068              
1069             # any 'use strict; package foo' that should come before the sub
1070             # declaration to sync with the first COP of the sub
1071              
1072             ## FIXME: $self->pragmata messes scoping up, although I don't know
1073             ## how it does that.
1074             # my $pragmata = '';
1075             # if ($cv and !B::Deparse::null($cv->START) and B::Deparse::is_state($cv->START)) {
1076             # $pragmata = $self->B::Deparse::pragmata($cv->START);
1077             # }
1078              
1079             # if (ref $name) { # lexical sub
1080             # # emit the sub.
1081             # my @text;
1082             # my $flags = $name->FLAGS;
1083             # push @text,
1084             # !$cv || $seq <= $name->COP_SEQ_RANGE_LOW
1085             # ? $self->keyword($flags & B::SVpad_OUR
1086             # ? "our"
1087             # : $flags & SVpad_STATE
1088             # ? "state"
1089             # : "my") . " "
1090             # : "";
1091             # # XXX We would do $self->keyword("sub"), but ‘my CORE::sub’
1092             # # doesn’t work and ‘my sub’ ignores a &sub in scope. I.e.,
1093             # # we have a core bug here.
1094             # push @text, "sub " . substr $name->PVX, 1;
1095             # my $text = join('', @text);
1096             # if ($cv) {
1097             # # my sub foo { }
1098             # my $cv_node = $self->deparse_sub($cv);
1099             # my $fmt = sprintf("%s%s%%c", $pragmata, $text);
1100             # return $self->info_from_template("sub", $cv,
1101             # $fmt, undef,
1102             # [$cv_node]);
1103             # } else {
1104             # return $self->info_from_string("sub no body", $cv, $text);
1105             # }
1106             # }
1107              
1108 0         0 my $gv = $cv->GV;
1109 0   0     0 $name //= $self->gv_name($gv);
1110 0 0       0 if ($is_form) {
1111 0         0 my $node = $self->deparse_format($ent->[1], $cv);
1112 0         0 return $self->info_from_template("format $name",
1113             "format $name = %c",
1114             undef, [$node])
1115             } else {
1116 0         0 my ($fmt, $type);
1117 0         0 $self->{'subs_declared'}{$name} = 1;
1118 0 0       0 if ($name eq "BEGIN") {
1119 0         0 my $use_dec = $self->begin_is_use($cv);
1120 0 0 0     0 if (defined ($use_dec) and $self->{'expand'} < 5) {
1121 0 0       0 if (0 == length($use_dec)) {
1122 0         0 $self->info_from_string('BEGIN', $cv, '');
1123             } else {
1124 0         0 $self->info_from_string('use', $cv, $use_dec);
1125             }
1126             }
1127             }
1128 0         0 my $l = '';
1129 0 0       0 if ($self->{'linenums'}) {
1130 0         0 my $line = $gv->LINE;
1131 0         0 my $file = $gv->FILE;
1132 0         0 $l = "\n# line $line \"$file\"\n";
1133             }
1134 0 0       0 if (class($cv->STASH) ne "SPECIAL") {
1135 0         0 my $stash = $cv->STASH->NAME;
1136 0 0       0 if ($stash ne $self->{'curstash'}) {
1137 0         0 $fmt = "package $stash;\n";
1138 0         0 $type = "package $stash";
1139 0 0       0 $name = "$self->{'curstash'}::$name" unless $name =~ /::/;
1140 0         0 $self->{'curstash'} = $stash;
1141             }
1142 0         0 $name =~ s/^\Q$stash\E::(?!\z|.*::)//;
1143 0         0 $fmt .= "sub $name";
1144 0         0 $type .= "sub $name";
1145             }
1146 0         0 my $node = $self->deparse_sub($cv, $parent);
1147 0         0 $fmt .= '%c';
1148 0         0 my $sub_node = $self->info_from_template($type, $cv, $fmt, [0], [$node]);
1149 0         0 $node->{parent} = $sub_node->{addr};
1150 0         0 $self->{optree}{$$cv} = $sub_node;
1151 0         0 return $sub_node;
1152             }
1153             }
1154              
1155             # Deparse a subroutine by name
1156             sub deparse_subname($$)
1157             {
1158 0     0 0 0 my ($self, $funcname) = @_;
1159 0         0 my $cv = svref_2object(\&$funcname);
1160 0         0 my $info = $self->deparse_sub($cv);
1161 0         0 my $sub_node = $self->info_from_template("sub $funcname", $cv, "sub $funcname %c",
1162             undef, [$info]);
1163 0         0 $self->{optree}{$$cv} = $sub_node;
1164 0         0 return $sub_node;
1165             }
1166              
1167             # Return a list of info nodes for "use" and "no" pragmas.
1168             sub declare_hints
1169             {
1170 1321     1321 0 3016 my ($self, $from, $to) = @_;
1171 1321         2558 my $use = $to & ~$from;
1172 1321         2164 my $no = $from & ~$to;
1173              
1174 1321         2142 my @decls = ();
1175 1321         20656 for my $pragma (B::Deparse::hint_pragmas($use)) {
1176 1266         27849 my $type = $self->keyword("use") . " $pragma";
1177 1266         6353 push @decls, $self->info_from_template($type, undef, "$type", [], []);
1178             }
1179 1321         8720 for my $pragma (B::Deparse::hint_pragmas($no)) {
1180 0         0 my $type = $self->keyword("no") . " $pragma";
1181 0         0 push @decls, $self->info_from_template($type, undef, "$type", [], []);
1182             }
1183 1321         3754 return @decls;
1184             }
1185              
1186             # Internal implementation hints that the core sets automatically, so don't need
1187             # (or want) to be passed back to the user
1188             my %ignored_hints = (
1189             'open<' => 1,
1190             'open>' => 1,
1191             ':' => 1,
1192             'strict/refs' => 1,
1193             'strict/subs' => 1,
1194             'strict/vars' => 1,
1195             );
1196              
1197             my %rev_feature;
1198              
1199             sub declare_hinthash {
1200 2087     2087 0 4615 my ($self, $from, $to, $indent, $hints) = @_;
1201 2087         2859 my $doing_features;
1202 2087 50       3544 if ($] >= 5.016) {
1203 2087         3456 $doing_features = ($hints & $feature::hint_mask) == $feature::hint_mask;
1204             } else {
1205 0         0 $doing_features = 0;
1206             }
1207 2087         4249 my @decls;
1208             my @features;
1209 2087         0 my @unfeatures; # bugs?
1210 2087         7827 for my $key (sort keys %$to) {
1211 67 50       109 next if $ignored_hints{$key};
1212 67   33     406 my $is_feature = $key =~ /^feature_/ && $^V ge 5.15.6;
1213 67 100 66     226 next if $is_feature and not $doing_features;
1214 54 100 66     161 if (!exists $from->{$key} or $from->{$key} ne $to->{$key}) {
1215 12 50       16 if ($is_cperl){
1216 0 0       0 next if $key eq 'feature_lexsubs';
1217 0 0       0 next if $key eq 'feature_signatures';
1218             }
1219 12 50       27 push(@features, $key), next if $is_feature;
1220             push @decls,
1221             qq(\$^H{) . single_delim($self, "q", "'", $key, "'") . qq(} = )
1222             . (
1223             defined $to->{$key}
1224 0 0       0 ? single_delim($self, "q", "'", $to->{$key}, "'")
1225             : 'undef'
1226             )
1227             . qq(;);
1228             }
1229             }
1230 2087         5169 for my $key (sort keys %$from) {
1231 55 50       85 next if $ignored_hints{$key};
1232 55   33     278 my $is_feature = $key =~ /^feature_/ && $^V ge 5.15.6;
1233 55 100 66     178 next if $is_feature and not $doing_features;
1234 42 50       100 if (!exists $to->{$key}) {
1235 0 0       0 push(@unfeatures, $key), next if $is_feature;
1236 0         0 push @decls, qq(delete \$^H{'$key'};);
1237             }
1238             }
1239 2087         2892 my @ret;
1240 2087 100 66     7598 if (@features || @unfeatures) {
1241 3 100       8 if (!%rev_feature) { %rev_feature = reverse %feature::feature }
  1         7  
1242             }
1243 2087 100       4139 if (@features) {
1244 3         1141 push @ret, $self->keyword("use") . " feature "
1245             . join(", ", map "'$rev_feature{$_}'", @features) . ";\n";
1246             }
1247 2087 50       3805 if (@unfeatures) {
1248 0         0 push @ret, $self->keyword("no") . " feature "
1249             . join(", ", map "'$rev_feature{$_}'", @unfeatures)
1250             . ";\n";
1251             }
1252             @decls and
1253 2087 50       3703 push @ret,
1254             join("\n" . (" " x $indent), "BEGIN {", @decls) . "\n}\n";
1255 2087         5293 return @ret;
1256             }
1257              
1258             # generate any pragmas, 'package foo' etc needed to synchronise
1259             # with the given cop
1260              
1261             sub pragmata {
1262 0     0 0 0 my $self = shift;
1263 0         0 my($op) = @_;
1264              
1265 0         0 my @text;
1266              
1267 0         0 my $stash = $op->stashpv;
1268 0 0       0 if ($stash ne $self->{'curstash'}) {
1269 0         0 push @text, $self->keyword("package") . " $stash;\n";
1270 0         0 $self->{'curstash'} = $stash;
1271             }
1272              
1273 0         0 if (OPpCONST_ARYBASE && $self->{'arybase'} != $op->arybase) {
1274             push @text, '$[ = '. $op->arybase .";\n";
1275             $self->{'arybase'} = $op->arybase;
1276             }
1277              
1278 0         0 my $warnings = $op->warnings;
1279 0         0 my $warning_bits;
1280 0 0 0     0 if ($warnings->isa("B::SPECIAL") && $$warnings == 4) {
    0 0        
    0          
1281 0         0 $warning_bits = $warnings::Bits{"all"} & WARN_MASK;
1282             }
1283             elsif ($warnings->isa("B::SPECIAL") && $$warnings == 5) {
1284 0         0 $warning_bits = $warnings::NONE;
1285             }
1286             elsif ($warnings->isa("B::SPECIAL")) {
1287 0         0 $warning_bits = undef;
1288             }
1289             else {
1290 0         0 $warning_bits = $warnings->PV & WARN_MASK;
1291             }
1292              
1293 0 0 0     0 if (defined ($warning_bits) and
      0        
1294             !defined($self->{warnings}) || $self->{'warnings'} ne $warning_bits) {
1295             push @text,
1296 0         0 $self->declare_warnings($self->{'warnings'}, $warning_bits);
1297 0         0 $self->{'warnings'} = $warning_bits;
1298             }
1299              
1300 0 0       0 my $hints = $] < 5.008009 ? $op->private : $op->hints;
1301 0         0 my $old_hints = $self->{'hints'};
1302 0 0       0 if ($self->{'hints'} != $hints) {
1303 0         0 push @text, $self->declare_hints($self->{'hints'}, $hints);
1304 0         0 $self->{'hints'} = $hints;
1305             }
1306              
1307 0         0 my $newhh;
1308 0 0       0 if ($] > 5.009) {
1309 0         0 $newhh = $op->hints_hash->HASH;
1310             }
1311              
1312 0 0       0 if ($] >= 5.015006) {
1313             # feature bundle hints
1314 0         0 my $from = $old_hints & $feature::hint_mask;
1315 0         0 my $to = $ hints & $feature::hint_mask;
1316 0 0       0 if ($from != $to) {
1317 0 0       0 if ($to == $feature::hint_mask) {
1318 0 0       0 if ($self->{'hinthash'}) {
1319             delete $self->{'hinthash'}{$_}
1320 0         0 for grep /^feature_/, keys %{$self->{'hinthash'}};
  0         0  
1321             }
1322 0         0 else { $self->{'hinthash'} = {} }
1323             $self->{'hinthash'}
1324 0         0 = _features_from_bundle($from, $self->{'hinthash'});
1325             }
1326             else {
1327 0         0 my $bundle =
1328             $feature::hint_bundles[$to >> $feature::hint_shift];
1329 0         0 $bundle =~ s/(\d[13579])\z/$1+1/e; # 5.11 => 5.12
  0         0  
1330 0         0 push @text,
1331             $self->keyword("no") . " feature ':all';\n",
1332             $self->keyword("use") . " feature ':$bundle';\n";
1333             }
1334             }
1335             }
1336              
1337 0 0       0 if ($] > 5.009) {
1338             push @text, $self->declare_hinthash(
1339             $self->{'hinthash'}, $newhh,
1340             $self->{indent_size}, $self->{hints},
1341 0         0 );
1342 0         0 $self->{'hinthash'} = $newhh;
1343             }
1344              
1345 0         0 return join("", @text);
1346             }
1347              
1348              
1349             # Create a "use", "no", or "BEGIN" block to set warnings.
1350             sub declare_warnings
1351             {
1352 1266     1266 0 3028 my ($self, $from, $to) = @_;
1353 1266 100       3257 if (($to & WARN_MASK) eq (warnings::bits("all") & WARN_MASK)) {
    50          
1354 2         1011 my $type = $self->keyword("use") . " warnings";
1355 2         26 return $self->info_from_string($type, undef, "$type");
1356             }
1357             elsif (($to & WARN_MASK) eq ("\0"x length($to) & WARN_MASK)) {
1358 1264         26894 my $type = $self->keyword("no") . " warnings";
1359 1264         6122 return $self->info_from_string($type, undef, "$type");
1360             }
1361 0         0 my $bit_expr = join('', map { sprintf("\\x%02x", ord $_) } split "", $to);
  0         0  
1362 0         0 my $str = "BEGIN {\n%+\${^WARNING_BITS} = \"$bit_expr;\n%-";
1363 0         0 return $self->info_from_template('warning bits begin', undef,
1364             "$str", [], [], {omit_next_semicolon=>1});
1365             }
1366              
1367             # Iterate over $self->{subs_todo} picking up the
1368             # text of of $self->next_todo.
1369             # We return an array of strings. The calling
1370             # routine will join these together
1371             sub seq_subs {
1372 2087     2087 0 4235 my ($self, $seq) = @_;
1373 2087         3053 my @texts;
1374              
1375 2087 50       3872 return () if !defined $seq;
1376 2087         2713 my @pending;
1377 2087   33     2804 while (scalar(@{$self->{'subs_todo'}})
  2087         6161  
1378             and $seq > $self->{'subs_todo'}[0][0]) {
1379 0         0 my $cv = $self->{'subs_todo'}[0][1];
1380             # Skip the OUTSIDE check for lexical subs. We may be deparsing a
1381             # cloned anon sub with lexical subs declared in it, in which case
1382             # the OUTSIDE pointer points to the anon protosub.
1383 0         0 my $lexical = ref $self->{'subs_todo'}[0][3];
1384 0   0     0 my $outside = !$lexical && $cv && $cv->OUTSIDE;
1385 0 0 0     0 if (!$lexical and $cv
      0        
1386 0 0       0 and ${$cv->OUTSIDE || \0} != ${$self->{'curcv'}})
  0         0  
1387             {
1388             # rocky: What do we do with @pending?
1389 0         0 push @pending, shift @{$self->{'subs_todo'}};
  0         0  
1390 0         0 next;
1391             }
1392 0         0 push @texts, $self->next_todo;
1393             }
1394 2087         5078 return @texts;
1395             }
1396              
1397             # FIXME: this code has to be here. Find out why and fix.
1398             # Truncate is special because OPf_SPECIAL makes a bareword first arg
1399             # be a filehandle. This could probably be better fixed in the core
1400             # by moving the GV lookup into ck_truc.
1401              
1402             # Demo code
1403             unless(caller) {
1404             my @texts = ('a', 'b', 'c');
1405             my $deparse = __PACKAGE__->new();
1406             my $info = info_from_list('op', $deparse, \@texts, ', ', 'test', {});
1407              
1408 8     8   84 use Data::Printer;
  8         55  
  8         40  
1409             my $str = $deparse->template_engine("%c", [0], ["16"]);
1410             p $str;
1411             my $str2 = $deparse->template_engine("%F", [[0, sub {'0x' . sprintf "%x", shift}]], [$str]);
1412             p $str2;
1413              
1414             # print $deparse->template_engine("100%% "), "\n";
1415             # print $deparse->template_engine("%c,\n%+%c\n%|%c %c!",
1416             # [1, 0, 2, 3],
1417             # ["is", "now", "the", "time"]), "\n";
1418              
1419             # $info = $deparse->info_from_template("demo", undef, "%C",
1420             # [[0, 1, ";\n%|"]],
1421             # ['$x=1', '$y=2']);
1422              
1423             # @texts = ("use warnings;", "use strict", "my(\$a)");
1424             # $info = $deparse->info_from_template("demo", undef, "%;", [], \@texts);
1425              
1426             # $info = $deparse->info_from_template("list", undef,
1427             # "%C", [[0, $#texts, ', ']],
1428             # \@texts);
1429              
1430             # p $info;
1431              
1432              
1433             # @texts = (['a', 1], ['b', 2], 'c');
1434             # $info = info_from_list('op', $deparse, \@texts, ', ', 'test', {});
1435             # p $info;
1436             }
1437              
1438             1;