File Coverage

lib/B/DeparseTree/TreeMain.pm
Criterion Covered Total %
statement 330 661 49.9
branch 123 344 35.7
condition 31 122 25.4
subroutine 39 50 78.0
pod 2 25 8.0
total 525 1202 43.6


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   47 use strict; use warnings;
  8     8   15  
  8         210  
  8         37  
  8         17  
  8         463  
20              
21             package B::DeparseTree;
22              
23 8         1062 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   48 );
  8         15  
41              
42 8     8   48 use Carp;
  8         15  
  8         447  
43 8     8   59 use B::Deparse;
  8         48  
  8         201  
44 8     8   3263 use B::DeparseTree::OPflags;
  8         21  
  8         439  
45 8     8   3232 use B::DeparseTree::PP_OPtable;
  8         39  
  8         899  
46 8     8   3378 use B::DeparseTree::SyntaxTree;
  8         28  
  8         1975  
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   59 use Config;
  8         18  
  8         1837  
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   489 BEGIN { map($globalnames{$_}++, "SIG", "STDIN", "STDOUT", "STDERR", "INC",
113             "ENV", "ARGV", "ARGVOUT", "_"); }
114              
115             my $max_prec;
116 8     8   624 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   36 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         210 eval { import B $_ };
  120         9870  
128 8     8   55 no strict 'refs';
  8         20  
  8         627  
129 120 100       239 *{$_} = sub () {0} unless *{$_}{CODE};
  24         97  
  120         4084  
130             }
131             }
132              
133             sub new {
134 10     10 1 750929 my $class = shift;
135 10         39 my $self = bless {}, $class;
136 10         167 $self->{'cuddle'} = " "; #\n%| is another alternative
137 10         42 $self->{'curcop'} = undef;
138 10         41 $self->{'curstash'} = "main";
139 10         37 $self->{'ex_const'} = "'?unrecoverable constant?'";
140 10         34 $self->{'expand'} = 0;
141 10         36 $self->{'files'} = {};
142              
143             # How many spaces per indent nesting?
144 10         35 $self->{'indent_size'} = 4;
145              
146 10         40 $self->{'opaddr'} = 0;
147 10         35 $self->{'linenums'} = 0;
148 10         35 $self->{'parens'} = 0;
149 10         39 $self->{'subs_todo'} = [];
150 10         33 $self->{'unquote'} = 0;
151 10         29 $self->{'use_dumper'} = 0;
152              
153             # Compress spaces with tabs? 1 tab = 8 spaces
154 10         25 $self->{'use_tabs'} = 0;
155              
156             # Indentation level
157 10         25 $self->{'level'} = 0;
158              
159 10         40 $self->{'ambient_arybase'} = 0;
160 10         21 $self->{'ambient_warnings'} = undef; # Assume no lexical warnings
161 10         27 $self->{'ambient_hints'} = 0;
162 10         32 $self->{'ambient_hinthash'} = undef;
163              
164             # Given an opcode address, get the accumulated OP tree
165             # OP for that. FIXME: remove this
166 10         30 $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         31 $self->{'last_fake_addr'} = 0;
171              
172 10         55 $self->init();
173              
174 10         44 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         34 return $self;
198             }
199              
200             {
201             # Mask out the bits that L uses
202             my $WARN_MASK;
203             BEGIN {
204 8     8   1616 $WARN_MASK = $warnings::Bits{all} | $warnings::DeadBits{all};
205             }
206             sub WARN_MASK () {
207 5184     5184 0 27479 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 2668 my $self = shift;
216              
217 1402         3224 $self->{'arybase'} = $self->{'ambient_arybase'};
218             $self->{'warnings'} = defined ($self->{'ambient_warnings'})
219 1402 100       3695 ? $self->{'ambient_warnings'} & WARN_MASK
220             : undef;
221 1402         2363 $self->{'hints'} = $self->{'ambient_hints'};
222 1402 50       3263 $self->{'hints'} &= 0xFF if $] < 5.009;
223 1402         2197 $self->{'hinthash'} = $self->{'ambient_hinthash'};
224              
225             # also a convenient place to clear out subs_declared
226 1402         2967 delete $self->{'subs_declared'};
227             }
228              
229             BEGIN {
230 8     8   35 for (qw[ pushmark ])
231             {
232 8         8357 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 1083936 my ($self, $coderef, $start_op) = @_;
247 1328         5539 my $cv = svref_2object ( $coderef );
248 1328         4617 my $gv = $cv->GV;
249 1328 50       5614 if ($gv->NAME eq 'main') {
250 0         0 return $self->main2info();
251             } else {
252 1328 50       5032 croak "Usage: ->coderef2info(CODEREF)"
253             unless UNIVERSAL::isa($coderef, "CODE");
254 1328         4375 $self->init();
255 1328         4118 return $self->deparse_sub($cv, $start_op);
256             }
257             }
258              
259             sub coderef2text
260             {
261 64     64 1 125635 my ($self, $func) = @_;
262 64         134 my $info;
263 64 50       238 if ($func eq 'main::main') {
264 0         0 $info = $self->main2info();
265             } else {
266 64 50       277 croak "Usage: ->coderef2text(CODEREF)" unless UNIVERSAL::isa($func, "CODE");
267 64         242 $self->init();
268 64         199 $info = $self->coderef2info($func);
269             }
270 64         219 return $self->info2str($info);
271             }
272              
273             sub const {
274 91     91 0 162 my $self = shift;
275 91         198 my($sv, $cx) = @_;
276 91 50       261 if ($self->{'use_dumper'}) {
277 0         0 return $self->const_dumper($sv, $cx);
278             }
279 91 50       707 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       559 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       409 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     499 if ($sv->FLAGS & SVf_IOK) {
    50          
    50          
    50          
298 62         329 my $str = $sv->int_value;
299 62 50       194 $str = $self->maybe_parens($str, $cx, 21) if $str < 0;
300 62         302 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   72 if ($] > 5.0150051) {
376 8         86 require overloading;
377 8         17773 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         71 my $str = $sv->PV;
409 29 50       90 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         245 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 4344 my ($self, $node, $prev_expr, $op) = @_;
481 2101         3493 $node->{prev_expr} = $prev_expr;
482 2101         3265 my $addr = $prev_expr->{addr};
483 2101 100 66     9418 if ($addr && ! exists $self->{optree}{$addr}) {
484 4 50       18 $self->{optree}{$addr} = $node if $op;
485             }
486             }
487              
488             sub walk_lineseq
489             {
490 1342     1342 0 3008 my ($self, $op, $kids, $callback) = @_;
491 1342         2654 my @kids = @$kids;
492 1342         2320 my @body = (); # Accumulated node structures
493 1342         1667 my $expr;
494 1342         1859 my $prev_expr = undef;
495 1342         1847 my $fix_cop = undef;
496 1342         3326 for (my $i = 0; $i < @kids; $i++) {
497 2088 100       13735 if (B::Deparse::is_state $kids[$i]) {
498 2087         5817 $expr = ($self->deparse($kids[$i], 0, $op));
499 2087         6236 $callback->(\@body, $i, $expr, $op);
500 2087         3267 $prev_expr = $expr;
501 2087 50       3759 if ($fix_cop) {
502 0         0 $fix_cop->{text} = $expr->{text};
503             }
504 2087         2800 $i++;
505 2087 50       4315 if ($i > $#kids) {
506 0         0 last;
507             }
508             }
509 2088 50       38684 if (B::Deparse::is_for_loop($kids[$i])) {
510 0         0 my $loop_expr = $self->for_loop($kids[$i], 0);
511 0 0       0 $callback->(\@body,
512             $i += $kids[$i]->sibling->name eq "unstack" ? 2 : 1,
513             $loop_expr);
514 0         0 $prev_expr = $expr;
515 0         0 next;
516             }
517 2088         7778 $expr = $self->deparse($kids[$i], (@kids != 1)/2, $op);
518              
519             # Perform semantic action on $expr accumulating the result
520             # in @body. $op is the parent, and $i is the child position
521 2088         6187 $callback->(\@body, $i, $expr, $op);
522 2088 100       4604 unless (exists $expr->{prev_expr}) {
523 759         2047 $self->update_node($expr, $prev_expr, $op);
524             }
525 2088         2891 $prev_expr = $expr;
526 2088 50       3868 if ($fix_cop) {
527 0         0 $fix_cop->{text} = $expr->{text};
528             }
529              
530             # If the text portion of a COP is empty, set up to fill it in
531             # from the text portion of the next node.
532 2088 50 33     17245 if (B::class($op) eq "COP" && !$expr->{text}) {
533 0         0 $fix_cop = $op;
534             } else {
535 2088         6684 $fix_cop = undef;
536             }
537             }
538              
539             # Add semicolons between statements. Don't null statements
540             # (which can happen for nexstate which doesn't have source code
541             # associated with it.
542 1342         4815 $expr = $self->info_from_template("statements", $op, "%;", [], \@body);
543 1342         4453 $self->update_node($expr, $prev_expr, $op);
544 1342         12047 return $expr;
545             }
546              
547             # $root should be the op which represents the root of whatever
548             # we're sequencing here. If it's undefined, then we don't append
549             # any subroutine declarations to the deparsed ops, otherwise we
550             # append appropriate declarations.
551             sub lineseq {
552 1342     1342 0 4035 my($self, $root, $cx, @ops) = @_;
553              
554 1342         2663 my $out_cop = $self->{'curcop'};
555 1342 100       2846 my $out_seq = defined($out_cop) ? $out_cop->cop_seq : undef;
556 1342         1825 my $limit_seq;
557 1342 50       2932 if (defined $root) {
558 1342         1994 $limit_seq = $out_seq;
559 1342         1656 my $nseq;
560 1342 50       1783 $nseq = $self->find_scope_st($root->sibling) if ${$root->sibling};
  1342         5493  
561 1342 100 33     4448 $limit_seq = $nseq if !defined($limit_seq)
      66        
562             or defined($nseq) && $nseq < $limit_seq;
563             }
564             $limit_seq = $self->{'limit_seq'}
565             if defined($self->{'limit_seq'})
566 1342 50 33     3118 && (!defined($limit_seq) || $self->{'limit_seq'} < $limit_seq);
      66        
567 1342         2962 local $self->{'limit_seq'} = $limit_seq;
568              
569             my $fn = sub {
570 4175     4175   7335 my ($exprs, $i, $info, $parent) = @_;
571 4175         5935 my $op = $ops[$i];
572 4175 50       7772 $info->{type} = $op->name unless $info->{type};
573 4175         6381 $info->{child_pos} = $i;
574 4175         5880 $info->{op} = $op;
575 4175 50       7034 if ($parent) {
576 4175 50       7400 Carp::confess("nonref parent, op: $op->name") if !ref($parent);
577 4175         6281 $info->{parent} = $$parent ;
578             }
579              
580 4175         6527 $self->{optree}{$$op} = $info;
581              
582 4175         7757 push @$exprs, $info;
583 1342         7115 };
584 1342         4709 return $self->walk_lineseq($root, \@ops, $fn);
585             }
586              
587             # _pessimise_walk(): recursively walk the optree of a sub,
588             # possibly undoing optimisations along the way.
589             # walk tree in root-to-branch order
590             # We add parent pointers in the process.
591              
592             sub _pessimise_walk {
593 12558     12558   20361 my ($self, $startop) = @_;
594              
595 12558 50       19889 return unless $$startop;
596 12558         14810 my ($op, $parent_op);
597              
598 12558         21271 for ($op = $startop; $$op; $op = $op->sibling) {
599 24710         65066 my $ppname = $op->name;
600              
601 24710   50     113608 $self->{ops}{$$op} ||= {};
602 24710         42836 $self->{ops}{$$op}{op} = $op;
603 24710         34395 $self->{ops}{$$op}{parent_op} = $startop;
604              
605             # pessimisations start here
606              
607 24710 100       36875 if ($ppname eq "padrange") {
608             # remove PADRANGE:
609             # the original optimisation either (1) changed this:
610             # pushmark -> (various pad and list and null ops) -> the_rest
611             # or (2), for the = @_ case, changed this:
612             # pushmark -> gv[_] -> rv2av -> (pad stuff) -> the_rest
613             # into this:
614             # padrange ----------------------------------------> the_rest
615             # so we just need to convert the padrange back into a
616             # pushmark, and in case (1), set its op_next to op_sibling,
617             # which is the head of the original chain of optimised-away
618             # pad ops, or for (2), set it to sibling->first, which is
619             # the original gv[_].
620              
621 827         4932 $B::overlay->{$$op} = {
622             type => OP_PUSHMARK,
623             name => 'pushmark',
624             private => ($op->private & OPpLVAL_INTRO),
625             };
626             }
627              
628             # pessimisations end here
629              
630 24710 100 66     109515 if (class($op) eq 'PMOP'
      100        
      66        
631             && ref($op->pmreplroot)
632 24         96 && ${$op->pmreplroot}
633             && $op->pmreplroot->isa( 'B::OP' ))
634             {
635 4         13 $self-> _pessimise_walk($op->pmreplroot);
636             }
637              
638 24710 100       124690 if ($op->flags & OPf_KIDS) {
639 11224         36008 $self-> _pessimise_walk($op->first);
640             }
641              
642             }
643             }
644              
645              
646             # _pessimise_walk_exe(): recursively walk the op_next chain of a sub,
647             # possibly undoing optimisations along the way.
648             # walk tree in execution order
649              
650             sub _pessimise_walk_exe {
651 1469     1469   3274 my ($self, $startop, $visited) = @_;
652              
653 1469 100       3313 return unless $$startop;
654 1455 50       3963 return if $visited->{$$startop};
655 1455         2136 my $op;
656 1455         3680 for ($op = $startop; $$op; $op = $op->next) {
657 12891 100       25600 last if $visited->{$$op};
658 12770         19851 $visited->{$$op} = 1;
659              
660 12770   50     22276 $self->{ops}{$$op} ||= {};
661 12770         19198 $self->{ops}{$$op}{op} = $op;
662              
663 12770         31735 my $ppname = $op->name;
664 12770 100       75337 if ($ppname =~
    100          
    100          
665             /^((and|d?or)(assign)?|(map|grep)while|range|cond_expr|once)$/
666             # entertry is also a logop, but its op_other invariably points
667             # into the same chain as the main execution path, so we skip it
668             ) {
669 116         481 $self->_pessimise_walk_exe($op->other, $visited);
670             }
671             elsif ($ppname eq "subst") {
672 18         52 $self->_pessimise_walk_exe($op->pmreplstart, $visited);
673             }
674             elsif ($ppname =~ /^(enter(loop|iter))$/) {
675             # redoop and nextop will already be covered by the main block
676             # of the loop
677 5         22 $self->_pessimise_walk_exe($op->lastop, $visited);
678             }
679              
680             # pessimisations start here
681             }
682             }
683              
684             # Go through an optree and "remove" some optimisations by using an
685             # overlay to selectively modify or un-null some ops. Deparsing in the
686             # absence of those optimisations is then easier.
687             #
688             # Note that older optimisations are not removed, as Deparse was already
689             # written to recognise them before the pessimise/overlay system was added.
690              
691             sub pessimise {
692 1330     1330 0 2960 my ($self, $root, $start) = @_;
693              
694 8     8   64 no warnings 'recursion';
  8         21  
  8         6528  
695             # walk tree in root-to-branch order
696 1330         3942 $self->_pessimise_walk($root);
697              
698 1330         2348 my %visited;
699             # walk tree in execution order
700 1330         4037 $self->_pessimise_walk_exe($start, \%visited);
701             }
702              
703             sub style_opts
704             {
705 0     0 0 0 my ($self, $opts) = @_;
706 0         0 my $opt;
707 0         0 while (length($opt = substr($opts, 0, 1))) {
708 0 0       0 if ($opt eq "C") {
    0          
    0          
    0          
709 0         0 $self->{'cuddle'} = " ";
710 0         0 $opts = substr($opts, 1);
711             } elsif ($opt eq "i") {
712 0         0 $opts =~ s/^i(\d+)//;
713 0         0 $self->{'indent_size'} = $1;
714             } elsif ($opt eq "T") {
715 0         0 $self->{'use_tabs'} = 1;
716 0         0 $opts = substr($opts, 1);
717             } elsif ($opt eq "v") {
718 0         0 $opts =~ s/^v([^.]*)(.|$)//;
719 0         0 $self->{'ex_const'} = $1;
720             }
721             }
722             }
723              
724             # B::Deparse name is print_protos
725             sub extract_prototypes($)
726             {
727 0     0 0 0 my $self = shift;
728 0         0 my $ar;
729             my @ret;
730 0         0 foreach $ar (@{$self->{'protos_todo'}}) {
  0         0  
731 0         0 my $body;
732 0 0       0 if (defined $ar->[1]) {
733 0 0       0 if (ref $ar->[1]) {
734             # FIXME: better optree tracking?
735             # And use formatting markup?
736 0         0 my $node = $self->const($ar->[1]->RV,0);
737 0         0 my $body_node =
738             $self->info_from_template("protos", undef,
739             "() {\n %c;\n}",
740             undef, [$node]);
741 0         0 $body = $body_node->{text};
742             } else {
743 0         0 $body = sprintf " (%s);", $ar->[1];
744             }
745             } else {
746 0         0 $body = ";";
747             }
748 0         0 push @ret, sprintf "sub %s%s\n", $ar->[0], $body;
749             }
750 0         0 delete $self->{'protos_todo'};
751 0         0 return @ret;
752             }
753              
754             # This gets called automatically when option:
755             # -MO="DeparseTree,sC" is added
756             # Running this prints out the program text.
757             sub compile {
758 0     0 0 0 my(@args) = @_;
759             return sub {
760 0     0   0 my $self = B::DeparseTree->new(@args);
761             # First deparse command-line args
762 0 0       0 if (defined $^I) { # deparse -i
763 0         0 print q(BEGIN { $^I = ).perlstring($^I).qq(; }\n);
764             }
765 0 0       0 if ($^W) { # deparse -w
766 0         0 print qq(BEGIN { \$^W = $^W; }\n);
767             }
768 0 0 0     0 if ($/ ne "\n" or defined $O::savebackslash) { # deparse -l and -0
769 0   0     0 my $fs = perlstring($/) || 'undef';
770 0   0     0 my $bs = perlstring($O::savebackslash) || 'undef';
771 0         0 print qq(BEGIN { \$/ = $fs; \$\\ = $bs; }\n);
772             }
773 0 0       0 my @BEGINs = B::begin_av->isa("B::AV") ? B::begin_av->ARRAY : ();
774 0 0       0 my @UNITCHECKs = B::unitcheck_av->isa("B::AV")
775             ? B::unitcheck_av->ARRAY
776             : ();
777 0 0       0 my @CHECKs = B::check_av->isa("B::AV") ? B::check_av->ARRAY : ();
778 0 0       0 my @INITs = B::init_av->isa("B::AV") ? B::init_av->ARRAY : ();
779 0 0       0 my @ENDs = B::end_av->isa("B::AV") ? B::end_av->ARRAY : ();
780 0 0       0 if ($] < 5.020) {
781 0         0 for my $block (@BEGINs, @UNITCHECKs, @CHECKs, @INITs, @ENDs) {
782 0         0 $self->B::Deparse::todo($block, 0);
783             }
784             } else {
785 0         0 my @names = qw(BEGIN UNITCHECK CHECK INIT END);
786 0         0 my @blocks = (\@BEGINs, \@UNITCHECKs, \@CHECKs, \@INITs, \@ENDs);
787 0         0 while (@names) {
788 0         0 my ($name, $blocks) = (shift @names, shift @blocks);
789 0         0 for my $block (@$blocks) {
790 0         0 $self->todo($block, 0, $name);
791             }
792             }
793             }
794 0         0 $self->B::Deparse::stash_subs();
795             local($SIG{"__DIE__"}) =
796             sub {
797 0 0       0 if ($self->{'curcop'}) {
798 0         0 my $cop = $self->{'curcop'};
799 0         0 my($line, $file) = ($cop->line, $cop->file);
800 0         0 print STDERR "While deparsing $file near line $line,\n";
801             }
802 8     8   58 use Data::Printer;
  8         31  
  8         97  
803 0         0 my @bt = caller(1);
804 0         0 p @bt;
805 0         0 };
806 0         0 $self->{'curcv'} = main_cv;
807 0         0 $self->{'curcvlex'} = undef;
808 0         0 print $self->extract_prototypes;
809 0         0 @{$self->{'subs_todo'}} =
810 0         0 sort {$a->[0] <=> $b->[0]} @{$self->{'subs_todo'}};
  0         0  
  0         0  
811 0         0 my $root = main_root;
812 0         0 local $B::overlay = {};
813              
814 0 0       0 if ($] < 5.021) {
815 0 0       0 unless (B::Deparse::null $root) {
816 0         0 $self->pessimise($root, main_start);
817             # Print deparsed program
818 0         0 print $self->deparse_root($root)->{text}, "\n";
819             }
820             } else {
821 0 0       0 unless (B::Deparse::null $root) {
822 0         0 $self->B::Deparse::pad_subs($self->{'curcv'});
823             # Check for a stub-followed-by-ex-cop, resulting from a program
824             # consisting solely of sub declarations. For backward-compati-
825             # bility (and sane output) we don’t want to emit the stub.
826             # leave
827             # enter
828             # stub
829             # ex-nextstate (or ex-dbstate)
830 0         0 my $kid;
831 0 0 0     0 if ( $root->name eq 'leave'
      0        
      0        
      0        
      0        
      0        
      0        
832             and ($kid = $root->first)->name eq 'enter'
833             and !B::Deparse::null($kid = $kid->sibling) and $kid->name eq 'stub'
834             and !B::Deparse::null($kid = $kid->sibling) and $kid->name eq 'null'
835             and class($kid) eq 'COP' and B::Deparse::null $kid->sibling )
836             {
837             # ignore deparsing routine
838             } else {
839 0         0 $self->pessimise($root, main_start);
840             # Print deparsed program
841 0         0 my $root_tree = $self->deparse_root($root);
842 0         0 print $root_tree->{text}, "\n";
843             }
844             }
845             }
846 0         0 my @text;
847 0         0 while (scalar(@{$self->{'subs_todo'}})) {
  0         0  
848 0         0 push @text, $self->next_todo->{text};
849             }
850 0 0       0 print join("", @text), "\n" if @text;
851              
852             # Print __DATA__ section, if necessary
853 8     8   2753 no strict 'refs';
  8         18  
  8         26245  
854             my $laststash = defined $self->{'curcop'}
855 0 0       0 ? $self->{'curcop'}->stash->NAME : $self->{'curstash'};
856 0 0       0 if (defined *{$laststash."::DATA"}{IO}) {
  0         0  
857             print $self->keyword("package") . " $laststash;\n"
858 0 0       0 unless $laststash eq $self->{'curstash'};
859 0         0 print $self->keyword("__DATA__") . "\n";
860 0         0 print readline(*{$laststash."::DATA"});
  0         0  
861             }
862             }
863 0         0 }
864              
865             # "deparse()" is the main function to call to produces a depare tree
866             # for a give B::OP. This method is the inner loop.
867              
868             # Rocky's comment with respect to:
869             # so try to keep it simple
870             #
871             # Most normal Perl programs really aren't that big. Yeah, I know there
872             # are a couple of big pigs like the B::Deparse code itself. The perl5
873             # debugger comes to mind too. But what's the likelihood of anyone wanting
874             # to decompile all of this?
875             #
876             # On the other hand, error checking is too valuable to throw out here.
877             # Also, in trying to use and modularize this code, I see there is
878             # a lot of repetition in subroutine parsing routines. That's
879             # why I added the above PP_MAPFNS table. I'm not going to trade off
880             # table lookup and interpetation for a huge amount of subroutine
881             # bloat.
882              
883             # That said it is useful to note that this is inner-most loop
884             # interpeter loop as it is called for each node in the B::OP tree.
885             #
886             sub deparse
887             {
888 19281     19281 0 33433 my($self, $op, $cx, $parent) = @_;
889              
890 19281 50       54871 Carp::confess("deparse called on an invalid op $op")
891             unless $op->can('name');
892              
893 19281         57827 my $name = $op->name;
894 19281 50       55469 print "YYY $name\n" if $ENV{'DEBUG_DEPARSETREE'};
895 19281         25348 my ($info, $meth);
896              
897 19281 100       35484 if (exists($PP_MAPFNS{$name})) {
898             # Interpret method calls for our PP_MAPFNS table
899 4092 100       8184 if (ref($PP_MAPFNS{$name}) eq 'ARRAY') {
900 1664         2367 my @args = @{$PP_MAPFNS{$name}};
  1664         5304  
901 1664         3014 $meth = shift @args;
902 1664 100       3492 if ($meth eq 'maybe_targmy') {
903             # FIXME: This is an inline version of targmy.
904             # Can we dedup it? do we want to?
905 231         407 $meth = shift @args;
906 231 100       641 unshift @args, $name unless @args;
907 231 100       981 if ($op->private & OPpTARGET_MY) {
908 4         34 my $var = $self->padname($op->targ);
909 4         11 my $val = $self->$meth($op, 7, @args);
910 4         10 my @texts = ($var, '=', $val);
911 4         25 $info = $self->info_from_template("my", $op,
912             "%c = %c", [0, 1],
913             [$var, $val],
914             {maybe_parens => [$self, $cx, 7]});
915             } else {
916 227         1135 $info = $self->$meth($op, $cx, @args);
917             }
918             } else {
919 1433         5922 $info = $self->$meth($op, $cx, @args);
920             }
921             } else {
922             # Simple case: one simple call of the
923             # the method in the table. Call this
924             # passing arguments $op, $cx, and $name.
925             # Some functions might not use these,
926             # but that's okay.
927 2428         4158 $meth = $PP_MAPFNS{$name};
928 2428         9378 $info = $self->$meth($op, $cx, $name);
929             }
930             } else {
931             # Tried and true fallback method:
932             # a method has been defined for this pp_op special.
933             # call that.
934 15189         20634 $meth = "pp_" . $name;
935 15189         44484 $info = $self->$meth($op, $cx);
936             }
937              
938 19281 50       39659 Carp::confess("nonref return for $meth deparse: $info") if !ref($info);
939 19281 50       47760 Carp::confess("not B::DeparseTree:Node returned for $meth: $info")
940             if !$info->isa("B::DeparseTree::TreeNode");
941 19281 100       43277 $info->{parent} = $$parent if $parent;
942 19281         30611 $info->{cop} = $self->{'curcop'};
943 19281         24962 my $got_op = $info->{op};
944 19281 100       27953 if ($got_op) {
945 19212 100       34514 if ($got_op != $op) {
946             # Do something here?
947             # printf("XX final op 0x%x is not requested 0x%x\n",
948             # $$op, $$got_op);
949             }
950             } else {
951 69         438 $info->{op} = $op;
952             }
953 19281         49448 $self->{optree}{$$op} = $info;
954 19281 100       32195 if ($info->{other_ops}) {
955 4183         4932 foreach my $other (@{$info->{other_ops}}) {
  4183         7501  
956 8884 50       26010 if (!ref $other) {
    100          
957 0         0 Carp::confess "$meth returns invalid other $other";
958             } elsif ($other->isa("B::DeparseTree::TreeNode")) {
959             # "$other" has been set up to mark a particular portion
960             # of the info.
961 5501         10258 $self->{optree}{$other->{addr}} = $other;
962 5501         10440 $other->{parent} = $$op;
963             } else {
964             # "$other" is just the OP. Have it mark everything
965             # or "info".
966 3383         10617 $self->{optree}{$$other} = $info;
967             }
968             }
969             }
970 19281         43986 return $info;
971             }
972              
973             # Deparse a subroutine
974             sub deparse_sub($$$$)
975             {
976 1330     1330 0 3022 my ($self, $cv, $start_op) = @_;
977              
978             # Sanity checks..
979 1330 50 33     9942 Carp::confess("NULL in deparse_sub") if !defined($cv) || $cv->isa("B::NULL");
980 1330 50       5991 Carp::confess("SPECIAL in deparse_sub") if $cv->isa("B::SPECIAL");
981              
982             # First get protype and sub attribute information
983 1330         3635 local $self->{'curcop'} = $self->{'curcop'};
984 1330         2204 my $proto = '';
985 1330 50       4864 if ($cv->FLAGS & SVf_POK) {
986 0         0 $proto .= "(". $cv->PV . ")";
987             }
988 1330 100       4929 if ($cv->CvFLAGS & (CVf_METHOD|CVf_LOCKED|CVf_LVALUE)) {
989 2         4 $proto .= ":";
990 2 100       7 $proto .= " lvalue" if $cv->CvFLAGS & CVf_LVALUE;
991 2 50       8 $proto .= " locked" if $cv->CvFLAGS & CVf_LOCKED;
992 2 100       15 $proto .= " method" if $cv->CvFLAGS & CVf_METHOD;
993             }
994              
995 1330         4096 local($self->{'curcv'}) = $cv;
996 1330         2723 local($self->{'curcvlex'});
997             local(@$self{qw'curstash warnings hints hinthash'})
998 1330         5755 = @$self{qw'curstash warnings hints hinthash'};
999              
1000             # Now deparse subroutine body
1001              
1002 1330         4453 my $root = $cv->ROOT;
1003 1330         2363 my ($body, $node);
1004              
1005 1330         2555 local $B::overlay = {};
1006 1330 50       14303 if (not B::Deparse::null $root) {
1007 1330         6822 $self->pessimise($root, $cv->START);
1008 1330         6497 my $lineseq = $root->first;
1009 1330 50       5071 if ($lineseq->name eq "lineseq") {
    0          
1010 1330         1927 my @ops;
1011 1330         5698 for(my $o=$lineseq->first; $$o; $o=$o->sibling) {
1012 4148         13987 push @ops, $o;
1013             }
1014 1330         3902 $body = $self->lineseq($root, 0, @ops);
1015 1330         35391 my $scope_en = $self->find_scope_en($lineseq);
1016             }
1017             elsif ($start_op) {
1018 0         0 $body = $self->deparse($start_op, 0, $lineseq);
1019             } else {
1020 0         0 $body = $self->deparse($root->first, 0, $lineseq);
1021             }
1022              
1023 1330         7491 my $fn_name = $cv->GV->NAME;
1024 1330         8668 $node = $self->info_from_template("sub $fn_name$proto",
1025             $lineseq,
1026             "$proto\n%|{\n%+%c\n%-}",
1027             [0], [$body]);
1028 1330         4049 $body->{parent} = $$lineseq;
1029 1330         4645 $self->{optree}{$$lineseq} = $node;
1030              
1031             } else {
1032 0         0 my $sv = $cv->const_sv;
1033 0 0       0 if ($$sv) {
1034             # uh-oh. inlinable sub... format it differently
1035 0         0 $node = $self->info_from_template('inline sub', $sv,
1036             "$proto\n%|{\n%+%c\n%-}",
1037             [0], [$self->const($sv, 0)]);
1038             } else {
1039             # XSUB? (or just a declaration)
1040 0         0 $node = $self->info_from_string("XSUB or sub declaration", $proto);
1041             }
1042             }
1043              
1044              
1045             # Should we create a real node for this instead of the copy?
1046 1330         4087 $self->{optree}{$$root} = $node;
1047              
1048             # Add additional DeparseTree tracking info
1049 1330 50       3258 if ($start_op) {
1050 0         0 $node->{op} = $start_op;
1051 0         0 $self->{'optree'}{$$start_op} = $node;
1052             }
1053 1330         2606 $node->{cop} = undef;
1054 1330         2246 $node->{'parent'} = $cv;
1055 1330         35035 return $node;
1056             }
1057              
1058             # We have a TODO list of things that must be handled
1059             # at the top level. There are things like
1060             # format statements, "BEGIN" and "use" statements.
1061             # Here we handle the next one.
1062             sub next_todo
1063             {
1064 0     0 0 0 my ($self, $parent) = @_;
1065 0         0 my $ent = shift @{$self->{'subs_todo'}};
  0         0  
1066 0         0 my ($seq, $cv, $is_form, $name) = @$ent;
1067              
1068             # any 'use strict; package foo' that should come before the sub
1069             # declaration to sync with the first COP of the sub
1070              
1071             ## FIXME: $self->pragmata messes scoping up, although I don't know
1072             ## how it does that.
1073             # my $pragmata = '';
1074             # if ($cv and !B::Deparse::null($cv->START) and B::Deparse::is_state($cv->START)) {
1075             # $pragmata = $self->B::Deparse::pragmata($cv->START);
1076             # }
1077              
1078             # if (ref $name) { # lexical sub
1079             # # emit the sub.
1080             # my @text;
1081             # my $flags = $name->FLAGS;
1082             # push @text,
1083             # !$cv || $seq <= $name->COP_SEQ_RANGE_LOW
1084             # ? $self->keyword($flags & B::SVpad_OUR
1085             # ? "our"
1086             # : $flags & SVpad_STATE
1087             # ? "state"
1088             # : "my") . " "
1089             # : "";
1090             # # XXX We would do $self->keyword("sub"), but ‘my CORE::sub’
1091             # # doesn’t work and ‘my sub’ ignores a &sub in scope. I.e.,
1092             # # we have a core bug here.
1093             # push @text, "sub " . substr $name->PVX, 1;
1094             # my $text = join('', @text);
1095             # if ($cv) {
1096             # # my sub foo { }
1097             # my $cv_node = $self->deparse_sub($cv);
1098             # my $fmt = sprintf("%s%s%%c", $pragmata, $text);
1099             # return $self->info_from_template("sub", $cv,
1100             # $fmt, undef,
1101             # [$cv_node]);
1102             # } else {
1103             # return $self->info_from_string("sub no body", $cv, $text);
1104             # }
1105             # }
1106              
1107 0         0 my $gv = $cv->GV;
1108 0   0     0 $name //= $self->gv_name($gv);
1109 0 0       0 if ($is_form) {
1110 0         0 my $node = $self->deparse_format($ent->[1], $cv);
1111 0         0 return $self->info_from_template("format $name",
1112             "format $name = %c",
1113             undef, [$node])
1114             } else {
1115 0         0 my ($fmt, $type);
1116 0         0 $self->{'subs_declared'}{$name} = 1;
1117 0 0       0 if ($name eq "BEGIN") {
1118 0         0 my $use_dec = $self->begin_is_use($cv);
1119 0 0 0     0 if (defined ($use_dec) and $self->{'expand'} < 5) {
1120 0 0       0 if (0 == length($use_dec)) {
1121 0         0 $self->info_from_string('BEGIN', $cv, '');
1122             } else {
1123 0         0 $self->info_from_string('use', $cv, $use_dec);
1124             }
1125             }
1126             }
1127 0         0 my $l = '';
1128 0 0       0 if ($self->{'linenums'}) {
1129 0         0 my $line = $gv->LINE;
1130 0         0 my $file = $gv->FILE;
1131 0         0 $l = "\n# line $line \"$file\"\n";
1132             }
1133 0 0       0 if (class($cv->STASH) ne "SPECIAL") {
1134 0         0 my $stash = $cv->STASH->NAME;
1135 0 0       0 if ($stash ne $self->{'curstash'}) {
1136 0         0 $fmt = "package $stash;\n";
1137 0         0 $type = "package $stash";
1138 0 0       0 $name = "$self->{'curstash'}::$name" unless $name =~ /::/;
1139 0         0 $self->{'curstash'} = $stash;
1140             }
1141 0         0 $name =~ s/^\Q$stash\E::(?!\z|.*::)//;
1142 0         0 $fmt .= "sub $name";
1143 0         0 $type .= "sub $name";
1144             }
1145 0         0 my $node = $self->deparse_sub($cv, $parent);
1146 0         0 $fmt .= '%c';
1147 0         0 my $sub_node = $self->info_from_template($type, $cv, $fmt, [0], [$node]);
1148 0         0 $node->{parent} = $sub_node->{addr};
1149 0         0 $self->{optree}{$$cv} = $sub_node;
1150 0         0 return $sub_node;
1151             }
1152             }
1153              
1154             # Deparse a subroutine by name
1155             sub deparse_subname($$)
1156             {
1157 0     0 0 0 my ($self, $funcname) = @_;
1158 0         0 my $cv = svref_2object(\&$funcname);
1159 0         0 my $info = $self->deparse_sub($cv);
1160 0         0 my $sub_node = $self->info_from_template("sub $funcname", $cv, "sub $funcname %c",
1161             undef, [$info]);
1162 0         0 $self->{optree}{$$cv} = $sub_node;
1163 0         0 return $sub_node;
1164             }
1165              
1166             # Return a list of info nodes for "use" and "no" pragmas.
1167             sub declare_hints
1168             {
1169 1321     1321 0 3063 my ($self, $from, $to) = @_;
1170 1321         2464 my $use = $to & ~$from;
1171 1321         2235 my $no = $from & ~$to;
1172              
1173 1321         2194 my @decls = ();
1174 1321         18978 for my $pragma (B::Deparse::hint_pragmas($use)) {
1175 1266         31223 my $type = $self->keyword("use") . " $pragma";
1176 1266         6570 push @decls, $self->info_from_template($type, undef, "$type", [], []);
1177             }
1178 1321         9396 for my $pragma (B::Deparse::hint_pragmas($no)) {
1179 0         0 my $type = $self->keyword("no") . " $pragma";
1180 0         0 push @decls, $self->info_from_template($type, undef, "$type", [], []);
1181             }
1182 1321         3845 return @decls;
1183             }
1184              
1185             # Internal implementation hints that the core sets automatically, so don't need
1186             # (or want) to be passed back to the user
1187             my %ignored_hints = (
1188             'open<' => 1,
1189             'open>' => 1,
1190             ':' => 1,
1191             'strict/refs' => 1,
1192             'strict/subs' => 1,
1193             'strict/vars' => 1,
1194             );
1195              
1196             my %rev_feature;
1197              
1198             sub declare_hinthash {
1199 2087     2087 0 4598 my ($self, $from, $to, $indent, $hints) = @_;
1200 2087         2650 my $doing_features;
1201 2087 50       3632 if ($] >= 5.016) {
1202 2087         3538 $doing_features = ($hints & $feature::hint_mask) == $feature::hint_mask;
1203             } else {
1204 0         0 $doing_features = 0;
1205             }
1206 2087         4446 my @decls;
1207             my @features;
1208 2087         0 my @unfeatures; # bugs?
1209 2087         6996 for my $key (sort keys %$to) {
1210 67 50       149 next if $ignored_hints{$key};
1211 67   33     605 my $is_feature = $key =~ /^feature_/ && $^V ge 5.15.6;
1212 67 100 66     283 next if $is_feature and not $doing_features;
1213 54 100 66     221 if (!exists $from->{$key} or $from->{$key} ne $to->{$key}) {
1214 12 50       24 if ($is_cperl){
1215 0 0       0 next if $key eq 'feature_lexsubs';
1216 0 0       0 next if $key eq 'feature_signatures';
1217             }
1218 12 50       39 push(@features, $key), next if $is_feature;
1219             push @decls,
1220             qq(\$^H{) . single_delim($self, "q", "'", $key, "'") . qq(} = )
1221             . (
1222             defined $to->{$key}
1223 0 0       0 ? single_delim($self, "q", "'", $to->{$key}, "'")
1224             : 'undef'
1225             )
1226             . qq(;);
1227             }
1228             }
1229 2087         5100 for my $key (sort keys %$from) {
1230 55 50       104 next if $ignored_hints{$key};
1231 55   33     473 my $is_feature = $key =~ /^feature_/ && $^V ge 5.15.6;
1232 55 100 66     210 next if $is_feature and not $doing_features;
1233 42 50       210 if (!exists $to->{$key}) {
1234 0 0       0 push(@unfeatures, $key), next if $is_feature;
1235 0         0 push @decls, qq(delete \$^H{'$key'};);
1236             }
1237             }
1238 2087         3004 my @ret;
1239 2087 100 66     7673 if (@features || @unfeatures) {
1240 3 100       9 if (!%rev_feature) { %rev_feature = reverse %feature::feature }
  1         10  
1241             }
1242 2087 100       4022 if (@features) {
1243 3         1709 push @ret, $self->keyword("use") . " feature "
1244             . join(", ", map "'$rev_feature{$_}'", @features) . ";\n";
1245             }
1246 2087 50       3805 if (@unfeatures) {
1247 0         0 push @ret, $self->keyword("no") . " feature "
1248             . join(", ", map "'$rev_feature{$_}'", @unfeatures)
1249             . ";\n";
1250             }
1251             @decls and
1252 2087 50       3795 push @ret,
1253             join("\n" . (" " x $indent), "BEGIN {", @decls) . "\n}\n";
1254 2087         5507 return @ret;
1255             }
1256              
1257             # generate any pragmas, 'package foo' etc needed to synchronise
1258             # with the given cop
1259              
1260             sub pragmata {
1261 0     0 0 0 my $self = shift;
1262 0         0 my($op) = @_;
1263              
1264 0         0 my @text;
1265              
1266 0         0 my $stash = $op->stashpv;
1267 0 0       0 if ($stash ne $self->{'curstash'}) {
1268 0         0 push @text, $self->keyword("package") . " $stash;\n";
1269 0         0 $self->{'curstash'} = $stash;
1270             }
1271              
1272 0         0 if (OPpCONST_ARYBASE && $self->{'arybase'} != $op->arybase) {
1273             push @text, '$[ = '. $op->arybase .";\n";
1274             $self->{'arybase'} = $op->arybase;
1275             }
1276              
1277 0         0 my $warnings = $op->warnings;
1278 0         0 my $warning_bits;
1279 0 0 0     0 if ($warnings->isa("B::SPECIAL") && $$warnings == 4) {
    0 0        
    0          
1280 0         0 $warning_bits = $warnings::Bits{"all"} & WARN_MASK;
1281             }
1282             elsif ($warnings->isa("B::SPECIAL") && $$warnings == 5) {
1283 0         0 $warning_bits = $warnings::NONE;
1284             }
1285             elsif ($warnings->isa("B::SPECIAL")) {
1286 0         0 $warning_bits = undef;
1287             }
1288             else {
1289 0         0 $warning_bits = $warnings->PV & WARN_MASK;
1290             }
1291              
1292 0 0 0     0 if (defined ($warning_bits) and
      0        
1293             !defined($self->{warnings}) || $self->{'warnings'} ne $warning_bits) {
1294             push @text,
1295 0         0 $self->declare_warnings($self->{'warnings'}, $warning_bits);
1296 0         0 $self->{'warnings'} = $warning_bits;
1297             }
1298              
1299 0 0       0 my $hints = $] < 5.008009 ? $op->private : $op->hints;
1300 0         0 my $old_hints = $self->{'hints'};
1301 0 0       0 if ($self->{'hints'} != $hints) {
1302 0         0 push @text, $self->declare_hints($self->{'hints'}, $hints);
1303 0         0 $self->{'hints'} = $hints;
1304             }
1305              
1306 0         0 my $newhh;
1307 0 0       0 if ($] > 5.009) {
1308 0         0 $newhh = $op->hints_hash->HASH;
1309             }
1310              
1311 0 0       0 if ($] >= 5.015006) {
1312             # feature bundle hints
1313 0         0 my $from = $old_hints & $feature::hint_mask;
1314 0         0 my $to = $ hints & $feature::hint_mask;
1315 0 0       0 if ($from != $to) {
1316 0 0       0 if ($to == $feature::hint_mask) {
1317 0 0       0 if ($self->{'hinthash'}) {
1318             delete $self->{'hinthash'}{$_}
1319 0         0 for grep /^feature_/, keys %{$self->{'hinthash'}};
  0         0  
1320             }
1321 0         0 else { $self->{'hinthash'} = {} }
1322             $self->{'hinthash'}
1323 0         0 = _features_from_bundle($from, $self->{'hinthash'});
1324             }
1325             else {
1326 0         0 my $bundle =
1327             $feature::hint_bundles[$to >> $feature::hint_shift];
1328 0         0 $bundle =~ s/(\d[13579])\z/$1+1/e; # 5.11 => 5.12
  0         0  
1329 0         0 push @text,
1330             $self->keyword("no") . " feature ':all';\n",
1331             $self->keyword("use") . " feature ':$bundle';\n";
1332             }
1333             }
1334             }
1335              
1336 0 0       0 if ($] > 5.009) {
1337             push @text, $self->declare_hinthash(
1338             $self->{'hinthash'}, $newhh,
1339             $self->{indent_size}, $self->{hints},
1340 0         0 );
1341 0         0 $self->{'hinthash'} = $newhh;
1342             }
1343              
1344 0         0 return join("", @text);
1345             }
1346              
1347              
1348             # Create a "use", "no", or "BEGIN" block to set warnings.
1349             sub declare_warnings
1350             {
1351 1266     1266 0 2968 my ($self, $from, $to) = @_;
1352 1266 100       3329 if (($to & WARN_MASK) eq (warnings::bits("all") & WARN_MASK)) {
    50          
1353 2         1439 my $type = $self->keyword("use") . " warnings";
1354 2         26 return $self->info_from_string($type, undef, "$type");
1355             }
1356             elsif (($to & WARN_MASK) eq ("\0"x length($to) & WARN_MASK)) {
1357 1264         31482 my $type = $self->keyword("no") . " warnings";
1358 1264         5796 return $self->info_from_string($type, undef, "$type");
1359             }
1360 0         0 my $bit_expr = join('', map { sprintf("\\x%02x", ord $_) } split "", $to);
  0         0  
1361 0         0 my $str = "BEGIN {\n%+\${^WARNING_BITS} = \"$bit_expr;\n%-";
1362 0         0 return $self->info_from_template('warning bits begin', undef,
1363             "$str", [], [], {omit_next_semicolon=>1});
1364             }
1365              
1366             # Iterate over $self->{subs_todo} picking up the
1367             # text of of $self->next_todo.
1368             # We return an array of strings. The calling
1369             # routine will join these together
1370             sub seq_subs {
1371 2087     2087 0 4413 my ($self, $seq) = @_;
1372 2087         2605 my @texts;
1373              
1374 2087 50       4355 return () if !defined $seq;
1375 2087         2730 my @pending;
1376 2087   33     2700 while (scalar(@{$self->{'subs_todo'}})
  2087         6272  
1377             and $seq > $self->{'subs_todo'}[0][0]) {
1378 0         0 my $cv = $self->{'subs_todo'}[0][1];
1379             # Skip the OUTSIDE check for lexical subs. We may be deparsing a
1380             # cloned anon sub with lexical subs declared in it, in which case
1381             # the OUTSIDE pointer points to the anon protosub.
1382 0         0 my $lexical = ref $self->{'subs_todo'}[0][3];
1383 0   0     0 my $outside = !$lexical && $cv && $cv->OUTSIDE;
1384 0 0 0     0 if (!$lexical and $cv
      0        
1385 0 0       0 and ${$cv->OUTSIDE || \0} != ${$self->{'curcv'}})
  0         0  
1386             {
1387             # rocky: What do we do with @pending?
1388 0         0 push @pending, shift @{$self->{'subs_todo'}};
  0         0  
1389 0         0 next;
1390             }
1391 0         0 push @texts, $self->next_todo;
1392             }
1393 2087         5295 return @texts;
1394             }
1395              
1396             # FIXME: this code has to be here. Find out why and fix.
1397             # Truncate is special because OPf_SPECIAL makes a bareword first arg
1398             # be a filehandle. This could probably be better fixed in the core
1399             # by moving the GV lookup into ck_truc.
1400              
1401             # Demo code
1402             unless(caller) {
1403             my @texts = ('a', 'b', 'c');
1404             my $deparse = __PACKAGE__->new();
1405             my $info = info_from_list('op', $deparse, \@texts, ', ', 'test', {});
1406              
1407 8     8   75 use Data::Printer;
  8         28  
  8         66  
1408             my $str = $deparse->template_engine("%c", [0], ["16"]);
1409             p $str;
1410             my $str2 = $deparse->template_engine("%F", [[0, sub {'0x' . sprintf "%x", shift}]], [$str]);
1411             p $str2;
1412              
1413             # print $deparse->template_engine("100%% "), "\n";
1414             # print $deparse->template_engine("%c,\n%+%c\n%|%c %c!",
1415             # [1, 0, 2, 3],
1416             # ["is", "now", "the", "time"]), "\n";
1417              
1418             # $info = $deparse->info_from_template("demo", undef, "%C",
1419             # [[0, 1, ";\n%|"]],
1420             # ['$x=1', '$y=2']);
1421              
1422             # @texts = ("use warnings;", "use strict", "my(\$a)");
1423             # $info = $deparse->info_from_template("demo", undef, "%;", [], \@texts);
1424              
1425             # $info = $deparse->info_from_template("list", undef,
1426             # "%C", [[0, $#texts, ', ']],
1427             # \@texts);
1428              
1429             # p $info;
1430              
1431              
1432             # @texts = (['a', 1], ['b', 2], 'c');
1433             # $info = info_from_list('op', $deparse, \@texts, ', ', 'test', {});
1434             # p $info;
1435             }
1436              
1437             1;