File Coverage

lib/B/DeparseTree/TreeMain.pm
Criterion Covered Total %
statement 314 645 48.6
branch 109 336 32.4
condition 27 124 21.7
subroutine 38 50 76.0
pod 2 26 7.6
total 490 1181 41.4


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 3     3   19 use strict; use warnings;
  3     3   4  
  3         73  
  3         14  
  3         6  
  3         159  
20              
21             package B::DeparseTree;
22              
23 3         414 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 3     3   18 );
  3         5  
41              
42 3     3   19 use Carp;
  3         6  
  3         154  
43 3     3   17 use B::Deparse;
  3         5  
  3         80  
44 3     3   1207 use B::DeparseTree::PP_OPtable;
  3         8  
  3         283  
45 3     3   1179 use B::DeparseTree::SyntaxTree;
  3         8  
  3         545  
46              
47             # Copy unchanged functions from B::Deparse
48             *find_scope_en = *B::Deparse::find_scope_en;
49             *find_scope_st = *B::Deparse::find_scope_st;
50             *gv_name = *B::Deparse::gv_name;
51             *lex_in_scope = *B::Deparse::lex_in_scope;
52             *padname = *B::Deparse::padname;
53             *rv2gv_or_string = *B::Deparse::rv2gv_or_string;
54             *stash_subs = *B::Deparse::stash_subs;
55             *stash_variable = *B::Deparse::stash_variable;
56              
57             our($VERSION, @EXPORT, @ISA);
58             $VERSION = '3.2.0';
59             @ISA = qw(Exporter);
60             @EXPORT = qw(
61             %globalnames
62             %ignored_hints
63             %rev_feature
64             WARN_MASK
65             coderef2info
66             coderef2text
67             const
68             declare_hinthash
69             declare_hints
70             declare_warnings
71             deparse_sub($$$$)
72             deparse_subname($$)
73             new
74             next_todo
75             pragmata
76             print_protos
77             seq_subs
78             style_opts
79             );
80              
81 3     3   20 use Config;
  3         3  
  3         491  
82             my $is_cperl = $Config::Config{usecperl};
83              
84             my $module;
85             if ($] >= 5.016 and $] < 5.018) {
86             # 5.16 and 5.18 are the same for now
87             $module = "P518";
88             } elsif ($] >= 5.018 and $] < 5.020) {
89             $module = "P518";
90             } elsif ($] >= 5.020 and $] < 5.022) {
91             $module = "P520";
92             } elsif ($] >= 5.022 and $] < 5.024) {
93             $module = "P522";
94             } elsif ($] >= 5.024 and $] < 5.026) {
95             $module = "P524";
96             } elsif ($] >= 5.026) {
97             $module = "P526";
98             } else {
99             die "Can only handle Perl 5.16..5.26";
100             }
101              
102             $module .= 'c' if $is_cperl;
103             @ISA = ("Exporter", "B::DeparseTree::$module");
104              
105             require "B/DeparseTree/${module}.pm";
106              
107             # The BEGIN {} is used here because otherwise this code isn't executed
108             # when you run B::Deparse on itself.
109             my %globalnames;
110 3     3   172 BEGIN { map($globalnames{$_}++, "SIG", "STDIN", "STDOUT", "STDERR", "INC",
111             "ENV", "ARGV", "ARGVOUT", "_"); }
112              
113             my $max_prec;
114 3     3   163 BEGIN { $max_prec = int(0.999 + 8*length(pack("F", 42))*log(2)/log(10)); }
115              
116             BEGIN {
117             # List version-specific constants here.
118             # Easiest way to keep this code portable between version looks to
119             # be to fake up a dummy constant that will never actually be true.
120 3     3   9 foreach (qw(OPpSORT_INPLACE OPpSORT_DESCEND OPpITER_REVERSED
121             OPpCONST_NOVER OPpPAD_STATE PMf_SKIPWHITE RXf_SKIPWHITE
122             RXf_PMf_CHARSET RXf_PMf_KEEPCOPY
123             CVf_LOCKED OPpREVERSE_INPLACE OPpSUBSTR_REPL_FIRST
124             PMf_NONDESTRUCT OPpCONST_ARYBASE OPpEVAL_BYTES)) {
125 45         58 eval { import B $_ };
  45         2997  
126 3     3   17 no strict 'refs';
  3         3  
  3         209  
127 45 100       70 *{$_} = sub () {0} unless *{$_}{CODE};
  9         33  
  45         1249  
128             }
129             }
130              
131             sub new {
132 5     5 1 351322 my $class = shift;
133 5         24 my $self = bless {}, $class;
134 5         57 $self->{'cuddle'} = " "; #\n%| is another alternative
135 5         19 $self->{'curcop'} = undef;
136 5         21 $self->{'curstash'} = "main";
137 5         18 $self->{'ex_const'} = "'?unrecoverable constant?'";
138 5         16 $self->{'expand'} = 0;
139 5         18 $self->{'files'} = {};
140              
141             # How many spaces per indent nesting?
142 5         14 $self->{'indent_size'} = 4;
143              
144 5         19 $self->{'opaddr'} = 0;
145 5         15 $self->{'linenums'} = 0;
146 5         16 $self->{'parens'} = 0;
147 5         15 $self->{'subs_todo'} = [];
148 5         18 $self->{'unquote'} = 0;
149 5         14 $self->{'use_dumper'} = 0;
150              
151             # Compress spaces with tabs? 1 tab = 8 spaces
152 5         11 $self->{'use_tabs'} = 0;
153              
154             # Indentation level
155 5         10 $self->{'level'} = 0;
156              
157 5         14 $self->{'ambient_arybase'} = 0;
158 5         10 $self->{'ambient_warnings'} = undef; # Assume no lexical warnings
159 5         9 $self->{'ambient_hints'} = 0;
160 5         14 $self->{'ambient_hinthash'} = undef;
161              
162             # Given an opcode address, get the accumulated OP tree
163             # OP for that. FIXME: remove this
164 5         15 $self->{optree} = {};
165              
166             # Extra opcode information: parent_op
167 5         16 $self->{ops} = {};
168              
169             # For B::DeparseTree::Node's that are created and don't have real OPs associated
170             # with them, we assign a fake address;
171 5         15 $self->{'last_fake_addr'} = 0;
172              
173 5         22 $self->init();
174              
175 5         18 while (my $arg = shift @_) {
176 0 0       0 if ($arg eq "-d") {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
177 0         0 $self->{'use_dumper'} = 1;
178 0         0 require Data::Dumper;
179             } elsif ($arg =~ /^-f(.*)/) {
180 0         0 $self->{'files'}{$1} = 1;
181             } elsif ($arg eq "-l") {
182 0         0 $self->{'linenums'} = 1;
183             } elsif ($arg eq "-a") {
184 0         0 $self->{'linenums'} = 1;
185 0         0 $self->{'opaddr'} = 1;
186             } elsif ($arg eq "-p") {
187 0         0 $self->{'parens'} = 1;
188             } elsif ($arg eq "-P") {
189 0         0 $self->{'noproto'} = 1;
190             } elsif ($arg eq "-q") {
191 0         0 $self->{'unquote'} = 1;
192             } elsif (substr($arg, 0, 2) eq "-s") {
193 0         0 $self->style_opts(substr $arg, 2);
194             } elsif ($arg =~ /^-x(\d)$/) {
195 0         0 $self->{'expand'} = $1;
196             }
197             }
198 5         10 return $self;
199             }
200              
201             {
202             # Mask out the bits that L uses
203             my $WARN_MASK;
204             BEGIN {
205 3     3   518 $WARN_MASK = $warnings::Bits{all} | $warnings::DeadBits{all};
206             }
207             sub WARN_MASK () {
208 5262     5262 0 25462 return $WARN_MASK;
209             }
210             }
211              
212             # Initialize the contextual information, either from
213             # defaults provided with the ambient_pragmas method,
214             # or from Perl's own defaults otherwise.
215             sub init {
216 1409     1409 0 2262 my $self = shift;
217              
218 1409         2789 $self->{'arybase'} = $self->{'ambient_arybase'};
219             $self->{'warnings'} = defined ($self->{'ambient_warnings'})
220 1409 100       4048 ? $self->{'ambient_warnings'} & WARN_MASK
221             : undef;
222 1409         2333 $self->{'hints'} = $self->{'ambient_hints'};
223 1409 50       3189 $self->{'hints'} &= 0xFF if $] < 5.009;
224 1409         2401 $self->{'hinthash'} = $self->{'ambient_hinthash'};
225              
226             # also a convenient place to clear out subs_declared
227 1409         3171 delete $self->{'subs_declared'};
228             }
229              
230 3     3   11 BEGIN { for (qw[ pushmark ]) {
231 3         2372 eval "sub OP_\U$_ () { " . opnumber($_) . "}"
232             }}
233              
234             sub main2info
235             {
236 0     0 0 0 my $self = shift;
237 0         0 $self->{'curcv'} = B::main_cv;
238 0         0 $self->pessimise(B::main_root, B::main_start);
239 0         0 return $self->deparse_root(B::main_root);
240             }
241              
242             sub coderef2info
243             {
244 1345     1345 0 1010694 my ($self, $coderef, $start_op) = @_;
245 1345 50       5288 croak "Usage: ->coderef2info(CODEREF)" unless UNIVERSAL::isa($coderef, "CODE");
246 1345         4863 $self->init();
247 1345         6342 return $self->deparse_sub(svref_2object($coderef), $start_op);
248             }
249              
250             sub coderef2text
251             {
252 59     59 1 110463 my ($self, $func) = @_;
253 59 50       265 croak "Usage: ->coderef2text(CODEREF)" unless UNIVERSAL::isa($func, "CODE");
254              
255 59         210 $self->init();
256 59         205 my $info = $self->coderef2info($func);
257 59         214 return $self->info2str($info);
258             }
259              
260             sub const {
261 77     77 0 111 my $self = shift;
262 77         143 my($sv, $cx) = @_;
263 77 50       189 if ($self->{'use_dumper'}) {
264 0         0 return $self->const_dumper($sv, $cx);
265             }
266 77 50       496 if (class($sv) eq "SPECIAL") {
267             # sv_undef, sv_yes, sv_no
268 0         0 my $text = ('undef', '1', $self->maybe_parens("!1", $cx, 21))[$$sv-1];
269 0         0 return info_from_text($sv, $self, $text, 'const_special', {});
270             }
271 77 50       356 if (class($sv) eq "NULL") {
272 0         0 return info_from_text($sv, $self, 'undef', 'const_NULL', {});
273             }
274             # convert a version object into the "v1.2.3" string in its V magic
275 77 50       273 if ($sv->FLAGS & SVs_RMG) {
276 0         0 for (my $mg = $sv->MAGIC; $mg; $mg = $mg->MOREMAGIC) {
277 0 0       0 if ($mg->TYPE eq 'V') {
278 0         0 return info_from_text($sv, $self, $mg->PTR, 'const_magic', {});
279             }
280             }
281             }
282              
283 77 100 33     342 if ($sv->FLAGS & SVf_IOK) {
    50          
    50          
    50          
284 54         203 my $str = $sv->int_value;
285 54 50       135 $str = $self->maybe_parens($str, $cx, 21) if $str < 0;
286 54         216 return $self->info_from_string("integer constant $str", $sv, $str);
287             } elsif ($sv->FLAGS & SVf_NOK) {
288 0         0 my $nv = $sv->NV;
289 0 0       0 if ($nv == 0) {
    0          
    0          
290 0 0       0 if (pack("F", $nv) eq pack("F", 0)) {
291             # positive zero
292 0         0 return info_from_text($sv, $self, "0", 'constant float positive 0', {});
293             } else {
294             # negative zero
295 0         0 return info_from_text($sv, $self, $self->maybe_parens("-.0", $cx, 21),
296             'constant float negative 0', {});
297             }
298             } elsif (1/$nv == 0) {
299 0 0       0 if ($nv > 0) {
300             # positive infinity
301 0         0 return info_from_text($sv, $self, $self->maybe_parens("9**9**9", $cx, 22),
302             'constant float +infinity', {});
303             } else {
304             # negative infinity
305 0         0 return info_from_text($sv, $self, $self->maybe_parens("-9**9**9", $cx, 21),
306             'constant float -infinity', {});
307             }
308             } elsif ($nv != $nv) {
309             # NaN
310 0 0       0 if (pack("F", $nv) eq pack("F", sin(9**9**9))) {
    0          
311             # the normal kind
312 0         0 return info_from_text($sv, $self, "sin(9**9**9)", 'const_Nan', {});
313             } elsif (pack("F", $nv) eq pack("F", -sin(9**9**9))) {
314             # the inverted kind
315 0         0 return info_from_text($sv, $self, $self->maybe_parens("-sin(9**9**9)", $cx, 21),
316             'constant float Nan invert', {});
317             } else {
318             # some other kind
319 0         0 my $hex = unpack("h*", pack("F", $nv));
320 0         0 return info_from_text($sv, $self, qq'unpack("F", pack("h*", "$hex"))',
321             'constant Na na na', {});
322             }
323             }
324             # first, try the default stringification
325 0         0 my $str = "$nv";
326 0 0       0 if ($str != $nv) {
327             # failing that, try using more precision
328 0         0 $str = sprintf("%.${max_prec}g", $nv);
329             # if (pack("F", $str) ne pack("F", $nv)) {
330 0 0       0 if ($str != $nv) {
331             # not representable in decimal with whatever sprintf()
332             # and atof() Perl is using here.
333 0         0 my($mant, $exp) = split_float($nv);
334 0         0 return info_from_text($sv, $self, $self->maybe_parens("$mant * 2**$exp", $cx, 19),
335             'constant float not-sprintf/atof-able', {});
336             }
337             }
338 0 0       0 $str = $self->maybe_parens($str, $cx, 21) if $nv < 0;
339 0         0 return info_from_text($sv, $self, $str, 'constant nv', {});
340             } elsif ($sv->FLAGS & SVf_ROK && $sv->can("RV")) {
341 0         0 my $ref = $sv->RV;
342 0 0       0 if (class($ref) eq "AV") {
    0          
    0          
343 0         0 my $list_info = $self->list_const($sv, 2, $ref->ARRAY);
344 0         0 return info_from_list($sv, $self, ['[', $list_info->{text}, ']'], '', 'const_av',
345             {body => [$list_info]});
346             } elsif (class($ref) eq "HV") {
347 0         0 my %hash = $ref->ARRAY;
348 0         0 my @elts;
349 0         0 for my $k (sort keys %hash) {
350 0         0 push @elts, "$k => " . $self->const($hash{$k}, 6);
351             }
352 0         0 return info_from_list($sv, $self, ["{", join(", ", @elts), "}"], '',
353             'constant hash value', {});
354             } elsif (class($ref) eq "CV") {
355             BEGIN {
356 3 50   3   15 if ($] > 5.0150051) {
357 3         16 require overloading;
358 3         5699 unimport overloading;
359             }
360             }
361 0 0 0     0 if ($] > 5.0150051 && $self->{curcv} &&
      0        
362             $self->{curcv}->object_2svref == $ref->object_2svref) {
363 0         0 return $self->info_from_string('sub __SUB__', $sv,
364             $self->keyword("__SUB__"));
365             }
366 0         0 my $sub_info = $self->deparse_sub($ref);
367 0         0 return info_from_list($sub_info->{op}, $self, ["sub ", $sub_info->{text}], '',
368             'constant sub 2',
369             {body => [$sub_info]});
370             }
371 0 0       0 if ($ref->FLAGS & SVs_SMG) {
372 0         0 for (my $mg = $ref->MAGIC; $mg; $mg = $mg->MOREMAGIC) {
373 0 0       0 if ($mg->TYPE eq 'r') {
374 0         0 my $re = B::Deparse::re_uninterp(B::Deparse::escape_str(B::Deparse::re_unback($mg->precomp)));
375 0         0 return $self->single_delim($sv, "qr", "", $re);
376             }
377             }
378             }
379              
380 0         0 my $const = $self->const($ref, 20);
381 0 0 0     0 if ($self->{in_subst_repl} && $const =~ /^[0-9]/) {
382 0         0 $const = "($const)";
383             }
384 0         0 my @texts = ("\\", $const);
385 0         0 return info_from_list($sv, $self, \@texts, '', 'const_rv',
386             {maybe_parens => [$self, $cx, 20]});
387              
388             } elsif ($sv->FLAGS & SVf_POK) {
389 23         118 my $str = $sv->PV;
390 23 50       70 if ($str =~ /[[:^print:]]/) {
391 0         0 return $self->single_delim($sv, "qq", '"',
392             B::Deparse::uninterp B::Deparse::escape_str B::Deparse::unback $str);
393             } else {
394 23         158 return $self->single_delim($sv, "q", "'", B::Deparse::unback $str);
395             }
396             } else {
397 0         0 return info_from_text($sv, $self, "undef", 'constant undef', {});
398             }
399             }
400              
401             sub const_dumper
402             {
403 0     0 0 0 my $self = shift;
404 0         0 my($sv, $cx) = @_;
405 0         0 my $ref = $sv->object_2svref();
406 0         0 my $dumper = Data::Dumper->new([$$ref], ['$v']);
407 0         0 $dumper->Purity(1)->Terse(1)->Deparse(1)->Indent(0)->Useqq(1)->Sortkeys(1);
408 0         0 my $str = $dumper->Dump();
409 0 0       0 if ($str =~ /^\$v/) {
410 0         0 return info_from_text($sv, $self, ['${my', $str, '\$v}'], 'const_dumper_my', {});
411             } else {
412 0         0 return info_from_text($sv, $self, $str, 'constant dumper', {});
413             }
414             }
415              
416             # This is a special case of scopeop and lineseq, for the case of the
417             # main_root.
418             sub deparse_root {
419 0     0 0 0 my $self = shift;
420 0         0 my($op) = @_;
421             local(@$self{qw'curstash warnings hints hinthash'})
422 0         0 = @$self{qw'curstash warnings hints hinthash'};
423 0         0 my @ops;
424 0 0       0 return if B::Deparse::null $op->first; # Can happen, e.g., for Bytecode without -k
425 0         0 for (my $kid = $op->first->sibling; !B::Deparse::null($kid); $kid = $kid->sibling) {
426 0         0 push @ops, $kid;
427             }
428             my $fn = sub {
429 0     0   0 my ($exprs, $i, $info, $parent) = @_;
430 0         0 my $text = $info->{text};
431 0         0 my $op = $ops[$i];
432 0         0 $text =~ s/\f//;
433 0         0 $text =~ s/\n$//;
434 0         0 $text =~ s/;\n?\z//;
435 0         0 $text =~ s/^\((.+)\)$/$1/;
436 0         0 $info->{type} = $op->name;
437 0         0 $info->{op} = $op;
438              
439             # FIXME: this is going away...
440 0         0 $self->{optree}{$$op} = $info;
441             # in favor of...
442 0         0 $self->{ops}{$$op}{info} = $info;
443              
444 0         0 $info->{text} = $text;
445 0 0       0 $info->{parent} = $$parent if $parent;
446 0         0 push @$exprs, $info;
447 0         0 };
448 0         0 my $info = $self->walk_lineseq($op, \@ops, $fn);
449 0         0 my @skipped_ops;
450 0 0       0 if (exists $info->{other_ops}) {
451 0         0 @skipped_ops = @{$info->{other_ops}};
  0         0  
452 0         0 push @skipped_ops, $op->first;
453             } else {
454 0         0 @skipped_ops = ($op->first);
455             }
456 0         0 $info->{other_ops} = \@skipped_ops;
457 0         0 return $info;
458              
459             }
460              
461             sub update_node($$$$)
462             {
463 5531     5531 0 9028 my ($self, $node, $prev_expr, $op) = @_;
464 5531         7790 $node->{prev_expr} = $prev_expr;
465 5531 50       12551 $self->{optree}{$$op} = $node if $op;
466 5531 50       12907 $self->{ops}{$$op}{info} = $node if $op;
467             }
468              
469             sub walk_lineseq
470             {
471 1352     1352 0 2982 my ($self, $op, $kids, $callback) = @_;
472 1352         2729 my @kids = @$kids;
473 1352         2246 my @body = (); # Accumulated node structures
474 1352         1576 my $expr;
475 1352         1773 my $prev_expr = undef;
476 1352         1647 my $fix_cop = undef;
477 1352         2846 for (my $i = 0; $i < @kids; $i++) {
478 2090 100       13003 if (B::Deparse::is_state $kids[$i]) {
479 2089         5099 $expr = ($self->deparse($kids[$i], 0, $op));
480 2089         5590 $callback->(\@body, $i, $expr, $op);
481 2089         5740 $self->update_node($expr, $prev_expr, $op);
482 2089         2771 $prev_expr = $expr;
483 2089 50       3685 if ($fix_cop) {
484 0         0 $fix_cop->{text} = $expr->{text};
485             }
486              
487 2089         2335 $i++;
488 2089 50       4391 if ($i > $#kids) {
489 0         0 last;
490             }
491             }
492 2090 50       36186 if (B::Deparse::is_for_loop($kids[$i])) {
493 0         0 my $loop_expr = $self->for_loop($kids[$i], 0);
494 0 0       0 $callback->(\@body,
495             $i += $kids[$i]->sibling->name eq "unstack" ? 2 : 1,
496             $loop_expr);
497 0         0 $self->update_node($expr, $prev_expr, $op);
498 0         0 $prev_expr = $expr;
499 0         0 next;
500             }
501 2090         7416 $expr = $self->deparse($kids[$i], (@kids != 1)/2, $op);
502              
503             # Perform semantic action on $expr accumulating the result
504             # in @body. $op is the parent, and $i is the child position
505 2090         5423 $callback->(\@body, $i, $expr, $op);
506 2090         4929 $self->update_node($expr, $prev_expr, $op);
507 2090         2659 $prev_expr = $expr;
508 2090 50       3529 if ($fix_cop) {
509 0         0 $fix_cop->{text} = $expr->{text};
510             }
511              
512             # If the text portion of a COP is empty, set up to fill it in
513             # from the text portion of the next node.
514 2090 50 33     17082 if (B::class($op) eq "COP" && !$expr->{text}) {
515 0         0 $fix_cop = $op;
516             } else {
517 2090         5891 $fix_cop = undef;
518             }
519             }
520              
521             # Add semicolons between statements. Don't null statements
522             # (which can happen for nexstate which doesn't have source code
523             # associated with it.
524 1352         5004 $expr = $self->info_from_template("statements", $op, "%;", [], \@body);
525 1352         3733 $self->update_node($expr, $prev_expr, $op);
526 1352         11898 return $expr;
527             }
528              
529             # $root should be the op which represents the root of whatever
530             # we're sequencing here. If it's undefined, then we don't append
531             # any subroutine declarations to the deparsed ops, otherwise we
532             # append appropriate declarations.
533             sub lineseq {
534 1352     1352 0 3748 my($self, $root, $cx, @ops) = @_;
535              
536 1352         2660 my $out_cop = $self->{'curcop'};
537 1352 100       2535 my $out_seq = defined($out_cop) ? $out_cop->cop_seq : undef;
538 1352         1569 my $limit_seq;
539 1352 50       2870 if (defined $root) {
540 1352         1822 $limit_seq = $out_seq;
541 1352         1569 my $nseq;
542 1352 50       1660 $nseq = $self->find_scope_st($root->sibling) if ${$root->sibling};
  1352         5606  
543 1352 100 33     4776 $limit_seq = $nseq if !defined($limit_seq)
      66        
544             or defined($nseq) && $nseq < $limit_seq;
545             }
546             $limit_seq = $self->{'limit_seq'}
547             if defined($self->{'limit_seq'})
548 1352 0 0     3215 && (!defined($limit_seq) || $self->{'limit_seq'} < $limit_seq);
      33        
549 1352         2731 local $self->{'limit_seq'} = $limit_seq;
550              
551             my $fn = sub {
552 4179     4179   6884 my ($exprs, $i, $info, $parent) = @_;
553 4179         5621 my $op = $ops[$i];
554 4179 50       7158 $info->{type} = $op->name unless $info->{type};
555 4179         6175 $info->{child_pos} = $i;
556 4179         5463 $info->{op} = $op;
557 4179 50       6552 if ($parent) {
558 4179 50       7312 Carp::confess("nonref parent, op: $op->name") if !ref($parent);
559 4179         6116 $info->{parent} = $$parent ;
560             }
561              
562             # FIXME: remove optree?
563 4179         6088 $self->{optree}{$$op} = $info;
564 4179         8881 $self->{ops}{$$op}{info} = $info;
565              
566 4179         7805 push @$exprs, $info;
567 1352         6868 };
568 1352         4309 return $self->walk_lineseq($root, \@ops, $fn);
569             }
570              
571             sub todo
572             {
573 0     0 0 0 my $self = shift;
574 0         0 my($cv, $is_form, $name) = @_;
575 0   0     0 my $cvfile = $cv->FILE//'';
576 0 0 0     0 return unless ($cvfile eq $0 || exists $self->{files}{$cvfile});
577 0         0 my $seq;
578 0 0 0     0 if ($cv->OUTSIDE_SEQ) {
    0          
579 0         0 $seq = $cv->OUTSIDE_SEQ;
580             } elsif (!B::Deparse::null($cv->START) and B::Deparse::is_state($cv->START)) {
581 0         0 $seq = $cv->START->cop_seq;
582             } else {
583 0         0 $seq = 0;
584             }
585 0         0 push @{$self->{'subs_todo'}}, [$seq, $cv, $is_form, $name];
  0         0  
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 12645     12645   19571 my ($self, $startop) = @_;
595              
596 12645 50       19369 return unless $$startop;
597 12645         14743 my ($op, $parent_op);
598              
599 12645         20831 for ($op = $startop; $$op; $op = $op->sibling) {
600 24880         61003 my $ppname = $op->name;
601              
602 24880   50     111071 $self->{ops}{$$op} ||= {};
603 24880         43850 $self->{ops}{$$op}{op} = $op;
604 24880         34372 $self->{ops}{$$op}{parent_op} = $startop;
605              
606             # pessimisations start here
607              
608 24880 100       35141 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 857         4949 $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 24880 100 66     106308 if (class($op) eq 'PMOP'
      100        
      66        
632             && ref($op->pmreplroot)
633 24         128 && ${$op->pmreplroot}
634             && $op->pmreplroot->isa( 'B::OP' ))
635             {
636 4         13 $self-> _pessimise_walk($op->pmreplroot);
637             }
638              
639 24880 100       120837 if ($op->flags & OPf_KIDS) {
640 11296         34376 $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 1466     1466   2963 my ($self, $startop, $visited) = @_;
653              
654 1466 100       3253 return unless $$startop;
655 1452 50       3440 return if $visited->{$$startop};
656 1452         2627 my $op;
657 1452         3071 for ($op = $startop; $$op; $op = $op->next) {
658 12847 100       24251 last if $visited->{$$op};
659 12744         19132 $visited->{$$op} = 1;
660              
661 12744   50     22168 $self->{ops}{$$op} ||= {};
662 12744         18187 $self->{ops}{$$op}{op} = $op;
663              
664 12744         29349 my $ppname = $op->name;
665 12744 100       71755 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 100         396 $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 3         13 $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 1345     1345 0 2653 my ($self, $root, $start) = @_;
694              
695 3     3   21 no warnings 'recursion';
  3         18  
  3         5178  
696             # walk tree in root-to-branch order
697 1345         4113 $self->_pessimise_walk($root);
698              
699 1345         2333 my %visited;
700             # walk tree in execution order
701 1345         3557 $self->_pessimise_walk_exe($start, \%visited);
702             }
703              
704             sub print_protos {
705 0     0 0 0 my $self = shift;
706 0         0 my $ar;
707             my @ret;
708 0         0 foreach $ar (@{$self->{'protos_todo'}}) {
  0         0  
709 0 0       0 my $proto = defined $ar->[1]
    0          
710             ? ref $ar->[1]
711             ? " () {\n " . $self->const($ar->[1]->RV,0) . ";\n}"
712             : " (". $ar->[1] . ");"
713             : ";";
714 0         0 push @ret, "sub " . $ar->[0] . "$proto\n";
715             }
716 0         0 delete $self->{'protos_todo'};
717 0         0 return @ret;
718             }
719              
720             sub style_opts
721             {
722 0     0 0 0 my ($self, $opts) = @_;
723 0         0 my $opt;
724 0         0 while (length($opt = substr($opts, 0, 1))) {
725 0 0       0 if ($opt eq "C") {
    0          
    0          
    0          
726 0         0 $self->{'cuddle'} = " ";
727 0         0 $opts = substr($opts, 1);
728             } elsif ($opt eq "i") {
729 0         0 $opts =~ s/^i(\d+)//;
730 0         0 $self->{'indent_size'} = $1;
731             } elsif ($opt eq "T") {
732 0         0 $self->{'use_tabs'} = 1;
733 0         0 $opts = substr($opts, 1);
734             } elsif ($opt eq "v") {
735 0         0 $opts =~ s/^v([^.]*)(.|$)//;
736 0         0 $self->{'ex_const'} = $1;
737             }
738             }
739             }
740              
741             # This gets called automatically when option:
742             # -MO="DeparseTree,sC" is added
743             # Running this prints out the program text.
744             sub compile {
745 0     0 0 0 my(@args) = @_;
746             return sub {
747 0     0   0 my $self = B::DeparseTree->new(@args);
748             # First deparse command-line args
749 0 0       0 if (defined $^I) { # deparse -i
750 0         0 print q(BEGIN { $^I = ).perlstring($^I).qq(; }\n);
751             }
752 0 0       0 if ($^W) { # deparse -w
753 0         0 print qq(BEGIN { \$^W = $^W; }\n);
754             }
755 0 0 0     0 if ($/ ne "\n" or defined $O::savebackslash) { # deparse -l and -0
756 0   0     0 my $fs = perlstring($/) || 'undef';
757 0   0     0 my $bs = perlstring($O::savebackslash) || 'undef';
758 0         0 print qq(BEGIN { \$/ = $fs; \$\\ = $bs; }\n);
759             }
760 0 0       0 my @BEGINs = B::begin_av->isa("B::AV") ? B::begin_av->ARRAY : ();
761 0 0       0 my @UNITCHECKs = B::unitcheck_av->isa("B::AV")
762             ? B::unitcheck_av->ARRAY
763             : ();
764 0 0       0 my @CHECKs = B::check_av->isa("B::AV") ? B::check_av->ARRAY : ();
765 0 0       0 my @INITs = B::init_av->isa("B::AV") ? B::init_av->ARRAY : ();
766 0 0       0 my @ENDs = B::end_av->isa("B::AV") ? B::end_av->ARRAY : ();
767 0 0       0 if ($] < 5.020) {
768 0         0 for my $block (@BEGINs, @UNITCHECKs, @CHECKs, @INITs, @ENDs) {
769 0         0 $self->todo($block, 0);
770             }
771             } else {
772 0         0 my @names = qw(BEGIN UNITCHECK CHECK INIT END);
773 0         0 my @blocks = (\@BEGINs, \@UNITCHECKs, \@CHECKs, \@INITs, \@ENDs);
774 0         0 while (@names) {
775 0         0 my ($name, $blocks) = (shift @names, shift @blocks);
776 0         0 for my $block (@$blocks) {
777 0         0 $self->todo($block, 0, $name);
778             }
779             }
780             }
781 0         0 $self->stash_subs();
782             local($SIG{"__DIE__"}) =
783             sub {
784 0 0       0 if ($self->{'curcop'}) {
785 0         0 my $cop = $self->{'curcop'};
786 0         0 my($line, $file) = ($cop->line, $cop->file);
787 0         0 print STDERR "While deparsing $file near line $line,\n";
788             }
789 3     3   1918 use Data::Printer;
  3         100435  
  3         17  
790 0         0 my @bt = caller(1);
791 0         0 p @bt;
792 0         0 };
793 0         0 $self->{'curcv'} = main_cv;
794 0         0 $self->{'curcvlex'} = undef;
795 0         0 print $self->print_protos;
796 0         0 @{$self->{'subs_todo'}} =
797 0         0 sort {$a->[0] <=> $b->[0]} @{$self->{'subs_todo'}};
  0         0  
  0         0  
798 0         0 my $root = main_root;
799 0         0 local $B::overlay = {};
800              
801 0 0       0 if ($] < 5.021) {
802 0 0       0 unless (B::Deparse::null $root) {
803 0         0 $self->pessimise($root, main_start);
804             # Print deparsed program
805 0         0 print $self->deparse_root($root)->{text}, "\n";
806             }
807             } else {
808 0 0       0 unless (B::Deparse::null $root) {
809 0         0 $self->B::Deparse::pad_subs($self->{'curcv'});
810             # Check for a stub-followed-by-ex-cop, resulting from a program
811             # consisting solely of sub declarations. For backward-compati-
812             # bility (and sane output) we don’t want to emit the stub.
813             # leave
814             # enter
815             # stub
816             # ex-nextstate (or ex-dbstate)
817 0         0 my $kid;
818 0 0 0     0 if ( $root->name eq 'leave'
      0        
      0        
      0        
      0        
      0        
      0        
819             and ($kid = $root->first)->name eq 'enter'
820             and !B::Deparse::null($kid = $kid->sibling) and $kid->name eq 'stub'
821             and !B::Deparse::null($kid = $kid->sibling) and $kid->name eq 'null'
822             and class($kid) eq 'COP' and B::Deparse::null $kid->sibling )
823             {
824             # ignore deparsing routine
825             } else {
826 0         0 $self->pessimise($root, main_start);
827             # Print deparsed program
828 0         0 my $root_tree = $self->deparse_root($root);
829 0         0 print $root_tree->{text}, "\n";
830             }
831             }
832             }
833 0         0 my @text;
834 0         0 while (scalar(@{$self->{'subs_todo'}})) {
  0         0  
835 0         0 push @text, $self->next_todo->{text};
836             }
837 0 0       0 print join("", @text), "\n" if @text;
838              
839             # Print __DATA__ section, if necessary
840 3     3   1132 no strict 'refs';
  3         7  
  3         8251  
841             my $laststash = defined $self->{'curcop'}
842 0 0       0 ? $self->{'curcop'}->stash->NAME : $self->{'curstash'};
843 0 0       0 if (defined *{$laststash."::DATA"}{IO}) {
  0         0  
844             print $self->keyword("package") . " $laststash;\n"
845 0 0       0 unless $laststash eq $self->{'curstash'};
846 0         0 print $self->keyword("__DATA__") . "\n";
847 0         0 print readline(*{$laststash."::DATA"});
  0         0  
848             }
849             }
850 0         0 }
851              
852             # "deparse()" is the main function to call to produces a depare tree
853             # for a give B::OP. This method is the inner loop.
854              
855             # Rocky's comment with respect to:
856             # so try to keep it simple
857             #
858             # Most normal Perl programs really aren't that big. Yeah, I know there
859             # are a couple of big pigs like the B::Deparse code itself. The perl5
860             # debugger comes to mind too. But what's the likelihood of anyone wanting
861             # to decompile all of this?
862             #
863             # On the other hand, error checking is too valuable to throw out here.
864             # Also, in trying to use and modularize this code, I see there is
865             # a lot of repetition in subroutine parsing routines. That's
866             # why I added the above PP_MAPFNS table. I'm not going to trade off
867             # table lookup and interpetation for a huge amount of subroutine
868             # bloat.
869              
870             # That said it is useful to note that this is inner-most loop
871             # interpeter loop as it is called for each node in the B::OP tree.
872             #
873             sub deparse
874             {
875 17231     17231 0 30024 my($self, $op, $cx, $parent) = @_;
876              
877 17231 50       45256 Carp::confess("deparse called on an invalid op $op")
878             unless $op->can('name');
879              
880 17231         48533 my $name = $op->name;
881 17231 50       33908 print "YYY $name\n" if $ENV{'DEBUG_DEPARSETREE'};
882 17231         20448 my ($info, $meth);
883              
884 17231 100       29040 if (exists($PP_MAPFNS{$name})) {
885             # Interpret method calls for our PP_MAPFNS table
886 2564 100       4969 if (ref($PP_MAPFNS{$name}) eq 'ARRAY') {
887 150         240 my @args = @{$PP_MAPFNS{$name}};
  150         454  
888 150         289 $meth = shift @args;
889 150 100       320 if ($meth eq 'maybe_targmy') {
890             # FIXME: This is an inline version of targmy.
891             # Can we dedup it? do we want to?
892 67         111 $meth = shift @args;
893 67 100       201 unshift @args, $name unless @args;
894 67 100       309 if ($op->private & OPpTARGET_MY) {
895 4         87 my $var = $self->padname($op->targ);
896 4         32 my $val = $self->$meth($op, 7, @args);
897 4         18 my @texts = ($var, '=', $val);
898 4         35 $info = $self->info_from_template("my", $op,
899             "%c = %c", [0, 1],
900             [$var, $val],
901             {maybe_parens => [$self, $cx, 7]});
902             } else {
903 63         324 $info = $self->$meth($op, $cx, @args);
904             }
905             } else {
906 83         331 $info = $self->$meth($op, $cx, @args);
907             }
908             } else {
909             # Simple case: one simple call of the
910             # the method in the table. Call this
911             # passing arguments $op, $cx, and $name.
912             # Some functions might not use these,
913             # but that's okay.
914 2414         3830 $meth = $PP_MAPFNS{$name};
915 2414         8276 $info = $self->$meth($op, $cx, $name);
916             }
917             } else {
918             # Tried and true fallback method:
919             # a method has been defined for this pp_op special.
920             # call that.
921 14667         18954 $meth = "pp_" . $name;
922 14667         39377 $info = $self->$meth($op, $cx);
923             }
924              
925 17231 50       33010 Carp::confess("nonref return for $meth deparse: $info") if !ref($info);
926 17231 50       49308 Carp::confess("not B::DeparseTree:Node returned for $meth: $info")
927             if !$info->isa("B::DeparseTree::Node");
928 17231 100       38204 $info->{parent} = $$parent if $parent;
929 17231         28372 $info->{cop} = $self->{'curcop'};
930 17231         21980 my $got_op = $info->{op};
931 17231 100       26188 if ($got_op) {
932 17158 100       32776 if ($got_op != $op) {
933             # Do something here?
934             # printf("XX final op 0x%x is not requested 0x%x\n",
935             # $$op, $$got_op);
936             }
937             } else {
938 73         105 $info->{op} = $op;
939             }
940 17231         47330 $self->{optree}{$$op} = $info;
941 17231 100       27522 if ($info->{other_ops}) {
942 4133         4745 foreach my $other (@{$info->{other_ops}}) {
  4133         7306  
943 8733 50       23797 if (!ref $other) {
    100          
944 0         0 Carp::confess "$meth returns invalid other $other";
945             } elsif ($other->isa("B::DeparseTree::Node")) {
946             # "$other" has been set up to mark a particular portion
947             # of the info.
948 5364         9520 $self->{optree}{$other->{addr}} = $other;
949 5364         9373 $other->{parent} = $$op;
950             } else {
951             # "$other" is just the OP. Have it mark everything
952             # or "info".
953 3369         8239 $self->{optree}{$$other} = $info;
954             }
955             }
956             }
957 17231         37017 return $info;
958             }
959              
960             # Deparse a subroutine
961             sub deparse_sub($$$$)
962             {
963 1345     1345 0 2731 my ($self, $cv, $start_op) = @_;
964              
965             # Sanity checks..
966 1345 50 33     9037 Carp::confess("NULL in deparse_sub") if !defined($cv) || $cv->isa("B::NULL");
967 1345 50       4567 Carp::confess("SPECIAL in deparse_sub") if $cv->isa("B::SPECIAL");
968              
969             # First get protype and sub attribute information
970 1345         3497 local $self->{'curcop'} = $self->{'curcop'};
971 1345         1963 my $proto = '';
972 1345 50       4473 if ($cv->FLAGS & SVf_POK) {
973 0         0 $proto .= "(". $cv->PV . ")";
974             }
975 1345 50       4457 if ($cv->CvFLAGS & (CVf_METHOD|CVf_LOCKED|CVf_LVALUE)) {
976 0         0 $proto .= ":";
977 0 0       0 $proto .= " lvalue" if $cv->CvFLAGS & CVf_LVALUE;
978 0 0       0 $proto .= " locked" if $cv->CvFLAGS & CVf_LOCKED;
979 0 0       0 $proto .= " method" if $cv->CvFLAGS & CVf_METHOD;
980             }
981              
982 1345         3222 local($self->{'curcv'}) = $cv;
983 1345         2707 local($self->{'curcvlex'});
984             local(@$self{qw'curstash warnings hints hinthash'})
985 1345         5627 = @$self{qw'curstash warnings hints hinthash'};
986              
987             # Now deparse subroutine body
988              
989 1345         4164 my $root = $cv->ROOT;
990 1345         2335 my ($body, $node);
991              
992 1345         2676 local $B::overlay = {};
993 1345 50       13346 if (not B::Deparse::null $root) {
994 1345         6360 $self->pessimise($root, $cv->START);
995 1345         5514 my $lineseq = $root->first;
996 1345 50       4988 if ($lineseq->name eq "lineseq") {
    0          
997 1345         1947 my @ops;
998 1345         5665 for(my $o=$lineseq->first; $$o; $o=$o->sibling) {
999 4162         13536 push @ops, $o;
1000             }
1001 1345         4119 $body = $self->lineseq($root, 0, @ops);
1002 1345         30877 my $scope_en = $self->find_scope_en($lineseq);
1003             }
1004             elsif ($start_op) {
1005 0         0 $body = $self->deparse($start_op, 0, $root);
1006             } else {
1007 0         0 $body = $self->deparse($root->first, 0, $root);
1008             }
1009              
1010 1345         7074 my $fn_name = $cv->GV->NAME;
1011 1345         7006 $node = $self->info_from_template("sub $fn_name$proto",
1012             $root,
1013             "$proto\n%|{\n%+%c\n%-}",
1014             [0], [$body]);
1015              
1016 1345         6127 $self->{optree}{$$lineseq} = $node;
1017              
1018             } else {
1019 0         0 my $sv = $cv->const_sv;
1020 0 0       0 if ($$sv) {
1021             # uh-oh. inlinable sub... format it differently
1022 0         0 $node = $self->info_from_template('inline sub', $sv,
1023             "$proto\n%|{\n%+%c\n%-}",
1024             [0], [$self->const($sv, 0)]);
1025             } else {
1026             # XSUB? (or just a declaration)
1027 0         0 $node = $self->info_from_string("XSUB or sub declaration", $proto);
1028             }
1029             }
1030              
1031              
1032             # Add additional DeparseTree tracking info
1033 1345 50       3082 if ($start_op) {
1034 0         0 $node->{op} = $start_op;
1035 0         0 $self->{'optree'}{$$start_op} = $node;
1036             }
1037 1345         3130 $node->{cop} = undef;
1038 1345         2724 $node->{'parent'} = $cv;
1039 1345         26469 return $node;
1040             }
1041              
1042             # We have a TODO list of things that must be handled
1043             # at the top level. There are things like
1044             # format statements, "BEGIN" and "use" statements.
1045             # Here we handle the next one.
1046             sub next_todo
1047             {
1048 0     0 0 0 my ($self, $parent) = @_;
1049 0         0 my $ent = shift @{$self->{'subs_todo'}};
  0         0  
1050 0         0 my $cv = $ent->[1];
1051 0         0 my $gv = $cv->GV;
1052 0         0 my $name = $self->gv_name($gv);
1053 0 0       0 if ($ent->[2]) {
1054 0         0 my $node = $self->deparse_format($ent->[1], $cv);
1055 0         0 return $self->info_from_template("format $name",
1056             "format $name = %c",
1057             undef, [$node])
1058             } else {
1059 0         0 my ($fmt, $type);
1060 0         0 $self->{'subs_declared'}{$name} = 1;
1061 0 0       0 if ($name eq "BEGIN") {
1062 0         0 my $use_dec = $self->begin_is_use($cv);
1063 0 0 0     0 if (defined ($use_dec) and $self->{'expand'} < 5) {
1064 0 0       0 if (0 == length($use_dec)) {
1065 0         0 $self->info_from_string('BEGIN', $cv, '');
1066             } else {
1067 0         0 $self->info_from_string('use', $cv, $use_dec);
1068             }
1069             }
1070             }
1071 0         0 my $l = '';
1072 0 0       0 if ($self->{'linenums'}) {
1073 0         0 my $line = $gv->LINE;
1074 0         0 my $file = $gv->FILE;
1075 0         0 $l = "\n# line $line \"$file\"\n";
1076             }
1077 0 0       0 if (class($cv->STASH) ne "SPECIAL") {
1078 0         0 my $stash = $cv->STASH->NAME;
1079 0 0       0 if ($stash ne $self->{'curstash'}) {
1080 0         0 $fmt = "package $stash;\n";
1081 0         0 $type = "package $stash";
1082 0 0       0 $name = "$self->{'curstash'}::$name" unless $name =~ /::/;
1083 0         0 $self->{'curstash'} = $stash;
1084             }
1085 0         0 $name =~ s/^\Q$stash\E::(?!\z|.*::)//;
1086 0         0 $fmt .= "sub $name";
1087 0         0 $type .= "sub $name";
1088             }
1089 0         0 my $node = $self->deparse_sub($cv, $parent);
1090 0         0 $fmt .= '%c';
1091 0         0 return $self->info_from_template($type, $cv, $fmt, [0], [$node]);
1092             }
1093             }
1094              
1095             # Deparse a subroutine by name
1096             sub deparse_subname($$)
1097             {
1098 0     0 0 0 my ($self, $funcname) = @_;
1099 0         0 my $cv = svref_2object(\&$funcname);
1100 0         0 my $info = $self->deparse_sub($cv);
1101 0         0 return $self->info_from_template("sub $funcname", $cv, "sub $funcname %c",
1102             undef, [$info]);
1103             }
1104              
1105             # Return a list of info nodes for "use" and "no" pragmas.
1106             sub declare_hints
1107             {
1108 1337     1337 0 3144 my ($self, $from, $to) = @_;
1109 1337         2638 my $use = $to & ~$from;
1110 1337         2247 my $no = $from & ~$to;
1111              
1112 1337         1934 my @decls = ();
1113 1337         16870 for my $pragma (B::Deparse::hint_pragmas($use)) {
1114 1288         28361 my $type = $self->keyword("use") . " $pragma";
1115 1288         5969 push @decls, $self->info_from_template($type, undef, "$type", [], []);
1116             }
1117 1337         8735 for my $pragma (B::Deparse::hint_pragmas($no)) {
1118 0         0 my $type = $self->keyword("no") . " $pragma";
1119 0         0 push @decls, $self->info_from_template($type, undef, "$type", [], []);
1120             }
1121 1337         3978 return @decls;
1122             }
1123              
1124             # Internal implementation hints that the core sets automatically, so don't need
1125             # (or want) to be passed back to the user
1126             my %ignored_hints = (
1127             'open<' => 1,
1128             'open>' => 1,
1129             ':' => 1,
1130             'strict/refs' => 1,
1131             'strict/subs' => 1,
1132             'strict/vars' => 1,
1133             );
1134              
1135             my %rev_feature;
1136              
1137             sub declare_hinthash {
1138 2089     2089 0 4339 my ($self, $from, $to, $indent, $hints) = @_;
1139 2089         3483 my $doing_features =
1140             ($hints & $feature::hint_mask) == $feature::hint_mask;
1141 2089         4015 my @decls;
1142             my @features;
1143 2089         0 my @unfeatures; # bugs?
1144 2089         6157 for my $key (sort keys %$to) {
1145 67 50       149 next if $ignored_hints{$key};
1146 67   33     534 my $is_feature = $key =~ /^feature_/ && $^V ge 5.15.6;
1147 67 100 66     265 next if $is_feature and not $doing_features;
1148 54 100 66     195 if (!exists $from->{$key} or $from->{$key} ne $to->{$key}) {
1149 12 50       33 push(@features, $key), next if $is_feature;
1150             push @decls,
1151             qq(\$^H{) . single_delim($self, "q", "'", $key, "'") . qq(} = )
1152             . (
1153             defined $to->{$key}
1154 0 0       0 ? single_delim($self, "q", "'", $to->{$key}, "'")
1155             : 'undef'
1156             )
1157             . qq(;);
1158             }
1159             }
1160 2089         5096 for my $key (sort keys %$from) {
1161 56 50       112 next if $ignored_hints{$key};
1162 56   33     382 my $is_feature = $key =~ /^feature_/ && $^V ge 5.15.6;
1163 56 100 66     219 next if $is_feature and not $doing_features;
1164 42 50       85 if (!exists $to->{$key}) {
1165 0 0       0 push(@unfeatures, $key), next if $is_feature;
1166 0         0 push @decls, qq(delete \$^H{'$key'};);
1167             }
1168             }
1169 2089         2671 my @ret;
1170 2089 100 66     7837 if (@features || @unfeatures) {
1171 3 100       9 if (!%rev_feature) { %rev_feature = reverse %feature::feature }
  1         20  
1172             }
1173 2089 100       4320 if (@features) {
1174 3         1349 push @ret, $self->keyword("use") . " feature "
1175             . join(", ", map "'$rev_feature{$_}'", @features) . ";\n";
1176             }
1177 2089 50       3960 if (@unfeatures) {
1178 0         0 push @ret, $self->keyword("no") . " feature "
1179             . join(", ", map "'$rev_feature{$_}'", @unfeatures)
1180             . ";\n";
1181             }
1182             @decls and
1183 2089 50       3861 push @ret,
1184             join("\n" . (" " x $indent), "BEGIN {", @decls) . "\n}\n";
1185 2089         5387 return @ret;
1186             }
1187              
1188             # generate any pragmas, 'package foo' etc needed to synchronise
1189             # with the given cop
1190              
1191             sub pragmata {
1192 0     0 0 0 my $self = shift;
1193 0         0 my($op) = @_;
1194              
1195 0         0 my @text;
1196              
1197 0         0 my $stash = $op->stashpv;
1198 0 0       0 if ($stash ne $self->{'curstash'}) {
1199 0         0 push @text, $self->keyword("package") . " $stash;\n";
1200 0         0 $self->{'curstash'} = $stash;
1201             }
1202              
1203 0         0 if (OPpCONST_ARYBASE && $self->{'arybase'} != $op->arybase) {
1204             push @text, '$[ = '. $op->arybase .";\n";
1205             $self->{'arybase'} = $op->arybase;
1206             }
1207              
1208 0         0 my $warnings = $op->warnings;
1209 0         0 my $warning_bits;
1210 0 0 0     0 if ($warnings->isa("B::SPECIAL") && $$warnings == 4) {
    0 0        
    0          
1211 0         0 $warning_bits = $warnings::Bits{"all"} & WARN_MASK;
1212             }
1213             elsif ($warnings->isa("B::SPECIAL") && $$warnings == 5) {
1214 0         0 $warning_bits = $warnings::NONE;
1215             }
1216             elsif ($warnings->isa("B::SPECIAL")) {
1217 0         0 $warning_bits = undef;
1218             }
1219             else {
1220 0         0 $warning_bits = $warnings->PV & WARN_MASK;
1221             }
1222              
1223 0 0 0     0 if (defined ($warning_bits) and
      0        
1224             !defined($self->{warnings}) || $self->{'warnings'} ne $warning_bits) {
1225             push @text,
1226 0         0 $self->declare_warnings($self->{'warnings'}, $warning_bits);
1227 0         0 $self->{'warnings'} = $warning_bits;
1228             }
1229              
1230 0 0       0 my $hints = $] < 5.008009 ? $op->private : $op->hints;
1231 0         0 my $old_hints = $self->{'hints'};
1232 0 0       0 if ($self->{'hints'} != $hints) {
1233 0         0 push @text, $self->declare_hints($self->{'hints'}, $hints);
1234 0         0 $self->{'hints'} = $hints;
1235             }
1236              
1237 0         0 my $newhh;
1238 0 0       0 if ($] > 5.009) {
1239 0         0 $newhh = $op->hints_hash->HASH;
1240             }
1241              
1242 0 0       0 if ($] >= 5.015006) {
1243             # feature bundle hints
1244 0         0 my $from = $old_hints & $feature::hint_mask;
1245 0         0 my $to = $ hints & $feature::hint_mask;
1246 0 0       0 if ($from != $to) {
1247 0 0       0 if ($to == $feature::hint_mask) {
1248 0 0       0 if ($self->{'hinthash'}) {
1249             delete $self->{'hinthash'}{$_}
1250 0         0 for grep /^feature_/, keys %{$self->{'hinthash'}};
  0         0  
1251             }
1252 0         0 else { $self->{'hinthash'} = {} }
1253             $self->{'hinthash'}
1254 0         0 = _features_from_bundle($from, $self->{'hinthash'});
1255             }
1256             else {
1257 0         0 my $bundle =
1258             $feature::hint_bundles[$to >> $feature::hint_shift];
1259 0         0 $bundle =~ s/(\d[13579])\z/$1+1/e; # 5.11 => 5.12
  0         0  
1260 0         0 push @text,
1261             $self->keyword("no") . " feature ':all';\n",
1262             $self->keyword("use") . " feature ':$bundle';\n";
1263             }
1264             }
1265             }
1266              
1267 0 0       0 if ($] > 5.009) {
1268             push @text, $self->declare_hinthash(
1269             $self->{'hinthash'}, $newhh,
1270             $self->{indent_size}, $self->{hints},
1271 0         0 );
1272 0         0 $self->{'hinthash'} = $newhh;
1273             }
1274              
1275 0         0 return join("", @text);
1276             }
1277              
1278              
1279             # Create a "use", "no", or "BEGIN" block to set warnings.
1280             sub declare_warnings
1281             {
1282 1288     1288 0 2914 my ($self, $from, $to) = @_;
1283 1288 100       2941 if (($to & WARN_MASK) eq (warnings::bits("all") & WARN_MASK)) {
    50          
1284 2         1010 my $type = $self->keyword("use") . " warnings";
1285 2         31 return $self->info_from_template($type, undef, "$type;\n",
1286             [], []);
1287             }
1288             elsif (($to & WARN_MASK) eq ("\0"x length($to) & WARN_MASK)) {
1289 1286         27511 my $type = $self->keyword("no") . " warnings";
1290 1286         6138 return $self->info_from_template($type, undef, "$type;\n",
1291             [], []);
1292             }
1293 0         0 my $bit_expr = join('', map { sprintf("\\x%02x", ord $_) } split "", $to);
  0         0  
1294 0         0 my $str = "BEGIN {\n%+\${^WARNING_BITS} = \"$bit_expr;\n%-";
1295 0         0 return $self->info_from_template('warning bits begin', undef,
1296             "%|$str\n", [], [], {omit_next_semicolon=>1});
1297             }
1298              
1299             # Iterate over $self->{subs_todo} picking up the
1300             # text of of $self->next_todo.
1301             # We return an array of strings. The calling
1302             # routine will join these together
1303             sub seq_subs {
1304 2089     2089 0 4167 my ($self, $seq) = @_;
1305 2089         2497 my @texts;
1306              
1307 2089 50       3900 return () if !defined $seq;
1308 2089         2801 my @pending;
1309 2089   33     2631 while (scalar(@{$self->{'subs_todo'}})
  2089         6070  
1310             and $seq > $self->{'subs_todo'}[0][0]) {
1311 0         0 my $cv = $self->{'subs_todo'}[0][1];
1312             # Skip the OUTSIDE check for lexical subs. We may be deparsing a
1313             # cloned anon sub with lexical subs declared in it, in which case
1314             # the OUTSIDE pointer points to the anon protosub.
1315 0         0 my $lexical = ref $self->{'subs_todo'}[0][3];
1316 0   0     0 my $outside = !$lexical && $cv && $cv->OUTSIDE;
1317 0 0 0     0 if (!$lexical and $cv
      0        
1318 0 0       0 and ${$cv->OUTSIDE || \0} != ${$self->{'curcv'}})
  0         0  
1319             {
1320             # rocky: What do we do with @pending?
1321 0         0 push @pending, shift @{$self->{'subs_todo'}};
  0         0  
1322 0         0 next;
1323             }
1324 0         0 push @texts, $self->next_todo;
1325             }
1326 2089         5299 return @texts;
1327             }
1328              
1329             # FIXME: this code has to be here. Find out why and fix.
1330             # Truncate is special because OPf_SPECIAL makes a bareword first arg
1331             # be a filehandle. This could probably be better fixed in the core
1332             # by moving the GV lookup into ck_truc.
1333              
1334             # Demo code
1335             unless(caller) {
1336             my @texts = ('a', 'b', 'c');
1337             my $deparse = __PACKAGE__->new();
1338             my $info = info_from_list('op', $deparse, \@texts, ', ', 'test', {});
1339              
1340 3     3   27 use Data::Printer;
  3         6  
  3         11  
1341             my $str = $deparse->template_engine("%c", [0], ["16"]);
1342             p $str;
1343             my $str2 = $deparse->template_engine("%F", [[0, sub {'0x' . sprintf "%x", shift}]], [$str]);
1344             p $str2;
1345              
1346             # print $deparse->template_engine("100%% "), "\n";
1347             # print $deparse->template_engine("%c,\n%+%c\n%|%c %c!",
1348             # [1, 0, 2, 3],
1349             # ["is", "now", "the", "time"]), "\n";
1350              
1351             # $info = $deparse->info_from_template("demo", undef, "%C",
1352             # [[0, 1, ";\n%|"]],
1353             # ['$x=1', '$y=2']);
1354              
1355             # @texts = ("use warnings;", "use strict", "my(\$a)");
1356             # $info = $deparse->info_from_template("demo", undef, "%;", [], \@texts);
1357              
1358             # $info = $deparse->info_from_template("list", undef,
1359             # "%C", [[0, $#texts, ', ']],
1360             # \@texts);
1361              
1362             # p $info;
1363              
1364              
1365             # @texts = (['a', 1], ['b', 2], 'c');
1366             # $info = info_from_list('op', $deparse, \@texts, ', ', 'test', {});
1367             # p $info;
1368             }
1369              
1370             1;